private void MessageLoop(object state)
        {
            var client = state as TcpClient;

            try
            {
                Debug.Log("Authenticating with server");

                using (var networkStream = client.GetStream())
                {
                    _stream = networkStream;
                    PerformHail(networkStream);

                    var        buffer        = new byte[1024];
                    NetMessage dataBuffer    = null;
                    var        bufferSize    = 0;
                    var        lengthBuffer  = new byte[2];
                    var        bytesReceived = 0;
                    int        readBytes;

                    var authMessages = new Queue <NetMessage>();
                    while (!_shutdownQueued)
                    {
                        readBytes = networkStream.Read(buffer, 0, buffer.Length);
                        if (readBytes > 0)
                        {
                            var readMessage = NetMessage.GetMessages(buffer, readBytes, ref bytesReceived,
                                                                     ref dataBuffer, ref lengthBuffer, ref bufferSize, authMessages.Enqueue);
                            if (readMessage >= 1)
                            {
                                break;
                            }
                        }
                        if (!client.Connected)
                        {
                            return;
                        }
                    }

                    if (authMessages.Count == 0)
                    {
                        throw new Exception("Could not read auth result");
                    }
                    var authMsg = authMessages.Dequeue();

                    var auth = authMsg.ReadBoolean();
                    authMsg.ReadPadBits();
                    if (!auth)
                    {
                        if (!authMsg.ReadString(out var reason))
                        {
                            reason = "Not authorized";
                        }
                        Debug.LogError($"Could not connect to server. {reason}");
                        UpdateConnectionStatus(ConnectionStatus.FailedToConnect);
                        return;
                    }
                    if (!authMsg.ReadGuid(out var guid))
                    {
                        throw new Exception("Could not read room guid");
                    }

                    Connected(guid, client);
                    UpdateConnectionStatus(ConnectionStatus.Connected);

                    //and drain the rest of messages that might have come after the auth
                    while (authMessages.Count > 0)
                    {
                        EnqueueMessage(authMessages.Dequeue());
                    }

                    while (!_shutdownQueued)
                    {
                        readBytes = networkStream.Read(buffer, 0, buffer.Length);
                        if (readBytes > 0)
                        {
                            NetMessage.GetMessages(buffer, readBytes, ref bytesReceived, ref dataBuffer,
                                                   ref lengthBuffer, ref bufferSize, EnqueueMessage);
                        }
                        if (!client.Connected)
                        {
                            return;
                        }
                    }
                }
            }
            catch (ObjectDisposedException ode)
            {
                //if (!_shutdownQueued)
                //    Debug.LogException(ode, "{0} disposed when it shouldn't have", ode.ObjectName);
            }
            catch (IOException ioe)
            {
                if (!(ioe.InnerException is SocketException))
                {
                    Debug.LogException(ioe);
                }
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
            finally
            {
                if (client != null)
                {
                    client.Close();
                }
                Disconnected();
                UpdateConnectionStatus(ConnectionStatus.Disconnected);
            }
        }
Example #2
0
        private async void HandleRoomConnection(TcpClient client)
        {
            var endpoint = client.Client.RemoteEndPoint;

            Debug.Log("Room connection request from {0}", endpoint);
            client.ReceiveBufferSize = 1024;
            client.SendBufferSize    = 1024;
            client.NoDelay           = true;
            client.LingerState       = new LingerOption(true, 10);

            Room room = null;

            try
            {
                using (var networkStream = client.GetStream())
                {
                    var        buffer        = new byte[1024];
                    NetMessage dataBuffer    = null;
                    var        bufferSize    = 0;
                    var        lengthBuffer  = new byte[2];
                    var        bytesReceived = 0;
                    int        readBytes;

                    var authMessages = new Queue <NetMessage>();
                    while (_tcpRunning)
                    {
                        readBytes = await networkStream.ReadAsync(buffer, 0, buffer.Length, _shutdownTokenSource.Token);

                        if (readBytes > 0)
                        {
                            var readMessage = NetMessage.GetMessages(buffer, readBytes, ref bytesReceived,
                                                                     ref dataBuffer, ref lengthBuffer, ref bufferSize, authMessages.Enqueue);
                            if (readMessage >= 1)
                            {
                                break;
                            }
                        }
                        if (!client.Connected)
                        {
                            return;
                        }
                    }

                    string denyReason;
                    if (
                        !ApproveRoomConnection((IPEndPoint)client.Client.RemoteEndPoint,
                                               authMessages.Count > 0 ? authMessages.Dequeue() : null, out denyReason, out room))
                    {
                        var dcMessage = GetMessage(denyReason.Length * 2 + 1);
                        dcMessage.Write(false);
                        dcMessage.WritePadBits();
                        dcMessage.Write(denyReason);
                        dcMessage.WriteSize();
                        await
                        networkStream.WriteAsync(dcMessage.Data, 0, dcMessage.LengthBytes,
                                                 _shutdownTokenSource.Token);

                        return;
                    }
                    else
                    {
                        var cMessage = GetMessage(17);
                        cMessage.Write(true);
                        cMessage.WritePadBits();
                        cMessage.Write(room.Guid);
                        cMessage.WriteSize();
                        await
                        networkStream.WriteAsync(cMessage.Data, 0, cMessage.LengthBytes, _shutdownTokenSource.Token);
                    }

                    room.TcpClient     = client;
                    room.NetworkStream = networkStream;

                    AddRoom(room);
                    UpdateRoomsOfNewRoom(room);

                    Debug.LogWarning("Room {1} connected from {0}, connectable at {2}", client.Client.RemoteEndPoint,
                                     room.RoomId, room.Address);

                    while (authMessages.Count > 0)
                    {
                        room.ConsumeData(authMessages.Dequeue());
                    }

                    while (_tcpRunning && room.Running)
                    {
                        readBytes = await networkStream.ReadAsync(buffer, 0, buffer.Length, _shutdownTokenSource.Token);

                        if (readBytes > 0)
                        {
                            NetMessage.GetMessages(buffer, readBytes, ref bytesReceived, ref dataBuffer,
                                                   ref lengthBuffer, ref bufferSize, room.ConsumeData);
                        }
                        if (!client.Connected)
                        {
                            return;
                        }
                    }
                }
            }
            catch (OperationCanceledException o)
            {
                Debug.Log("Operation canceled");
            }
            catch (ObjectDisposedException ode)
            {
                if (_tcpRunning && ode.ObjectName != "System.Net.Sockets.NetworkStream")
                {
                    Debug.LogException(ode, "{0} disposed when it shouldn't have", ode.ObjectName);
                }
            }
            catch (SocketException se)
            {
            }
            catch (IOException ioe)
            {
                if (!(ioe.InnerException is SocketException))
                {
                    Debug.LogException(ioe);
                }
            }
            catch (Exception exp)
            {
                Debug.LogException(exp);
            }
            finally
            {
                Debug.Log("Closing room connection to {0}", endpoint);
                client.Close();

                if (room != null)
                {
                    RemoveRoom(room);
                    room.NetworkStream = null;
                    //todo: move all players in the room to a new room.
                }
            }
        }
        private async void ConnectCallback(IAsyncResult ar)
        {
            var client = ar.AsyncState as TcpClient;

            try
            {
                if (client != _serverClient)
                {
                    throw new Exception("TcpClient Mismatch");
                }

                client.EndConnect(ar);
                Debug.Log("Authenticating with server");

                using (var networkStream = client.GetStream())
                {
                    await PerformHail(networkStream);

                    var        buffer        = new byte[1024];
                    NetMessage dataBuffer    = null;
                    var        bufferSize    = 0;
                    var        lengthBuffer  = new byte[2];
                    var        bytesReceived = 0;
                    int        readBytes;


                    var authMessages = new Queue <NetMessage>();
                    while (!_shutdownQueued)
                    {
                        readBytes = await networkStream.ReadAsync(buffer, 0, buffer.Length);

                        if (readBytes > 0)
                        {
                            var readMessage = NetMessage.GetMessages(buffer, readBytes, ref bytesReceived,
                                                                     ref dataBuffer, ref lengthBuffer, ref bufferSize, authMessages.Enqueue);
                            if (readMessage >= 1)
                            {
                                break;
                            }
                        }
                        if (!client.Connected)
                        {
                            return;
                        }
                    }

                    if (authMessages.Count == 0)
                    {
                        throw new Exception("Could not read auth result");
                    }
                    var authMsg = authMessages.Dequeue();

                    var auth = authMsg.ReadBoolean();
                    authMsg.ReadPadBits();
                    if (!auth)
                    {
                        string reason;
                        if (!authMsg.ReadString(out reason))
                        {
                            reason = "Not authorized";
                        }
                        Debug.LogError("Could not connect to server. {0}", reason);
                        ServerStatus = ConnectionStatus.FailedToConnect;
                        ServerStatusChanged.TryRaise(Debug.Logger);
                        return;
                    }
                    Guid guid;
                    if (!authMsg.ReadGuid(out guid))
                    {
                        throw new Exception("Could not read room guid");
                    }

                    RoomId = guid;
                    Debug.Log("Connected to dispatcher. Id is {0}", RoomId);
                    Server = new Server(this)
                    {
                        NetworkStream = networkStream, TcpClient = client
                    };
                    ServerStatus = ConnectionStatus.Connected;
                    ServerStatusChanged.TryRaise(Debug.Logger);

                    //and drain the rest of messages that might have come after the auth
                    while (authMessages.Count > 0)
                    {
                        EnqueueMessage(authMessages.Dequeue());
                    }

                    while (!_shutdownQueued)
                    {
                        readBytes = await networkStream.ReadAsync(buffer, 0, buffer.Length);

                        if (readBytes > 0)
                        {
                            NetMessage.GetMessages(buffer, readBytes, ref bytesReceived, ref dataBuffer,
                                                   ref lengthBuffer, ref bufferSize, EnqueueMessage);
                        }
                        if (!client.Connected)
                        {
                            return;
                        }
                    }
                }
            }
            catch (ObjectDisposedException ode)
            {
                if (!_shutdownQueued)
                {
                    Debug.LogException(ode, "{0} disposed when it shouldn't have", ode.ObjectName);
                }
            }
            catch (IOException ioe)
            {
                if (!(ioe.InnerException is SocketException))
                {
                    Debug.LogException(ioe);
                }
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
            finally
            {
                if (client != null)
                {
                    client.Close();
                }
                ServerStatus = ConnectionStatus.Disconnected;
                ServerStatusChanged.TryRaise(Debug.Logger);
            }
        }
Example #4
0
        private async void HandleClientConnection(TcpClient client)
        {
            var endpoint = client.Client.RemoteEndPoint;

            Debug.Log("Player connection request from {0}", endpoint);
            client.ReceiveBufferSize = 1024;
            client.SendBufferSize    = 1024;
            client.NoDelay           = true;
            client.LingerState       = new LingerOption(true, 10);

            Player player = null;

            try
            {
                using (var networkStream = client.GetStream())
                {
                    var        buffer        = new byte[1024];
                    NetMessage dataBuffer    = null;
                    var        bufferSize    = 0;
                    var        lengthBuffer  = new byte[2];
                    var        bytesReceived = 0;
                    int        readBytes;

                    var authMessages = new Queue <NetMessage>();
                    while (_tcpRunning)
                    {
                        readBytes = await networkStream.ReadAsync(buffer, 0, buffer.Length, _shutdownTokenSource.Token);

                        if (readBytes > 0)
                        {
                            var readMessage = NetMessage.GetMessages(buffer, readBytes, ref bytesReceived,
                                                                     ref dataBuffer, ref lengthBuffer, ref bufferSize, authMessages.Enqueue);
                            if (readMessage >= 1)
                            {
                                break;
                            }
                        }
                        if (!client.Connected)
                        {
                            return;
                        }
                    }

                    player = new Player(this)
                    {
                        TcpClient     = client,
                        NetworkStream = networkStream,
                        Status        = ConnectionStatus.Connecting
                    };
                    if (ConstructNetData != null)
                    {
                        player.NetUserData = ConstructNetData();
                    }

                    if (VerifyPlayer != null)
                    {
                        if (authMessages.Count > 0)
                        {
                            VerifyPlayer(player, authMessages.Dequeue());
                        }
                        else
                        {
                            player.Disconnect("No authentication message sent");
                        }
                    }
                    else
                    {
                        player.AllowConnect();
                    }

                    var canConnect = await player.AllowConnectCompletion.Task;
                    if (!canConnect)
                    {
                        return;
                    }

                    player.Status = ConnectionStatus.Connected;
                    FinalizePlayerAdd(player);

                    Debug.Log("Client connected from {0}", client.Client.RemoteEndPoint);
                    //and drain the rest of messages that might have come after the auth
                    while (authMessages.Count > 0)
                    {
                        player.ConsumeData(authMessages.Dequeue());
                    }

                    while (_tcpRunning)
                    {
                        readBytes = await networkStream.ReadAsync(buffer, 0, buffer.Length, _shutdownTokenSource.Token);

                        if (readBytes > 0)
                        {
                            NetMessage.GetMessages(buffer, readBytes, ref bytesReceived, ref dataBuffer,
                                                   ref lengthBuffer, ref bufferSize, player.ConsumeData);
                        }
                        if (!client.Connected)
                        {
                            return;
                        }
                    }
                }
            }
            catch (OperationCanceledException o)
            {
                Debug.Log("Operation canceled");
            }
            catch (ObjectDisposedException ode)
            {
                if (_tcpRunning && ode.ObjectName != "System.Net.Sockets.NetworkStream")
                {
                    Debug.LogException(ode, "{0} disposed when it shouldn't have", ode.ObjectName);
                }
            }
            catch (SocketException se)
            {
            }
            catch (IOException ioe)
            {
                if (!(ioe.InnerException is SocketException))
                {
                    Debug.LogException(ioe);
                }
            }
            catch (Exception exp)
            {
                Debug.LogException(exp);
            }
            finally
            {
                player.Status = ConnectionStatus.Disconnecting;
                Debug.Log("Closing client connection to {0}", endpoint);
                client.Close();
                if (player != null)
                {
                    player.Status = ConnectionStatus.Disconnected;
                    RemovePlayer(player);
                    player.NetworkStream = null;
                }
            }
        }
        private async void HandleClientConnection(TcpClient client)
        {
            var endpoint = client.Client.RemoteEndPoint;

            Debug.Log($"Player connection request from {endpoint}");
            client.ReceiveBufferSize = 1024;
            client.ReceiveTimeout    = 5000;
            client.SendBufferSize    = 1024;
            client.NoDelay           = true;
            client.LingerState       = new LingerOption(true, 10);

            ConnectionInfo ci = null;

            try
            {
                using (var networkStream = client.GetStream())
                {
                    var        buffer        = new byte[1024];
                    NetMessage dataBuffer    = null;
                    var        bufferSize    = 0;
                    var        lengthBuffer  = new byte[2];
                    var        bytesReceived = 0;
                    int        readBytes;

                    var authMessages = new Queue <NetMessage>();
                    while (_tcpRunning)
                    {
                        readBytes = await networkStream.ReadAsync(buffer, 0, buffer.Length, _shutdownTokenSource.Token);

                        if (readBytes > 0)
                        {
                            var readMessage = NetMessage.GetMessages(buffer, readBytes, ref bytesReceived,
                                                                     ref dataBuffer, ref lengthBuffer, ref bufferSize, authMessages.Enqueue);
                            if (readMessage >= 1)
                            {
                                break;
                            }
                        }
                        if (!client.Connected)
                        {
                            return;
                        }
                    }

                    ci = new ConnectionInfo
                    {
                        Client = client,
                        Stream = networkStream
                    };

                    lock (_players)
                        _players.Add(ci);

                    if (authMessages.Count > 0)
                    {
                        PlayerAttemptingConnection(ci, (IPEndPoint)client.Client.RemoteEndPoint, player =>
                        {
                            ci.Player     = player;
                            player.Status = ConnectionStatus.Connecting;
                        }, authMessages.Dequeue());
                    }
                    else
                    {
                        ci.Player.Disconnect("No authentication message sent");
                    }

                    var canConnect = await ci.AllowConnectCompletion.Task;
                    if (!canConnect)
                    {
                        return;
                    }

                    ci.Player.Status = ConnectionStatus.Connected;
                    FinalizePlayerAdd(ci.Player);

                    Debug.Log($"Client connected from {client.Client.RemoteEndPoint}");
                    //and drain the rest of messages that might have come after the auth
                    while (authMessages.Count > 0)
                    {
                        ci.Player.ConsumeData(authMessages.Dequeue());
                    }

                    while (_tcpRunning)
                    {
                        readBytes = await networkStream.ReadAsync(buffer, 0, buffer.Length, _shutdownTokenSource.Token);

                        if (readBytes > 0)
                        {
                            NetMessage.GetMessages(buffer, readBytes, ref bytesReceived, ref dataBuffer,
                                                   ref lengthBuffer, ref bufferSize, ci.Player.ConsumeData);
                        }
                        else
                        {
                            EnsureConnected(ci);
                        }
                        if (!client.Connected)
                        {
                            return;
                        }
                    }
                }
            }
            catch (OperationCanceledException o)
            {
                Debug.Log("Operation canceled");
            }
            catch (ObjectDisposedException ode)
            {
                if (_tcpRunning && !ode.ObjectName.StartsWith("System.Net.Sockets"))
                {
                    Debug.LogException(ode, $"{ode.ObjectName} disposed when it shouldn't have");
                }
            }
            catch (SocketException se)
            {
            }
            catch (IOException ioe)
            {
                if (!(ioe.InnerException is SocketException))
                {
                    Debug.LogException(ioe);
                }
            }
            catch (Exception exp)
            {
                Debug.LogException(exp);
            }
            finally
            {
                Debug.Log($"Closing client connection to {endpoint}");
                client.Close();

                if (ci != null)
                {
                    ci.Player.Status = ConnectionStatus.Disconnecting;

                    lock (_players)
                        _players.Remove(ci);
                    ci.Player.Status = ConnectionStatus.Disconnected;
                    RemovePlayer(ci.Player);
                    ci.Player.Connection = null;
                }
            }
        }