void OnDisconnected(object sender, DisconnectedEventArgs e) { state = EncryptionState.Disconnected; encryption = null; Disconnected?.Invoke(this, e); }
private void Release( bool userRequestedDisconnect ) { lock (netLock) { cancellationToken.Dispose(); cancellationToken = null; if (netWriter != null) { netWriter.Dispose(); netWriter = null; } if (netReader != null) { netReader.Dispose(); netReader = null; } if (netStream != null) { netStream.Dispose(); netStream = null; } socket.Close(); socket = null; netFilter = null; } OnDisconnected( new DisconnectedEventArgs( userRequestedDisconnect ) ); connectionFree.Set(); }
private void Release(bool userRequestedDisconnect) { lock (netLock) { cancellationToken.Dispose(); cancellationToken = null; if (netWriter != null) { netWriter.Dispose(); netWriter = null; } if (netReader != null) { netReader.Dispose(); netReader = null; } if (netStream != null) { netStream.Dispose(); netStream = null; } socket.Close(); socket = null; netFilter = null; } OnDisconnected(new DisconnectedEventArgs(userRequestedDisconnect)); connectionFree.Set(); }
public override void SetNetEncryptionFilter(INetFilterEncryption filter) { lock (netLock) { if (socket != null) { netFilter = filter; } } }
/// <summary> /// Connects this client to a 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 <see cref="SteamClient.ConnectedCallback"/>. /// If the server that SteamKit attempts to connect to is down, a <see cref="SteamClient.DisconnectedCallback"/> /// 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. /// </summary> /// <param name="cmServer"> /// The <see cref="IPEndPoint"/> of the CM server to connect to. /// If <c>null</c>, SteamKit will randomly select a CM server from its internal list. /// </param> public void Connect(IPEndPoint cmServer = null) { this.Disconnect(); encryptionSetup = false; pendingNetFilterEncryption = null; ExpectDisconnection = false; if (cmServer == null) { cmServer = Servers.GetNextServerCandidate(); } connection.Connect(cmServer, ( int )ConnectionTimeout.TotalMilliseconds); }
private void ConnectCompleted(bool success) { // Always discard result if our request was cancelled // If we have no cancellation token source, we were already Release()'ed if (cancellationToken?.IsCancellationRequested ?? true) { DebugLog.WriteLine("TcpConnection", "Connection request to {0} was cancelled", destination); if (success) { Shutdown(); } Release(userRequestedDisconnect: true); return; } else if (!success) { DebugLog.WriteLine("TcpConnection", "Timed out while connecting to {0}", destination); Release(userRequestedDisconnect: false); return; } DebugLog.WriteLine("TcpConnection", "Connected to {0}", destination); try { lock (netLock) { netStream = new NetworkStream(socket, false); netReader = new BinaryReader(netStream); netWriter = new BinaryWriter(netStream); netFilter = null; netThread = new Thread(NetLoop); netThread.Name = "TcpConnection Thread"; } netThread.Start(); OnConnected(EventArgs.Empty); } catch (Exception ex) { DebugLog.WriteLine("TcpConnection", "Exception while setting up connection to {0}: {1}", destination, ex); Release(userRequestedDisconnect: false); } }
/// <summary> /// Connects this client to a UFS server. /// This begins the process of connecting and encrypting the data channel between the client and the UFS server. /// Results are returned asynchronously in a <see cref="ConnectedCallback"/>. /// If the UFS server that this client attempts to connect to is down, a <see cref="DisconnectedCallback"/> will be posted instead. /// <see cref="UFSClient"/> will not attempt to reconnect to Steam, you must handle this callback and call <see cref="Connect"/> again, preferrably after a short delay. /// In order to connect to the UFS server, the parent <see cref="SteamClient"/> must be connected to the CM server. /// </summary> /// <param name="ufsServer"> /// The <see cref="System.Net.IPEndPoint"/> of the UFS server to connect to. /// If <c>null</c>, <see cref="UFSClient"/> will randomly select a UFS server from the <see cref="SteamClient"/>'s list of servers. /// </param> public void Connect(IPEndPoint ufsServer = null) { DebugLog.Assert(steamClient.IsConnected, "UFSClient", "CMClient is not connected!"); this.Disconnect(); pendingNetFilterEncryption = null; if (ufsServer == null) { var serverList = steamClient.GetServersOfType(EServerType.UFS); Random random = new Random(); ufsServer = serverList[random.Next(serverList.Count)]; } connection.Connect(ufsServer, ( int )ConnectionTimeout.TotalMilliseconds); }
void HandleEncryptResult(IPacketMsg packetMsg) { var encResult = new Msg <MsgChannelEncryptResult>(packetMsg); DebugLog.WriteLine("UFSClient", "Encryption result: {0}", encResult.Body.Result); if (encResult.Body.Result == EResult.OK && pendingNetFilterEncryption != null) { Debug.Assert(pendingNetFilterEncryption != null); connection.SetNetEncryptionFilter(pendingNetFilterEncryption); pendingNetFilterEncryption = null; steamClient.PostCallback(new ConnectedCallback(encResult.Body)); } else { DebugLog.WriteLine("UFSClient", "Encryption channel setup failed"); connection.Disconnect(); } }
/// <summary> /// Connects this client to a 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 <see cref="SteamClient.ConnectedCallback"/>. /// If the server that SteamKit attempts to connect to is down, a <see cref="SteamClient.DisconnectedCallback"/> /// 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. /// </summary> /// <param name="cmServer"> /// The <see cref="IPEndPoint"/> of the CM server to connect to. /// If <c>null</c>, SteamKit will randomly select a CM server from its internal list. /// </param> public void Connect(IPEndPoint cmServer = null) { this.Disconnect(); encryptionSetup = false; pendingNetFilterEncryption = null; ExpectDisconnection = false; Task <IPEndPoint> epTask = null; if (cmServer == null) { epTask = Servers.GetNextServerCandidateAsync(); } else { epTask = Task.FromResult(cmServer); } connection.Connect(epTask, ( int )ConnectionTimeout.TotalMilliseconds); }
bool HandleEncryptResult(IPacketMsg packetMsg) { var encResult = new Msg <MsgChannelEncryptResult>(packetMsg); DebugLog.WriteLine("CMClient", "Encryption result: {0}", encResult.Body.Result); if (encResult.Body.Result == EResult.OK && pendingNetFilterEncryption != null) { Debug.Assert(pendingNetFilterEncryption != null); connection.SetNetEncryptionFilter(pendingNetFilterEncryption); pendingNetFilterEncryption = null; encryptionSetup = true; return(true); } else { DebugLog.WriteLine("CMClient", "Encryption channel setup failed"); connection.Disconnect(); return(false); } }
/// <summary> /// Connects to the specified CM server. /// </summary> /// <param name="endPointTask">Task returning the CM server.</param> /// <param name="timeout">Timeout in milliseconds</param> public override void Connect(Task <IPEndPoint> endPointTask, int timeout) { Disconnect(); outPackets = new List <UdpPacket>(); inPackets = new Dictionary <uint, UdpPacket>(); remoteEndPoint = null; remoteConnId = 0; outSeq = 1; outSeqSent = 0; outSeqAcked = 0; inSeq = 0; inSeqAcked = 0; inSeqHandled = 0; filter = null; netThread = new Thread(NetLoop); netThread.Name = "UdpConnection Thread"; netThread.Start(endPointTask); }
/// <summary> /// Sets the network encryption filter for this connection /// </summary> /// <param name="filter">filter implementing <see cref="INetFilterEncryption"/></param> public override void SetNetEncryptionFilter( INetFilterEncryption filter ) { this.filter = filter; }
void HandleEncryptResult( IPacketMsg packetMsg ) { var encResult = new Msg<MsgChannelEncryptResult>( packetMsg ); DebugLog.WriteLine( "UFSClient", "Encryption result: {0}", encResult.Body.Result ); if ( encResult.Body.Result == EResult.OK && pendingNetFilterEncryption != null ) { Debug.Assert( pendingNetFilterEncryption != null ); connection.SetNetEncryptionFilter( pendingNetFilterEncryption ); pendingNetFilterEncryption = null; steamClient.PostCallback( new ConnectedCallback( encResult.Body ) ); } else { DebugLog.WriteLine( "UFSClient", "Encryption channel setup failed" ); connection.Disconnect(); } }
bool HandleEncryptResult( IPacketMsg packetMsg ) { var encResult = new Msg<MsgChannelEncryptResult>( packetMsg ); DebugLog.WriteLine( "CMClient", "Encryption result: {0}", encResult.Body.Result ); if ( encResult.Body.Result == EResult.OK && pendingNetFilterEncryption != null ) { Debug.Assert( pendingNetFilterEncryption != null ); connection.SetNetEncryptionFilter( pendingNetFilterEncryption ); pendingNetFilterEncryption = null; encryptionSetup = true; return true; } else { DebugLog.WriteLine( "CMClient", "Encryption channel setup failed" ); connection.Disconnect(); return false; } }
/// <summary> /// Sets the network encryption filter for this connection /// </summary> /// <param name="filter">filter implementing <see cref="INetFilterEncryption"/></param> public abstract void SetNetEncryptionFilter(INetFilterEncryption filter);
void HandleEncryptRequest(IPacketMsg packetMsg) { var request = new Msg <MsgChannelEncryptRequest>(packetMsg); var connectedUniverse = request.Body.Universe; var protoVersion = request.Body.ProtocolVersion; DebugLog.WriteLine(nameof(EnvelopeEncryptedConnection), "Got encryption request. Universe: {0} Protocol ver: {1}", connectedUniverse, protoVersion); DebugLog.Assert(protoVersion == 1, nameof(EnvelopeEncryptedConnection), "Encryption handshake protocol version mismatch!"); DebugLog.Assert(connectedUniverse == universe, nameof(EnvelopeEncryptedConnection), FormattableString.Invariant($"Expected universe {universe} but server reported universe {connectedUniverse}")); byte[] randomChallenge; if (request.Payload.Length >= 16) { randomChallenge = request.Payload.ToArray(); } else { randomChallenge = null; } var publicKey = KeyDictionary.GetPublicKey(connectedUniverse); if (publicKey == null) { DebugLog.WriteLine(nameof(EnvelopeEncryptedConnection), "HandleEncryptRequest got request for invalid universe! Universe: {0} Protocol ver: {1}", connectedUniverse, protoVersion); Disconnect(); } var response = new Msg <MsgChannelEncryptResponse>(); var tempSessionKey = CryptoHelper.GenerateRandomBlock(32); byte[] encryptedHandshakeBlob = null; using (var rsa = new RSACrypto(publicKey)) { if (randomChallenge != null) { var blobToEncrypt = new byte[tempSessionKey.Length + randomChallenge.Length]; Array.Copy(tempSessionKey, blobToEncrypt, tempSessionKey.Length); Array.Copy(randomChallenge, 0, blobToEncrypt, tempSessionKey.Length, randomChallenge.Length); encryptedHandshakeBlob = rsa.Encrypt(blobToEncrypt); } else { encryptedHandshakeBlob = rsa.Encrypt(tempSessionKey); } } var keyCrc = CryptoHelper.CRCHash(encryptedHandshakeBlob); response.Write(encryptedHandshakeBlob); response.Write(keyCrc); response.Write(( uint )0); if (randomChallenge != null) { encryption = new NetFilterEncryptionWithHMAC(tempSessionKey); } else { encryption = new NetFilterEncryption(tempSessionKey); } state = EncryptionState.Challenged; Send(response.Serialize()); }
/// <summary> /// Sets the network encryption filter for this connection /// </summary> /// <param name="filter">filter implementing <see cref="INetFilterEncryption"/></param> public abstract void SetNetEncryptionFilter( INetFilterEncryption filter );
/// <summary> /// Sets the network encryption filter for this connection /// </summary> /// <param name="filter">filter implementing <see cref="INetFilterEncryption"/></param> public override void SetNetEncryptionFilter(INetFilterEncryption filter) { this.filter = filter; }
bool HandleEncryptRequest(IPacketMsg packetMsg) { var encRequest = new Msg <MsgChannelEncryptRequest>(packetMsg); EUniverse eUniv = encRequest.Body.Universe; uint protoVersion = encRequest.Body.ProtocolVersion; DebugLog.WriteLine("CMClient", "Got encryption request. Universe: {0} Protocol ver: {1}", eUniv, protoVersion); DebugLog.Assert(protoVersion == 1, "CMClient", "Encryption handshake protocol version mismatch!"); byte[] randomChallenge; if (encRequest.Payload.Length >= 16) { randomChallenge = encRequest.Payload.ToArray(); } else { randomChallenge = null; } byte[] pubKey = KeyDictionary.GetPublicKey(eUniv); if (pubKey == null) { connection.Disconnect(); DebugLog.WriteLine("CMClient", "HandleEncryptionRequest got request for invalid universe! Universe: {0} Protocol ver: {1}", eUniv, protoVersion); return(false); } ConnectedUniverse = eUniv; var encResp = new Msg <MsgChannelEncryptResponse>(); var tempSessionKey = CryptoHelper.GenerateRandomBlock(32); byte[] encryptedHandshakeBlob = null; using (var rsa = new RSACrypto(pubKey)) { if (randomChallenge != null) { var blobToEncrypt = new byte[tempSessionKey.Length + randomChallenge.Length]; Array.Copy(tempSessionKey, blobToEncrypt, tempSessionKey.Length); Array.Copy(randomChallenge, 0, blobToEncrypt, tempSessionKey.Length, randomChallenge.Length); encryptedHandshakeBlob = rsa.Encrypt(blobToEncrypt); } else { encryptedHandshakeBlob = rsa.Encrypt(tempSessionKey); } } var keyCrc = CryptoHelper.CRCHash(encryptedHandshakeBlob); encResp.Write(encryptedHandshakeBlob); encResp.Write(keyCrc); encResp.Write(( uint )0); if (randomChallenge != null) { pendingNetFilterEncryption = new NetFilterEncryptionWithHMAC(tempSessionKey); } else { pendingNetFilterEncryption = new NetFilterEncryption(tempSessionKey); } this.Send(encResp); return(true); }
/// <summary> /// Connects this client to a 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 <see cref="SteamClient.ConnectedCallback"/>. /// If the server that SteamKit attempts to connect to is down, a <see cref="SteamClient.DisconnectedCallback"/> /// 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. /// </summary> /// <param name="cmServer"> /// The <see cref="IPEndPoint"/> of the CM server to connect to. /// If <c>null</c>, SteamKit will randomly select a CM server from its internal list. /// </param> public void Connect( IPEndPoint cmServer = null ) { this.Disconnect(); encryptionSetup = false; pendingNetFilterEncryption = null; ExpectDisconnection = false; if ( cmServer == null ) { cmServer = Servers.GetNextServerCandidate(); } connection.Connect( cmServer, ( int )ConnectionTimeout.TotalMilliseconds ); }
/// <summary> /// Connects this client to a 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 <see cref="SteamClient.ConnectedCallback"/>. /// If the server that SteamKit attempts to connect to is down, a <see cref="SteamClient.DisconnectedCallback"/> /// 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. /// </summary> /// <param name="cmServer"> /// The <see cref="IPEndPoint"/> of the CM server to connect to. /// If <c>null</c>, SteamKit will randomly select a CM server from its internal list. /// </param> public void Connect( IPEndPoint cmServer = null ) { this.Disconnect(); encryptionSetup = false; pendingNetFilterEncryption = null; ExpectDisconnection = false; Task<IPEndPoint> epTask = null; if ( cmServer == null ) { epTask = Servers.GetNextServerCandidateAsync(); } else { epTask = Task.FromResult( cmServer ); } connection.Connect( epTask, ( int )ConnectionTimeout.TotalMilliseconds ); }
public override void SetNetEncryptionFilter( INetFilterEncryption filter ) { lock (netLock) { if (socket != null) { netFilter = filter; } } }
void HandleEncryptRequest( IPacketMsg packetMsg ) { var encRequest = new Msg<MsgChannelEncryptRequest>( packetMsg ); EUniverse eUniv = encRequest.Body.Universe; uint protoVersion = encRequest.Body.ProtocolVersion; DebugLog.WriteLine( "UFSClient", "Got encryption request. Universe: {0} Protocol ver: {1}", eUniv, protoVersion ); DebugLog.Assert( protoVersion == 1, "UFSClient", "Encryption handshake protocol version mismatch!" ); byte[] randomChallenge; if ( encRequest.Payload.Length >= 16 ) { randomChallenge = encRequest.Payload.ToArray(); } else { randomChallenge = null; } byte[] pubKey = KeyDictionary.GetPublicKey( eUniv ); if ( pubKey == null ) { connection.Disconnect(); DebugLog.WriteLine( "UFSClient", "HandleEncryptionRequest got request for invalid universe! Universe: {0} Protocol ver: {1}", eUniv, protoVersion ); return; } ConnectedUniverse = eUniv; var encResp = new Msg<MsgChannelEncryptResponse>(); var tempSessionKey = CryptoHelper.GenerateRandomBlock( 32 ); byte[] encryptedHandshakeBlob = null; using ( var rsa = new RSACrypto( pubKey ) ) { if ( randomChallenge != null ) { var blobToEncrypt = new byte[ tempSessionKey.Length + randomChallenge.Length ]; Array.Copy( tempSessionKey, blobToEncrypt, tempSessionKey.Length ); Array.Copy( randomChallenge, 0, blobToEncrypt, tempSessionKey.Length, randomChallenge.Length ); encryptedHandshakeBlob = rsa.Encrypt( blobToEncrypt ); } else { encryptedHandshakeBlob = rsa.Encrypt( tempSessionKey ); } } var keyCrc = CryptoHelper.CRCHash( encryptedHandshakeBlob ); encResp.Write( encryptedHandshakeBlob ); encResp.Write( keyCrc ); encResp.Write( ( uint )0 ); if ( randomChallenge != null ) { pendingNetFilterEncryption = new NetFilterEncryptionWithHMAC( tempSessionKey ); } else { pendingNetFilterEncryption = new NetFilterEncryption( tempSessionKey ); } this.Send( encResp ); }
private void ConnectCompleted(bool success) { // Always discard result if our request was cancelled if (cancellationToken.IsCancellationRequested) { DebugLog.WriteLine("TcpConnection", "Connection request to {0} was cancelled", destination); if (success) Shutdown(); Release( userRequestedDisconnect: true ); return; } else if (!success) { DebugLog.WriteLine("TcpConnection", "Timed out while connecting to {0}", destination); Release( userRequestedDisconnect: false ); return; } DebugLog.WriteLine("TcpConnection", "Connected to {0}", destination); try { lock (netLock) { netStream = new NetworkStream(socket, false); netReader = new BinaryReader(netStream); netWriter = new BinaryWriter(netStream); netFilter = null; netThread = new Thread(NetLoop); netThread.Name = "TcpConnection Thread"; } netThread.Start(); OnConnected(EventArgs.Empty); } catch (Exception ex) { DebugLog.WriteLine("TcpConnection", "Exception while setting up connection to {0}: {1}", destination, ex); Release( userRequestedDisconnect: false ); } }
/// <summary> /// Connects this client to a UFS server. /// This begins the process of connecting and encrypting the data channel between the client and the UFS server. /// Results are returned asynchronously in a <see cref="ConnectedCallback"/>. /// If the UFS server that this client attempts to connect to is down, a <see cref="DisconnectedCallback"/> will be posted instead. /// <see cref="UFSClient"/> will not attempt to reconnect to Steam, you must handle this callback and call <see cref="Connect"/> again, preferrably after a short delay. /// In order to connect to the UFS server, the parent <see cref="SteamClient"/> must be connected to the CM server. /// </summary> /// <param name="ufsServer"> /// The <see cref="System.Net.IPEndPoint"/> of the UFS server to connect to. /// If <c>null</c>, <see cref="UFSClient"/> will randomly select a UFS server from the <see cref="SteamClient"/>'s list of servers. /// </param> public void Connect( IPEndPoint ufsServer = null ) { DebugLog.Assert( steamClient.IsConnected, "UFSClient", "CMClient is not connected!" ); this.Disconnect(); pendingNetFilterEncryption = null; if ( ufsServer == null ) { var serverList = steamClient.GetServersOfType( EServerType.UFS ); Random random = new Random(); ufsServer = serverList[ random.Next( serverList.Count ) ]; } connection.Connect( ufsServer, ( int )ConnectionTimeout.TotalMilliseconds ); }
/// <summary> /// Connects to the specified CM server. /// </summary> /// <param name="endPointTask">Task returning the CM server.</param> /// <param name="timeout">Timeout in milliseconds</param> public override void Connect(Task<IPEndPoint> endPointTask, int timeout) { Disconnect(); outPackets = new List<UdpPacket>(); inPackets = new Dictionary<uint, UdpPacket>(); remoteEndPoint = null; remoteConnId = 0; outSeq = 1; outSeqSent = 0; outSeqAcked = 0; inSeq = 0; inSeqAcked = 0; inSeqHandled = 0; filter = null; netThread = new Thread(NetLoop); netThread.Name = "UdpConnection Thread"; netThread.Start(endPointTask); }