Esempio n. 1
0
        protected void NegotiateChannels(Connection.Tcp connection)
        {
            Message.Base msg;

            if (connection.Receive(out msg))
            {
                if (msg.IsType <Message.Negotiation.Start>())
                {
                    connection.Parameters.guid = Guid.NewGuid();

                    SaveMonitor(connection);

                    // Send a new Guid for these connections and the number of associated channels
                    Message.Negotiation.New n = new Message.Negotiation.New
                    {
                        guid       = connection.Parameters.guid,
                        nbChannels = (ushort)Math.Min(channels != null ? channels.Count : 0, ushort.MaxValue)
                    };

                    connection.Send(n);

                    if (n.nbChannels <= 0)
                    {
                        Drop(connection, "No channels configured.");
                    }

                    for (ushort i = 0; i < n.nbChannels; i++)
                    {
                        ServerChannel channel = channels[i];

                        Message.Negotiation.Parameters param = new Message.Negotiation.Parameters
                        {
                            guid          = n.guid,
                            channel       = i,
                            type          = channel.type,
                            heartbeat     = channel.parameters.Heartbeat,
                            autoReconnect = !channel.parameters.disableAutoReconnect
                        };

                        connection.Send(param);
                    }
                }
                else if (msg.IsType <Message.Negotiation.Channel.TCP>())
                {
                    Message.Negotiation.Channel.TCP tcp = (Message.Negotiation.Channel.TCP)msg;

                    connection.SetConfig(tcp.guid, tcp.channel, channels[tcp.channel].parameters.Heartbeat);

                    SaveChannel(connection);
                }
                else
                {
                    Drop(connection, "Unsupported negotiation command '{0}'.", msg.GetType());
                }
            }
            else
            {
                Drop(connection, "Expected to receive some negotiation command.");
            }
        }
Esempio n. 2
0
        protected void AcceptClient(IAsyncResult async_result)
        {
            try
            {
                if (state == State.RUNNING && listener != null && listener.Server != null && listener.Server.IsBound)
                {
                    Message.Negotiation.Parameters param = new Message.Negotiation.Parameters
                    {
                        guid          = Guid.Empty,
                        channel       = ushort.MaxValue,
                        heartbeat     = negotiation.parameters.Heartbeat,
                        autoReconnect = !negotiation.parameters.disableAutoReconnect
                    };

                    // Get the new connection
                    Connection.Tcp connection = new Connection.Tcp(this, param, DisconnectionHandler, listener.EndAcceptTcpClient(async_result));

                    lock (initializedConnections)
                    {
                        initializedConnections.Add(connection);
                    }

                    connection.initialization = Task.Run(() => Connected(connection));
                }
            }
            catch (ObjectDisposedException)
            {
                // Can happen rarely because the atomicity between IsBound and EndAcceptTcpClient is not verified. Therefore the
                // listener can be disposed in this time frame. In this case, we have nothing to do. Just exit to close cleanly the listener.
            }
            catch (Exception exception)
            {
                Debug.LogErrorFormat("{0}: {1}\n{2}", exception.GetType(), exception.Message, exception.StackTrace);
            }
        }
Esempio n. 3
0
        protected void ValidateCredentials(Connection.Tcp connection)
        {
            Message.Connection.Request request = new Message.Connection.Request
            {
                version  = connection.version,
                username = credentials.username,
                password = credentials.password
            };

            connection.Send(request);

            Message.Base v;

            if (connection.Receive(out v) && v.IsType <Message.Connection.Validation>())
            {
                Message.Connection.Validation validation = (Message.Connection.Validation)v;

                // Check if the sent credentials are OK
                if (validation.accepted)
                {
                    NegotiateChannels(connection);
                }
                else
                {
                    Drop(connection, "Invalid credentials.");
                }
            }
            else
            {
                Drop(connection, "Expected to receive credentials validation.");
            }
        }
Esempio n. 4
0
        protected void ConnectUdp(Connection.Tcp connection, Message.Negotiation.Parameters param)
        {
            UdpConnectionParams udp_params = SendUdpParams(connection, param);

            lock (pendingUdpConnection)
            {
                pendingUdpConnection.Add(udp_params);
            }
        }
