Ejemplo n.º 1
0
        /// <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, HandshakePassphrase, Compression);

                HandshakeMessage handshake = new HandshakeMessage();
                if (handshake.Initialize(udpServer.ReceiveBuffer, udpServer.ReceiveBufferOffset, udpServer.ReceiveBufferLength) != -1)
                {
                    // Received handshake message could be parsed successfully.
                    if (handshake.ID != Guid.Empty && handshake.Passphrase == HandshakePassphrase)
                    {
                        // Create a random socket and connect it to the client.
                        TransportProvider<Socket> udpClient = new TransportProvider<Socket>();
                        udpClient.ReceiveBuffer = new byte[ReceiveBufferSize];
                        udpClient.Passphrase = HandshakePassphrase;
                        udpClient.Provider = Transport.CreateSocket(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.Passphrase = Cipher.GenerateKey(260);
                            handshake.Passphrase = udpClient.Passphrase;
                        }

                        // 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, HandshakePassphrase, 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);
                        ReceiveHandshakeAsync(udpServer);

                        try
                        {
                            ReceivePayloadOneAsync(udpClient);
                        }
                        catch
                        {
                            // Receive will fail if client disconnected before handshake is complete.
                            TerminateConnection(udpClient, true);
                        }
                    }
                    else
                    {
                        // Authentication during handshake failed, so we terminate the client connection.
                        TerminateConnection(udpServer, false);
                        OnHandshakeProcessUnsuccessful();
                    }
                }
                else
                {
                    // Handshake message could not be parsed, so we terminate the client connection.
                    TerminateConnection(udpServer, false);
                    OnHandshakeProcessUnsuccessful();
                }
            }
            catch
            {
                // Server socket has been terminated.
                udpServer.Reset();
                OnServerStopped();
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Callback method for asynchronous receive operation of handshake data.
        /// </summary>
        private void ReceiveHandshakeAsyncCallback(IAsyncResult asyncResult)
        {
            TransportProvider<Socket> udpClient = (TransportProvider<Socket>)asyncResult.AsyncState;
            if (!asyncResult.IsCompleted)
            {
                // Handshake response is not recevied in a timely fashion.
                TerminateConnection(udpClient, false);
                OnHandshakeProcessTimeout();
            }
            else
            {
                // Received handshake response from server so we'll process it.
                try
                {
                    // Update statistics and pointers.
                    udpClient.Statistics.UpdateBytesReceived(udpClient.Provider.EndReceiveFrom(asyncResult, ref m_udpServer));
                    udpClient.ReceiveBufferLength = udpClient.Statistics.LastBytesReceived;

                    // Process the received handshake response message.
                    Payload.ProcessReceived(ref udpClient.ReceiveBuffer, ref udpClient.ReceiveBufferOffset, ref udpClient.ReceiveBufferLength, Encryption, HandshakePassphrase, Compression);

                    HandshakeMessage handshake = new HandshakeMessage();
                    if (handshake.Initialize(udpClient.ReceiveBuffer, udpClient.ReceiveBufferOffset, udpClient.ReceiveBufferLength) != -1)
                    {
                        // Received handshake response message could be parsed.
                        this.ServerID = handshake.ID;
                        udpClient.Passphrase = handshake.Passphrase;

                        // Client is now considered to be connected to the server.
                        OnConnectionEstablished();
                        ReceivePayloadAsync(udpClient);
                    }
                    else
                    {
                        // Received handshake response message could not be parsed.
                        TerminateConnection(udpClient, false);
                        OnHandshakeProcessUnsuccessful();
                    }
                }
                catch
                {
                    // This is most likely because the server forcibly disconnected the client.
                    TerminateConnection(udpClient, false);
                    OnHandshakeProcessUnsuccessful();
                }
            }
        }
Ejemplo n.º 3
0
        /// <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, HandshakePassphrase, 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 && handshake.Passphrase == HandshakePassphrase)
                        {
                            // Authentication is successful; respond to the handshake.
                            tcpClient.ID = handshake.ID;
                            handshake.ID = this.ServerID;
                            if (SecureSession)
                            {
                                // Create a secret key for ciphering client data.
                                tcpClient.Passphrase = Cipher.GenerateKey(260);
                                handshake.Passphrase = tcpClient.Passphrase;
                            }

                            // 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, HandshakePassphrase, 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();
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Connects the <see cref="UdpClient"/> to the server asynchronously.
        /// </summary>
        /// <exception cref="FormatException">Server property in <see cref="ClientBase.ConnectionString"/> is invalid.</exception>
        /// <exception cref="InvalidOperationException">Attempt is made to connect the <see cref="UdpClient"/> when it is not disconnected.</exception>
        public override void ConnectAsync()
        {
            if (CurrentState == ClientState.Disconnected)
            {
                // Initialize if unitialized.
                Initialize();

                m_udpClient = new TransportProvider<Socket>();
                m_udpClient.ID = this.ClientID;
                m_udpClient.Passphrase = HandshakePassphrase;
                m_udpClient.ReceiveBuffer = new byte[ReceiveBufferSize];
                
                // Create a server endpoint.
                if (m_connectData.ContainsKey("server"))
                {
                    // Client has a server endpoint specified.
                    string[] parts = m_connectData["server"].Split(':');
                    if (parts.Length == 2)
                    {
                        m_udpServer = Transport.CreateEndPoint(parts[0], int.Parse(parts[1]));
                    }
                    else
                    {
                        throw new FormatException(string.Format("Server property in ConnectionString is invalid. Example: {0}.", DefaultConnectionString));
                    }
                }
                else
                {
                    if (Handshake)
                        throw new InvalidOperationException("Handshake requires Server property in the ConnectionString.");

                    // Create a random server endpoint since one is not specified.
                    m_udpServer = Transport.CreateEndPoint(string.Empty, 0);
                }

                if (Handshake)
                {
                    // Handshaking must be performed. 
                    m_receivedGoodbye = DoGoodbyeCheck;
                    HandshakeMessage handshake = new HandshakeMessage();
                    handshake.ID = this.ClientID;
                    handshake.Passphrase = this.HandshakePassphrase;

                    // Prepare binary image of handshake to be transmitted.
                    m_udpClient.Provider = Transport.CreateSocket(0, ProtocolType.Udp);
                    m_udpClient.SendBuffer = handshake.BinaryImage;
                    m_udpClient.SendBufferOffset = 0;
                    m_udpClient.SendBufferLength = m_udpClient.SendBuffer.Length;
                    Payload.ProcessTransmit(ref m_udpClient.SendBuffer, ref m_udpClient.SendBufferOffset, ref m_udpClient.SendBufferLength, Encryption, HandshakePassphrase, Compression);

                    // Initialiate handshake process from a seperate thread.
                    new Thread((ThreadStart)delegate()
                    {
                        int connectionAttempts = 0;
                        while (true)
                        {
                            try
                            {
                                connectionAttempts++;
                                OnConnectionAttempt();

                                // Transmit the prepared and processed handshake message.
                                m_udpClient.Provider.SendTo(m_udpClient.SendBuffer, m_udpServer);

                                // Wait for the server's reponse to the handshake message.
                                Thread.Sleep(1000);
                                ReceiveHandshakeAsync(m_udpClient);
                                break;
                            }
                            catch (SocketException ex)
                            {
                                OnConnectionException(ex);
                                if (ex.SocketErrorCode == SocketError.ConnectionReset && 
                                    (MaxConnectionAttempts == -1 || connectionAttempts < MaxConnectionAttempts))
                                {
                                    // Server is unavailable, so keep retrying connection to the server.                                  
                                    continue;
                                }
                                else
                                {
                                    // For any other reason, clean-up as if the client was disconnected.
                                    TerminateConnection(m_udpClient, false);
                                    break;
                                }
                            }
                            catch (Exception ex)
                            {
                                // This is highly unlikely, but we must handle this situation just-in-case.
                                OnConnectionException(ex);
                                TerminateConnection(m_udpClient, false);
                                break;
                            }
                        }
                    }).Start();
                }
                else
                {
                    // Disable SocketError.ConnectionReset exception from being thrown when the enpoint is not listening.
                    m_udpClient.Provider = Transport.CreateSocket(int.Parse(m_connectData["port"]), ProtocolType.Udp);
                    m_udpClient.Provider.IOControl(SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);

                    OnConnectionAttempt();
                    m_receivedGoodbye = NoGoodbyeCheck;
                    OnConnectionEstablished();
                    ReceivePayloadAsync(m_udpClient);
                }
            }
            else
            {
                throw new InvalidOperationException("Client is currently not disconnected.");
            }
        }