Exemplo n.º 1
0
        private void _Room(Connection connection, NetIncomingMessage inMessage)
        {
            RoomCommand command = RoomCommand.Unknown;

            try
            {
                command = (RoomCommand)inMessage.ReadByte();
            }
            catch
            {
            }

            switch (command)
            {
            default:
            case RoomCommand.Unknown:
                break;

            case RoomCommand.Create:
            case RoomCommand.Destroy:
                // Unexpected
                break;

            case RoomCommand.Update:     // Server to Client
                _handler.RoomOperation(
                    RoomOperation.Update,
                    new Room(
                        connection.IPEndPoint.ToString().MD5String(),
                        connection,
                        new Packet(inMessage)));
                break;

            case RoomCommand.GetRoom:
            {
                string roomId = null;
                try
                {
                    roomId = inMessage.ReadString();
                }
                catch
                {
                }
                if (roomId == null)
                {
                    break;
                }

                _handler.Room(new Room(roomId, null, new Packet(inMessage)));
            }
            break;

            case RoomCommand.GetRoomsPage:
            {
                byte reqId     = 0;
                byte page      = 0;
                byte pages     = 0;
                byte roomCount = 0;

                try
                {
                    reqId     = inMessage.ReadByte();
                    page      = inMessage.ReadByte();
                    pages     = inMessage.ReadByte();
                    roomCount = inMessage.ReadByte();
                }
                catch
                {
                }

                if (reqId == 0 ||
                    reqId != _roomsPageReqId ||
                    page == 0 ||
                    roomCount == 0)
                {
                    return;
                }

                string[] roomIds = new string[roomCount];
                try
                {
                    for (int i = 0; i < roomCount; i++)
                    {
                        roomIds[i] = inMessage.ReadString();
                    }
                }
                catch
                {
                    return;
                }

                _handler.RoomsPage(roomIds, page, pages);
            }
            break;

            case RoomCommand.Auth:     // Master to Server
            {
                if (!IsHosting)
                {
                    return;
                }

                IPEndPoint ipEndPoint = null;
                try
                {
                    ipEndPoint = inMessage.ReadIPEndPoint();
                }
                catch
                {
                }
                if (ipEndPoint == null)
                {
                    return;
                }

                // Create auth
                string token = (ipEndPoint + DateTime.Now.ToString()).MD5String();
                Pair <IPEndPoint, string> auth = new Pair <IPEndPoint, string>(ipEndPoint, token);

                lock (_auths)
                {
                    Pair <IPEndPoint, string> oldAuth = _auths.FirstOrDefault(x => x.Left.Equals(ipEndPoint));
                    if (oldAuth != null)
                    {
                        _auths.Remove(oldAuth);
                    }

                    _auths.Add(auth);
                    _authsCache = _auths.ToArray();
                }

                // Send 'Hello' to client (NAT Punchthrough)
                byte[] data = "SA".GetBytes();
                SendToForeign(ipEndPoint, data, 0, data.Length);

                // Send accept to Master
                NetOutgoingMessage outMessage = _peer.CreateMessage();
                outMessage.Write((byte)DataType.Room);
                outMessage.Write((byte)RoomCommand.Accept);
                outMessage.Write(ipEndPoint);
                outMessage.Write(token);
                _master.NetConnection.SendMessage(outMessage, NetDeliveryMethod.ReliableOrdered, 0);
            }
            break;

            case RoomCommand.Connect:     // Master to Client
            {
                string     id         = null;
                IPEndPoint ipEndPoint = null;
                string     token      = null;

                try
                {
                    id         = inMessage.ReadString();
                    ipEndPoint = inMessage.ReadIPEndPoint();
                    token      = inMessage.ReadString();
                }
                catch
                {
                }

                if (id == null || ipEndPoint == null || token == null ||
                    string.IsNullOrEmpty(_targetRoomId) || id != _targetRoomId ||
                    _joinPacket == null)
                {
                    return;
                }

                // Connect to Server
                NetOutgoingMessage outMessage = _peer.CreateMessage();
                outMessage.Write(token);
                _joinPacket.Serialize(outMessage);

                _server = new Connection(ConnectionType.Server, _peer.Connect(ipEndPoint, outMessage),
                                         ConnectionStatus.Connecting);

                _targetRoomId = null;
                _joinPacket   = null;
            }
            break;
            }
        }