Esempio n. 5
0
        protected void ValidateCredentials(Connection.Tcp connection)
        {
            Message.Base req;

            if (connection.Receive(out req) && req.IsType <Message.Connection.Request>())
            {
                Message.Connection.Request request = (Message.Connection.Request)req;

                connection.version = request.version;

                if (connection.version < maxSupportedVersion)
                {
                    Debug.LogWarningFormat("Client does not support protocol version '{0}'. Using version '{1}' instead.", maxSupportedVersion, connection.version);
                }

                Message.Connection.Validation validation = new Message.Connection.Validation();

                // Check if the credentials are valid
                if (request.username == credentials.username && request.password == credentials.password)
                {
                    validation.accepted = true;

                    // Notify the client that the credentials are valid
                    connection.Send(validation);

                    NegotiateChannels(connection);
                }
                else
                {
                    string error_message = string.Format("Invalid connection credentials for user '{0}'. Dropping connection.", request.username);

                    Debug.LogWarning(error_message);

                    validation.accepted = false;

                    // Notify the client that the credentials are wrong
                    connection.Send(validation);

                    // Drop the connection
                    Close(connection);

                    throw new DropException(error_message);
                }
            }
            else
            {
                Drop(connection, "Expected to receive negotiation connection request.");
            }
        }
Esempio n. 6
0
        protected void Connected(Connection.Tcp connection)
        {
            try
            {
                // We should be connected
                if (connection.client.Connected)
                {
                    // Get the stream associated with this connection
                    connection.stream = connection.client.GetStream();

                    Message.Connection.Parameters header = new Message.Connection.Parameters
                    {
                        version   = maxSupportedVersion,
                        encrypted = (serverCertificate != null)
                    };

                    // Send greating message with protocol version and parameters
                    connection.Send(header);

                    if (serverCertificate != null)
                    {
                        // Create the SSL wraping stream
                        connection.stream = new SslStream(connection.stream, false, new RemoteCertificateValidationCallback(
                                                              (sender, certificate, chain, sslPolicyErrors) => (sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) == SslPolicyErrors.RemoteCertificateNotAvailable
                                                              ), null, EncryptionPolicy.RequireEncryption);

                        // Authenticate with the client
                        ((SslStream)connection.stream).BeginAuthenticateAsServer(serverCertificate, Authenticated, connection);
                    }
                    else
                    {
                        // No encryption, the channel stay as is
                        ValidateCredentials(connection);
                    }
                }
                else
                {
                    Debug.LogError("The connection from the client failed.");
                }
            }
            catch (DropException)
            {
                throw;
            }
            catch (Exception exception)
            {
                Debug.LogErrorFormat("{0}: {1}\n{2}", exception.GetType(), exception.Message, exception.StackTrace);
            }
        }
Esempio n. 7
0
        protected void ConnectTcp(Message.Negotiation.Parameters param)
        {
            // Create a new TCP client
            Connection.Tcp connection = new Connection.Tcp(this, param, DisconnectionHandler, new TcpClient());

            if (param.guid != Guid.Empty)
            {
                lock (initializedConnections)
                {
                    initializedConnections.Add(connection);
                }
            }

            // Start asynchronous connection to server
            connection.initialization = Task.Run(() => connection.client.BeginConnect(hostname, port, Connected, connection));
        }
Esempio n. 8
0
        protected void Drop(Connection.Tcp connection, string message, params object[] values)
        {
            string error_message = string.Format(message, values);

            if (!error_message.EndsWith("."))
            {
                error_message += ".";
            }

            error_message += " Dropping connection.";

            Debug.LogError(error_message);

            Close(connection);

            throw new DropException(error_message);
        }
Esempio n. 9
0
        protected void Authenticated(IAsyncResult async_result)
        {
            try
            {
                // Finalize the authentication as client for the SSL stream
                Connection.Tcp connection = (Connection.Tcp)async_result.AsyncState;

                ((SslStream)connection.stream).EndAuthenticateAsClient(async_result);

                ValidateCredentials(connection);
            }
            catch (DropException)
            {
                throw;
            }
            catch (Exception)
            {
                Debug.LogError("Authentication failed");
            }
        }
