diff --git a/SteamKit2/SteamKit2/Steam3/CMClient.cs b/SteamKit2/SteamKit2/Steam3/CMClient.cs
index f566351f..413e22e2 100644
--- a/SteamKit2/SteamKit2/Steam3/CMClient.cs
+++ b/SteamKit2/SteamKit2/Steam3/CMClient.cs
@@ -10,6 +10,8 @@ using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
+using System.Collections.ObjectModel;
+using System.Linq;
namespace SteamKit2.Internal
{
@@ -18,60 +20,10 @@ namespace SteamKit2.Internal
///
public abstract class CMClient
{
- const ushort PortCM_PublicEncrypted = 27017;
- const ushort PortCM_Public = 27014;
-
///
/// Bootstrap list of CM servers.
///
- public static readonly IPEndPoint[] Servers =
- {
- // Qwest, Seattle
- new IPEndPoint( IPAddress.Parse( "72.165.61.174" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "72.165.61.174" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "72.165.61.175" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "72.165.61.175" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "72.165.61.176" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "72.165.61.176" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "72.165.61.185" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "72.165.61.185" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "72.165.61.187" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "72.165.61.187" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "72.165.61.188" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "72.165.61.188" ), 27018 ),
- // Inteliquent, Luxembourg, cm-[01-04].lux.valve.net
- new IPEndPoint( IPAddress.Parse( "146.66.152.12" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "146.66.152.12" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "146.66.152.12" ), 27019 ),
- new IPEndPoint( IPAddress.Parse( "146.66.152.13" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "146.66.152.13" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "146.66.152.13" ), 27019 ),
- new IPEndPoint( IPAddress.Parse( "146.66.152.14" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "146.66.152.14" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "146.66.152.14" ), 27019 ),
- new IPEndPoint( IPAddress.Parse( "146.66.152.15" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "146.66.152.15" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "146.66.152.15" ), 27019 ),
- /* Highwinds, Netherlands (not live)
- new IPEndPoint( IPAddress.Parse( "81.171.115.5" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "81.171.115.5" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "81.171.115.5" ), 27019 ),
- new IPEndPoint( IPAddress.Parse( "81.171.115.6" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "81.171.115.6" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "81.171.115.6" ), 27019 ),
- new IPEndPoint( IPAddress.Parse( "81.171.115.7" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "81.171.115.7" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "81.171.115.7" ), 27019 ),
- new IPEndPoint( IPAddress.Parse( "81.171.115.8" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "81.171.115.8" ), 27018 ),
- new IPEndPoint( IPAddress.Parse( "81.171.115.8" ), 27019 ),*/
- // Highwinds, Kaysville
- new IPEndPoint( IPAddress.Parse( "209.197.29.196" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "209.197.29.197" ), 27017 ),
- /* Starhub, Singapore (non-optimal route)
- new IPEndPoint( IPAddress.Parse( "103.28.54.10" ), 27017 ),
- new IPEndPoint( IPAddress.Parse( "103.28.54.11" ), 27017 )*/
- };
+ public static ReadOnlyCollection Servers { get; private set; }
///
/// Returns the the local IP of this client.
@@ -102,16 +54,76 @@ namespace SteamKit2.Internal
/// The SteamID.
public SteamID SteamID { get; private set; }
+ ///
+ /// Gets or sets the connection timeout used when connecting to the Steam server.
+ /// The default value is 5 seconds.
+ ///
+ ///
+ /// The connection timeout.
+ ///
+ public TimeSpan ConnectionTimeout { get; set; }
+
Connection connection;
byte[] tempSessionKey;
- bool encrypted;
ScheduledFunction heartBeatFunc;
Dictionary> serverMap;
+ static CMClient()
+ {
+ Servers = new ReadOnlyCollection( new List
+ {
+ // Qwest, Seattle
+ new IPEndPoint( IPAddress.Parse( "72.165.61.174" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "72.165.61.174" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "72.165.61.175" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "72.165.61.175" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "72.165.61.176" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "72.165.61.176" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "72.165.61.185" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "72.165.61.185" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "72.165.61.187" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "72.165.61.187" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "72.165.61.188" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "72.165.61.188" ), 27018 ),
+ // Inteliquent, Luxembourg, cm-[01-04].lux.valve.net
+ new IPEndPoint( IPAddress.Parse( "146.66.152.12" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "146.66.152.12" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "146.66.152.12" ), 27019 ),
+ new IPEndPoint( IPAddress.Parse( "146.66.152.13" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "146.66.152.13" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "146.66.152.13" ), 27019 ),
+ new IPEndPoint( IPAddress.Parse( "146.66.152.14" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "146.66.152.14" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "146.66.152.14" ), 27019 ),
+ new IPEndPoint( IPAddress.Parse( "146.66.152.15" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "146.66.152.15" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "146.66.152.15" ), 27019 ),
+ /* Highwinds, Netherlands (not live)
+ new IPEndPoint( IPAddress.Parse( "81.171.115.5" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "81.171.115.5" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "81.171.115.5" ), 27019 ),
+ new IPEndPoint( IPAddress.Parse( "81.171.115.6" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "81.171.115.6" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "81.171.115.6" ), 27019 ),
+ new IPEndPoint( IPAddress.Parse( "81.171.115.7" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "81.171.115.7" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "81.171.115.7" ), 27019 ),
+ new IPEndPoint( IPAddress.Parse( "81.171.115.8" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "81.171.115.8" ), 27018 ),
+ new IPEndPoint( IPAddress.Parse( "81.171.115.8" ), 27019 ),*/
+ // Highwinds, Kaysville
+ new IPEndPoint( IPAddress.Parse( "209.197.29.196" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "209.197.29.197" ), 27017 ),
+ /* Starhub, Singapore (non-optimal route)
+ new IPEndPoint( IPAddress.Parse( "103.28.54.10" ), 27017 ),
+ new IPEndPoint( IPAddress.Parse( "103.28.54.11" ), 27017 )*/
+ } );
+ }
+
///
/// Initializes a new instance of the class with a specific connection type.
///
@@ -124,6 +136,9 @@ namespace SteamKit2.Internal
{
serverMap = new Dictionary>();
+ // our default timeout
+ ConnectionTimeout = TimeSpan.FromSeconds( 5 );
+
switch ( type )
{
case ProtocolType.Tcp:
@@ -140,7 +155,7 @@ namespace SteamKit2.Internal
connection.NetMsgReceived += NetMsgReceived;
connection.Disconnected += Disconnected;
- connection.Connected += Connected;
+
heartBeatFunc = new ScheduledFunction( () =>
{
Send( new ClientMsgProtobuf( EMsg.ClientHeartBeat ) );
@@ -156,38 +171,21 @@ namespace SteamKit2.Internal
/// SteamKit will not attempt to reconnect to Steam, you must handle this callback and call Connect again
/// preferrably after a short delay.
///
- public void Connect()
- {
- encrypted = true;
-
- Random random = new Random();
- var server = Servers[ random.Next( Servers.Length ) ];
-
- connection.Connect( server );
- }
-
- ///
- /// Connects this client to the specified Steam3 server.
- /// This begins the process of connecting and encrypting the data channel between the client and the server.
- /// Results are returned asynchronously in a .
- /// If the server that SteamKit attempts to connect to is down, a
- /// will be posted instead.
- /// SteamKit will not attempt to reconnect to Steam, you must handle this callback and call Connect again
- /// preferrably after a short delay.
- ///
- /// The of the CM server to connect to.
- ///
- /// If set to true the underlying connection to Steam will be encrypted. This is the default mode of communication.
- /// Previous versions of SteamKit always used encryption.
+ ///
+ /// The of the CM server to connect to.
+ /// If null, SteamKit will randomly select a CM server from its internal list.
///
- public void Connect( IPAddress cmServer, bool bEncrypted = true )
+ public void Connect( IPEndPoint cmServer = null )
{
this.Disconnect();
- encrypted = bEncrypted;
- var endPoint = new IPEndPoint( cmServer, bEncrypted ? PortCM_PublicEncrypted : PortCM_Public );
+ if ( cmServer == null )
+ {
+ Random random = new Random();
+ cmServer = Servers[ random.Next( Servers.Count ) ];
+ }
- connection.Connect( endPoint );
+ connection.Connect( cmServer, ConnectionTimeout.Milliseconds );
}
///
@@ -281,6 +279,10 @@ namespace SteamKit2.Internal
case EMsg.ClientServerList: // Steam server list
HandleServerList( packetMsg );
break;
+
+ case EMsg.ClientCMList:
+ HandleCMList( packetMsg );
+ break;
}
}
///
@@ -298,19 +300,6 @@ namespace SteamKit2.Internal
OnClientMsgReceived( GetPacketMsg( e.Data ) );
}
- void Connected( object sender, EventArgs e )
- {
- // If we're on an encrypted connection, we wait for the handshake to complete
- if ( encrypted )
- return;
-
- // we only connect to the public universe
- ConnectedUniverse = EUniverse.Public;
-
- // since there is no encryption handshake, we're 'connected' after the underlying connection is established
- OnClientConnected();
- }
-
void Disconnected( object sender, EventArgs e )
{
ConnectedUniverse = EUniverse.Invalid;
@@ -482,6 +471,17 @@ namespace SteamKit2.Internal
endpointList.Add( new IPEndPoint( NetHelpers.GetIPAddress( server.server_ip ), ( int )server.server_port ) );
}
}
+ void HandleCMList( IPacketMsg packetMsg )
+ {
+ var cmMsg = new ClientMsgProtobuf( packetMsg );
+ DebugLog.Assert( cmMsg.Body.cm_addresses.Count == cmMsg.Body.cm_ports.Count, "CMClient", "HandleCMList received malformed message" );
+
+ var cmList = cmMsg.Body.cm_addresses
+ .Zip( cmMsg.Body.cm_ports, ( addr, port ) => new IPEndPoint( NetHelpers.GetIPAddress( addr ), ( int )port ) );
+
+ // update our bootstrap list with steam's list of CMs
+ Servers = new ReadOnlyCollection( cmList.ToList() );
+ }
#endregion
}
}