/// <summary> /// Callback method for asynchronous receive operation of handshake data. /// </summary> private void ReceiveHandshakeAsyncCallback(IAsyncResult asyncResult) { TransportProvider<Socket> tcpClient = (TransportProvider<Socket>)asyncResult.AsyncState; if (!asyncResult.IsCompleted) { // Handshake didn't complete in a timely fashion. TerminateConnection(tcpClient, false); OnHandshakeProcessTimeout(); } else { // Received handshake data from client so we'll process it. try { // Update statistics and pointers. tcpClient.Statistics.UpdateBytesReceived(tcpClient.Provider.EndReceive(asyncResult)); tcpClient.ReceiveBufferLength = tcpClient.Statistics.LastBytesReceived; if (tcpClient.Statistics.LastBytesReceived == 0) // Client disconnected gracefully. throw new SocketException((int)SocketError.Disconnecting); // Process the received handshake message. Payload.ProcessReceived(ref tcpClient.ReceiveBuffer, ref tcpClient.ReceiveBufferOffset, ref tcpClient.ReceiveBufferLength, Encryption, SharedSecret, Compression); HandshakeMessage handshake = new HandshakeMessage(); if (handshake.Initialize(tcpClient.ReceiveBuffer, tcpClient.ReceiveBufferOffset, tcpClient.ReceiveBufferLength) != -1) { // Received handshake message could be parsed successfully. if (handshake.ID != Guid.Empty) { // Send respond to the handshake message. tcpClient.ID = handshake.ID; handshake.ID = this.ServerID; if (SecureSession) { // Create a secret key for ciphering client data. tcpClient.Secretkey = Cipher.GenerateKey(260); handshake.Secretkey = tcpClient.Secretkey; } // Prepare binary image of handshake response to be transmitted. tcpClient.SendBuffer = handshake.BinaryImage; tcpClient.SendBufferOffset = 0; tcpClient.SendBufferLength = tcpClient.SendBuffer.Length; Payload.ProcessTransmit(ref tcpClient.SendBuffer, ref tcpClient.SendBufferOffset, ref tcpClient.SendBufferLength, Encryption, SharedSecret, Compression); // Transmit the prepared and processed handshake response message. tcpClient.Provider.Send(tcpClient.SendBuffer); // Handshake process is complete and client is considered connected. lock (m_tcpClients) { m_tcpClients.Add(tcpClient.ID, tcpClient); } OnClientConnected(tcpClient.ID); ReceivePayloadAsync(tcpClient); } else { // Authentication during handshake failed, so we terminate the client connection. TerminateConnection(tcpClient, false); OnHandshakeProcessUnsuccessful(); } } else { // Handshake message could not be parsed, so we terminate the client connection. TerminateConnection(tcpClient, false); OnHandshakeProcessUnsuccessful(); } } catch { // Handshake process could not be completed most likely due to client disconnect. TerminateConnection(tcpClient, false); OnHandshakeProcessUnsuccessful(); } } }
/// <summary> /// Callback method for asynchronous receive operation of handshake response data. /// </summary> private void ReceiveHandshakeAsyncCallback(IAsyncResult asyncResult) { TransportProvider<Socket> tcpClient = (TransportProvider<Socket>)asyncResult.AsyncState; if (!asyncResult.IsCompleted) { // Handshake response is not recevied in a timely fashion. TerminateConnection(tcpClient, false); OnHandshakeProcessTimeout(); } else { // Received handshake response from server so we'll process it. try { // Update statistics and pointers. tcpClient.Statistics.UpdateBytesReceived(tcpClient.Provider.EndReceive(asyncResult)); tcpClient.ReceiveBufferLength = tcpClient.Statistics.LastBytesReceived; if (tcpClient.Statistics.LastBytesReceived == 0) // Client disconnected gracefully. throw new SocketException((int)SocketError.Disconnecting); // Process the received handshake response message. Payload.ProcessReceived(ref tcpClient.ReceiveBuffer, ref tcpClient.ReceiveBufferOffset, ref tcpClient.ReceiveBufferLength, Encryption, SharedSecret, Compression); HandshakeMessage handshake = new HandshakeMessage(); if (handshake.Initialize(tcpClient.ReceiveBuffer, tcpClient.ReceiveBufferOffset, tcpClient.ReceiveBufferLength) != -1) { // Received handshake response message could be parsed. this.ServerID = handshake.ID; tcpClient.Secretkey = handshake.Secretkey; // Client is now considered to be connected to the server. OnConnectionEstablished(); ReceivePayloadAsync(tcpClient); } else { // Received handshake response message could not be parsed. TerminateConnection(tcpClient, false); OnHandshakeProcessUnsuccessful(); } } catch { // This is most likely because the server forcibly disconnected the client. TerminateConnection(tcpClient, false); OnHandshakeProcessUnsuccessful(); } } }
/// <summary> /// Callback method for asynchronous receive operation of handshake data. /// </summary> private void ReceiveHandshakeAsyncCallback(IAsyncResult asyncResult) { TransportProvider<Socket> udpServer = (TransportProvider<Socket>)asyncResult.AsyncState; // Received handshake data from client so we'll process it. try { // Update statistics and pointers. EndPoint client = Transport.CreateEndPoint(string.Empty, 0); udpServer.Statistics.UpdateBytesReceived(udpServer.Provider.EndReceiveFrom(asyncResult, ref client)); udpServer.ReceiveBufferLength = udpServer.Statistics.LastBytesReceived; // Process the received handshake message. Payload.ProcessReceived(ref udpServer.ReceiveBuffer, ref udpServer.ReceiveBufferOffset, ref udpServer.ReceiveBufferLength, Encryption, SharedSecret, Compression); HandshakeMessage handshake = new HandshakeMessage(); if (handshake.Initialize(udpServer.ReceiveBuffer, udpServer.ReceiveBufferOffset, udpServer.ReceiveBufferLength) != -1) { // Received handshake message is parsed successfully. if (handshake.ID != Guid.Empty) { // Create a random socket and connect it to the client. TransportProvider<Socket> udpClient = new TransportProvider<Socket>(); udpClient.ReceiveBuffer = new byte[ReceiveBufferSize]; udpClient.Secretkey = SharedSecret; udpClient.Provider = Transport.CreateSocket(m_configData["interface"], 0, ProtocolType.Udp); udpClient.Provider.Connect(client); // Authentication is successful; respond to the handshake. udpClient.ID = handshake.ID; handshake.ID = this.ServerID; if (SecureSession) { // Create a secret key for ciphering client data. udpClient.Secretkey = Guid.NewGuid().ToString(); handshake.Secretkey = udpClient.Secretkey; } // Prepare binary image of handshake response to be transmitted. udpClient.SendBuffer = handshake.BinaryImage; udpClient.SendBufferOffset = 0; udpClient.SendBufferLength = udpClient.SendBuffer.Length; Payload.ProcessTransmit(ref udpClient.SendBuffer, ref udpClient.SendBufferOffset, ref udpClient.SendBufferLength, Encryption, SharedSecret, Compression); // Transmit the prepared and processed handshake response message. udpClient.Provider.SendTo(udpClient.SendBuffer, udpClient.Provider.RemoteEndPoint); // Handshake process is complete and client is considered connected. lock (m_udpClients) { m_udpClients.Add(udpClient.ID, udpClient); } OnClientConnected(udpClient.ID); try { ReceivePayloadOneAsync(udpClient); } catch { // Receive will fail if client disconnected before handshake is complete. TerminateConnection(udpClient, true); } } else { // Validation during handshake failed. OnHandshakeProcessUnsuccessful(); } } else { // Handshake message could not be parsed. OnHandshakeProcessUnsuccessful(); } // Resume receiving of client handshake messages. ReceiveHandshakeAsync(udpServer); } catch { // Server socket has been terminated. udpServer.Reset(); OnServerStopped(); } }
/// <summary> /// Callback method for asynchronous connect operation. /// </summary> private void ConnectAsyncCallback(IAsyncResult asyncResult) { TransportProvider<Socket> tcpClient = (TransportProvider<Socket>)asyncResult.AsyncState; try { // Perform post-connect operations. m_connectionAttempts++; tcpClient.Provider.EndConnect(asyncResult); tcpClient.ID = this.ClientID; tcpClient.Secretkey = SharedSecret; // We can proceed further with receiving data from the client. if (Handshake) { // Handshaking must be performed. HandshakeMessage handshake = new HandshakeMessage(); handshake.ID = this.ClientID; handshake.Secretkey = this.SharedSecret; // Prepare binary image of handshake to be transmitted. tcpClient.SendBuffer = handshake.BinaryImage; tcpClient.SendBufferOffset = 0; tcpClient.SendBufferLength = tcpClient.SendBuffer.Length; Payload.ProcessTransmit(ref tcpClient.SendBuffer, ref tcpClient.SendBufferOffset, ref tcpClient.SendBufferLength, Encryption, SharedSecret, Compression); // Transmit the prepared and processed handshake message. tcpClient.Provider.Send(tcpClient.SendBuffer); // Wait for the server's reponse to the handshake message. ReceiveHandshakeAsync(tcpClient); } else { // No handshaking to be performed. OnConnectionEstablished(); ReceivePayloadAsync(tcpClient); } } catch (SocketException ex) { OnConnectionException(ex); if (ex.SocketErrorCode == SocketError.ConnectionRefused && (MaxConnectionAttempts == -1 || m_connectionAttempts < MaxConnectionAttempts)) { // Server is unavailable, so keep retrying connection to the server. try { ConnectAsync(); } catch { TerminateConnection(tcpClient, false); } } else { // For any other reason, clean-up as if the client was disconnected. TerminateConnection(tcpClient, false); } } catch (Exception ex) { // This is highly unlikely, but we must handle this situation just-in-case. OnConnectionException(ex); TerminateConnection(tcpClient, false); } }