Esempio n. 10
0
        protected void Authenticated(IAsyncResult async_result)
        {
            Connection.Tcp connection = null;

            try
            {
                // Finalize the authentication as server for the SSL stream
                connection = (Connection.Tcp)async_result.AsyncState;

                ((SslStream)connection.stream).EndAuthenticateAsServer(async_result);

                ValidateCredentials(connection);
            }
            catch (DropException)
            {
                throw;
            }
            catch (Exception)
            {
                Drop(connection, "Authentication failed.");
            }
        }
Esempio n. 11
0
        protected void NegotiateChannels(Connection.Tcp connection)
        {
            // Check if we must negotiate other channel or just open the current one
            if (connection.Remote == Guid.Empty)
            {
                connection.Send(new Message.Negotiation.Start());

                Message.Base msg;

                if (connection.Receive(out msg) && msg.IsType <Message.Negotiation.New>())
                {
                    Message.Negotiation.New n = (Message.Negotiation.New)msg;

                    connection.Parameters.guid = n.guid;

                    ushort nb_channels = n.nbChannels;

                    if (nb_channels > 0)
                    {
                        List <Message.Negotiation.Parameters> parameters = new List <Message.Negotiation.Parameters>(nb_channels);

                        for (ushort i = 0; i < nb_channels; i++)
                        {
                            if (connection.Receive(out msg) && msg.IsType <Message.Negotiation.Parameters>())
                            {
                                Message.Negotiation.Parameters param = (Message.Negotiation.Parameters)msg;

                                parameters.Add(param);
                            }
                            else
                            {
                                Drop(connection, "Expected to receive channel parameterts for channel {0}.", i);
                            }
                        }

                        SaveMonitor(connection);

                        foreach (Message.Negotiation.Parameters param in parameters)
                        {
                            if (!Ready(param.guid, param.channel))
                            {
                                switch (param.type)
                                {
                                case Channel.Type.TCP:
                                    ConnectTcp(param);
                                    break;

                                case Channel.Type.UDP:
                                    ConnectUdp(connection, param);
                                    break;
                                }
                            }
                        }

                        state = State.RUNNING;
                    }
                    else
                    {
                        Drop(connection, "No channels configured.");
                    }
                }
                else
                {
                    Drop(connection, "Expected to receive the new connection negotiation parameters.");
                }
            }
            else
            {
                Message.Negotiation.Channel.TCP tcp = new Message.Negotiation.Channel.TCP
                {
                    guid    = connection.Remote,
                    channel = connection.Channel
                };

                connection.Send(tcp);

                SaveChannel(connection);
            }
        }
Esempio n. 12
0
        protected void Connected(IAsyncResult async_result)
        {
            try
            {
                // Finalize connection to server
                Connection.Tcp connection = (Connection.Tcp)async_result.AsyncState;

                connection.client.EndConnect(async_result);

                // We should be connected
                if (connection.client.Connected)
                {
                    // Get the stream associated with this connection
                    connection.stream = connection.client.GetStream();

                    Message.Base h;

                    if (connection.Receive(out h) && h.IsType <Message.Connection.Parameters>())
                    {
                        Message.Connection.Parameters header = (Message.Connection.Parameters)h;

                        connection.version = header.version;

                        if (connection.version > maxSupportedVersion)
                        {
                            Debug.LogWarningFormat("Usupported protocol version '{0}'. Using version '{1}' instead.", connection.version, maxSupportedVersion);

                            connection.version = maxSupportedVersion;
                        }

                        if (header.encrypted)
                        {
                            // Create the SSL wraping stream
                            connection.stream = new SslStream(connection.stream, false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null, EncryptionPolicy.RequireEncryption);

                            // Authenticate with the server
                            ((SslStream)connection.stream).BeginAuthenticateAsClient(hostname, Authenticated, connection);
                        }
                        else
                        {
                            // No encryption, the channel stay as is
                            ValidateCredentials(connection);
                        }
                    }
                    else
                    {
                        Drop(connection, "Expected to receive connection greetings and parameters.");
                    }
                }
                else
                {
                    Drop(connection, "The connection to {0}:{1} failed.", hostname, port);
                }
            }
            catch (DropException)
            {
                throw;
            }
            catch (Exception exception)
            {
                Debug.LogErrorFormat("{0}: {1}\n{2}", exception.GetType(), exception.Message, exception.StackTrace);
            }
        }