Exemplo n.º 2
0
        private void _Callback(object peer)
        {
            if (!IsAlive)
            {
                return;
            }

            try
            {
                NetIncomingMessage inMessage = _peer.ReadMessage();
                if (inMessage == null)
                {
                    return;
                }

                switch (inMessage.MessageType)
                {
                default:
                    break;

                case NetIncomingMessageType.ConnectionApproval:     // Client to Server
                {
                    if (!IsHosting)
                    {
                        inMessage.SenderConnection.Deny("Peer not hosting!");
                        break;
                    }

                    string token = null;
                    try
                    {
                        token = inMessage.ReadString();
                    }
                    catch
                    {
                    }
                    if (token == null)
                    {
                        inMessage.SenderConnection.Deny("Bad authentication data");
                        break;
                    }

                    Pair <IPEndPoint, string> auth =
                        _authsCache.FirstOrDefault(x => x.Left.Equals(inMessage.SenderEndPoint));
                    if (auth == null)
                    {
                        inMessage.SenderConnection.Deny("Authentication not found");
                        break;
                    }

                    lock (_auths)
                    {
                        _auths.Remove(auth);
                        _authsCache = _auths.ToArray();
                    }

                    if (auth.Right != token)
                    {
                        inMessage.SenderConnection.Deny("Authentication failed");
                        break;
                    }

                    Connection connection = new Connection(ConnectionType.Client, inMessage.SenderConnection,
                                                           ConnectionStatus.Connecting);
                    Pair <bool, Packet> result = _handler.Login(connection, new Packet(inMessage));

                    if (result == null)
                    {
                        inMessage.SenderConnection.Deny("Failed to perform login");
                        break;
                    }

                    if (!result.Left)
                    {
                        if (string.IsNullOrEmpty(result.Right.GetString("Reason")))
                        {
                            result.Right.SetString("Reason", "Login refused");
                        }
                        inMessage.SenderConnection.Deny("_" + result.Right.ToBase64String());
                        break;
                    }

                    lock (_clients)
                    {
                        if (!_clients.Contains(connection))
                        {
                            _clients.Add(connection);
                            _clientsCache = _clients.ToArray();
                        }
                    }

                    inMessage.SenderConnection.Approve();
                }
                break;

                case NetIncomingMessageType.StatusChanged:
                {
                    NetConnectionStatus status = (NetConnectionStatus)inMessage.ReadByte();
                    if (status != NetConnectionStatus.Connected && status != NetConnectionStatus.Disconnected)
                    {
                        break;
                    }

                    Connection connection = null;
                    if (_master != null && _master.IPEndPoint.Equals(inMessage.SenderEndPoint))
                    {
                        connection = _master;
                    }
                    else if (_server != null && _server.IPEndPoint.Equals(inMessage.SenderEndPoint))
                    {
                        connection = _server;
                    }
                    else
                    {
                        connection =
                            _clientsCache.FirstOrDefault(x => x.IPEndPoint.Equals(inMessage.SenderEndPoint));
                    }

                    if (connection == null)
                    {
                        if (status == NetConnectionStatus.Connected)
                        {
                            inMessage.SenderConnection.Disconnect("Connection not found");
                        }
                        break;
                    }

                    if (status == NetConnectionStatus.Connected)
                    {
                        connection.Status = ConnectionStatus.Connected;
                        _handler.Connect(connection);
                    }
                    else
                    {
                        // Drop/Remove connection by 'Type'
                        switch (connection.Type)
                        {
                        case ConnectionType.Master:
                        {
                            _master = null;

                            // Server
                            if (IsHosting)
                            {
                                IsHosting = false;
                            }

                            _serverRoom = null;

                            lock (_clients)
                            {
                                foreach (Connection conn in _clients)
                                {
                                    conn.NetConnection.Disconnect("Server closed the room and connection");
                                    conn.Status = ConnectionStatus.Disconnecting;
                                }

                                _clients.Clear();
                                _clientsCache = new Connection[0];
                            }

                            lock (_auths)
                            {
                                _auths.Clear();
                                _authsCache = new Pair <IPEndPoint, string> [0];
                            }

                            // Client
                            if (_server != null)
                            {
                                _server.NetConnection.Disconnect("Left");
                                _server = null;
                            }
                        }
                        break;

                        case ConnectionType.Server:
                            _server = null;
                            break;

                        case ConnectionType.Client:
                        {
                            lock (_clients)
                            {
                                if (_clients.Remove(connection))
                                {
                                    _clientsCache = _clients.ToArray();
                                }
                            }
                        }
                        break;
                        }

                        connection.Status = ConnectionStatus.Disconnected;
                        string reason = inMessage.ReadString();
                        if (reason.StartsWith("_"))
                        {
                            Packet packet = reason.Substring(1).ToPacket();
                            if (string.IsNullOrEmpty(packet.GetString("Reason")))
                            {
                                packet.SetString("Reason", "Unknown");
                            }
                            _handler.Disconnect(connection, packet);
                        }
                        else
                        {
                            Packet packet = new Packet();
                            packet.SetString("Reason", reason);
                            _handler.Disconnect(connection, packet);
                        }
                    }
                }
                break;

                case NetIncomingMessageType.Data:
                {
                    Connection connection = null;
                    if (_master != null && _master.IPEndPoint.Equals(inMessage.SenderEndPoint))
                    {
                        connection = _master;
                    }
                    else if (_server != null && _server.IPEndPoint.Equals(inMessage.SenderEndPoint))
                    {
                        connection = _server;
                    }
                    else
                    {
                        connection =
                            _clientsCache.FirstOrDefault(x => x.IPEndPoint.Equals(inMessage.SenderEndPoint));
                    }

                    if (connection == null)
                    {
                        inMessage.SenderConnection.Disconnect("Connection not found");
                        break;
                    }

                    DataType type = DataType.Unknown;

                    try
                    {
                        type = (DataType)inMessage.ReadByte();
                    }
                    catch
                    {
                    }

                    switch (type)
                    {
                    default:
                    case DataType.Unknown:
                        break;

                    case DataType.Room:
                        if (inMessage.DeliveryMethod == NetDeliveryMethod.ReliableOrdered ||
                            inMessage.DeliveryMethod == NetDeliveryMethod.ReliableSequenced)
                        {
                            _Room(connection, inMessage);
                        }
                        break;

                    case DataType.Data:
                        _handler.Data(connection, (Delivery)inMessage.DeliveryMethod, new Packet(inMessage),
                                      (Channel)inMessage.SequenceChannel);
                        break;
                    }
                }
                break;

                case NetIncomingMessageType.ConnectionLatencyUpdated:
                {
                    Connection connection = null;
                    if (_master != null && _master.IPEndPoint.Equals(inMessage.SenderEndPoint))
                    {
                        connection = _master;
                    }
                    else if (_server != null && _server.IPEndPoint.Equals(inMessage.SenderEndPoint))
                    {
                        connection = _server;
                    }
                    else
                    {
                        connection =
                            _clientsCache.FirstOrDefault(x => x.IPEndPoint.Equals(inMessage.SenderEndPoint));
                    }

                    if (connection == null)
                    {
                        inMessage.SenderConnection.Disconnect("Connection not found");
                        break;
                    }

                    connection.Latency = inMessage.ReadFloat();
                    _handler.Latency(connection, connection.Latency);
                }
                break;

                case NetIncomingMessageType.UnconnectedData:
                {
                    _handler.ForeignData(inMessage.SenderEndPoint, inMessage.Data);
                }
                break;

                case NetIncomingMessageType.DebugMessage:
                    _handler.Log(LogType.Info, inMessage.ReadString());
                    break;

                case NetIncomingMessageType.WarningMessage:
                    _handler.Log(LogType.Warning, inMessage.ReadString());
                    break;

                case NetIncomingMessageType.ErrorMessage:
                    _handler.Log(LogType.Error, inMessage.ReadString());
                    break;
                }

                _peer.Recycle(inMessage);
            }
            catch (Exception exception)
            {
                _Reset();
                _handler.Terminate(true, exception);
            }
        }