Пример #1
0
        /// <summary>
        /// Fired when packet received from a client.
        /// </summary>
        private void PacketReceived(Client client, PacketBase packet)
        {
            try
            {
                //heartbeat
                if (packet is HeartbeatPacket hp)
                {
                    NetworkPlayer player = NetworkPlayer.FromPacket(hp);
                    if (player != null)
                    {
                        AddOrUpdatePlayer(player, client);
                    }
                }

                //command request
                else if (packet is CommandRequestPacket req)
                {
                    Log.Write($"Received '{req.CommandType}' request from '{client.RemoteIP}'");
                    switch (req.CommandType)
                    {
                    //get-players command
                    case CommandType.GetPlayers:
                        Answer_GetPlayers(client, req);
                        break;

                    //quit-game command
                    case CommandType.QuitGame:
                        Answer_QuitGame(client, req);
                        break;

                    //all other commands
                    default:
                        Passthrough_Command(client, req);
                        break;
                    }
                }

                //command response
                else if (packet is CommandResponsePacket resp)
                {
                    Log.Write($"Received '{resp.CommandType}' ({resp.Code}) response from '{client.RemoteIP}'");
                    _commandManager.ResponseReceived(resp);
                }

                //data
                else if (packet is DataPacket dp)
                {
                    Passthrough_Data(client, dp);
                }
            }
            catch (Exception ex)
            {
                Log.Write("PacketReceived: Error processing packet");
                ErrorHandler.LogError(ex);
            }
        }
Пример #2
0
        /// <summary>
        /// Answers a 'GetPlayers' request, responds with a list of connected players (of same game).
        /// </summary>
        private void Answer_GetPlayers(Client sourceClient, CommandRequestPacket packet)
        {
            try
            {
                //get source player
                NetworkPlayer player = NetworkPlayer.FromPacket(packet);

                //get list of connected players (not source player)
                List <NetworkPlayer> otherPlayers = GetMatchingPlayers(player.GameTitle, player.GameVersion)
                                                    .Where(p => p.PlayerKey != player.PlayerKey)
                                                    .ToList();

                //message
                Log.Write($"Sending '{packet.CommandType}' ({otherPlayers.Count} player{(otherPlayers.Count != 1 ? "s" : "")}) response to '{player.IP}'");

                //serialize list to bytes
                PacketBuilder builder = new PacketBuilder();
                builder.AddUInt16((ushort)otherPlayers.Count);
                foreach (NetworkPlayer p in otherPlayers)
                {
                    builder.AddBytes(p.ToBytes());
                }

                //create packet
                CommandResponsePacket response = new CommandResponsePacket(
                    gameTitle: player.GameTitle,
                    gameVersion: player.GameVersion,
                    sourceIP: _ip,
                    destinationIP: player.IP,
                    playerName: player.Name,
                    commandType: CommandType.GetPlayers,
                    sequence: packet.Sequence,
                    code: ResultCode.Accept,
                    data: builder.ToBytes());

                //send response back to source
                sourceClient.SendPacket(response);
            }
            catch (Exception ex)
            {
                Log.Write("Answer_GetPlayers: Error returning player list");
                ErrorHandler.LogError(ex);
            }
        }
Пример #3
0
        /// <summary>
        /// Answers a 'QuitGame' request, responds with acceptance.
        /// </summary>
        private void Answer_QuitGame(Client sourceClient, CommandRequestPacket packet)
        {
            try
            {
                //get source player
                NetworkPlayer player = NetworkPlayer.FromPacket(packet);
                player = GetPlayerByKey(player.PlayerKey);

                //set quit flag
                player.QuitGame = true;

                //remove expired players
                RemoveExpiredPlayers();

                //remove expired sessions
                RemoveExpiredSessions();

                //message
                Log.Write($"Sending '{packet.CommandType}' ({ResultCode.Accept}) response to '{player.IP}'");

                //create packet
                CommandResponsePacket response = new CommandResponsePacket(
                    gameTitle: player.GameTitle,
                    gameVersion: player.GameVersion,
                    sourceIP: _ip,
                    destinationIP: player.IP,
                    playerName: player.Name,
                    commandType: CommandType.QuitGame,
                    sequence: packet.Sequence,
                    code: ResultCode.Accept,
                    data: null);

                //send response back to source
                sourceClient.SendPacket(response);
            }
            catch (Exception ex)
            {
                Log.Write("Answer_QuitGame: Unknown error");
                ErrorHandler.LogError(ex);
            }
        }
Пример #4
0
        /// <summary>
        /// Forwards a data packet to destination player.  No waiting or response.
        /// </summary>
        private void Passthrough_Data(Client sourceClient, DataPacket dataPacket)
        {
            NetworkPlayer sourcePlayer = null;
            NetworkPlayer destinationPlayer;
            bool          sessionEnded = false;

            try
            {
                //get source player
                sourcePlayer = NetworkPlayer.FromPacket(dataPacket);
                if (sourcePlayer == null)
                {
                    Log.Write($"Passthrough_Data: Unable to parse packet");
                    return;
                }

                //get destination player
                destinationPlayer = GetMatchingPlayer(dataPacket.DestinationIP, dataPacket.GameTitle, dataPacket.GameVersion);
                if (destinationPlayer == null)
                {
                    Log.Write($"Passthrough_Data: Cannot find destination player at '{dataPacket.DestinationIP}'");
                    sessionEnded = true;
                    return;
                }

                //get session
                Session session = GetSession(sourcePlayer.PlayerKey, destinationPlayer.PlayerKey);
                if (session == null)
                {
                    Log.Write($"Passthrough_Data: Live session does not exist between '{sourcePlayer.IP}' and '{destinationPlayer.IP}'");
                    sessionEnded = true;
                    return;
                }

                //get destination client
                Client destinationClient = GetClientByPlayer(destinationPlayer);
                if (destinationClient == null)
                {
                    Log.Write($"Passthrough_Data: Destination player at {destinationClient.RemoteIP} does not have assigned TCP client");
                    sessionEnded = true;
                    return;
                }

                ////message (keep)
                //Log.Write($"Forwarding data packet from '{sourcePlayer.IP}' to '{destinationPlayer.IP}'");

                //forward request to destination
                destinationClient.SendPacket(dataPacket);
            }
            catch (Exception ex)
            {
                Log.Write("Passthrough_Data: Error forwarding data packet");
                ErrorHandler.LogError(ex);
            }
            finally
            {
                try
                {
                    //send session-ended command?
                    if (sessionEnded)
                    {
                        SendEndSessionCommand(sourceClient, sourcePlayer);
                    }
                }
                catch (Exception ex)
                {
                    Log.Write("Passthrough_Data: Finalizer error");
                    ErrorHandler.LogError(ex);
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Forwards a command request packet to destination player, waits for response (or timeout),
        /// responds to source player with answer.
        /// </summary>
        private void Passthrough_Command(Client sourceClient, CommandRequestPacket requestPacket)
        {
            CommandResult result            = new CommandResult(ResultCode.Unspecified);
            NetworkPlayer sourcePlayer      = null;
            NetworkPlayer destinationPlayer = null;
            bool          sessionEnded      = false;

            try
            {
                //get source player
                sourcePlayer = NetworkPlayer.FromPacket(requestPacket);
                if (sourcePlayer == null)
                {
                    Log.Write($"Passthrough_Command: Unable to parse packet");
                    result.Code = ResultCode.Error;
                    return;
                }

                //get destination player
                destinationPlayer = GetMatchingPlayer(requestPacket.DestinationIP, requestPacket.GameTitle, requestPacket.GameVersion);
                if (destinationPlayer == null)
                {
                    Log.Write($"Passthrough_Command: Cannot find destination player at '{requestPacket.DestinationIP}'");
                    result.Code = ResultCode.Error;
                    return;
                }

                //create session?
                if (requestPacket.CommandType == CommandType.ConnectToPlayer)
                {
                    CreateSession(sourcePlayer.PlayerKey, destinationPlayer.PlayerKey);
                }

                //get session
                Session session = GetSession(sourcePlayer.PlayerKey, destinationPlayer.PlayerKey);
                if ((session == null) && (requestPacket.CommandType != CommandType.ConnectToPlayer))
                {
                    Log.Write($"Passthrough_Command: Live session does not exist between '{sourcePlayer.IP}' and '{destinationPlayer.IP}'");
                    result.Code  = ResultCode.Error;
                    sessionEnded = true;
                    return;
                }

                //get destination client
                Client destinationClient = GetClientByPlayer(destinationPlayer);
                if (destinationClient == null)
                {
                    Log.Write($"Passthrough_Command: Destination player at {destinationClient.RemoteIP} does not have assigned TCP client");
                    result.Code = ResultCode.Error;
                    return;
                }

                //message
                Log.Write($"Forwarding '{requestPacket.CommandType}' request from '{sourcePlayer.IP}' to '{destinationPlayer.IP}'");

                //record command request being sent
                _commandManager.RequestSent(requestPacket);

                //forward request to destination
                destinationClient.SendPacket(requestPacket);

                //wait for response or timeout
                while (true)
                {
                    //get current status
                    result = _commandManager.GetCommandStatus(requestPacket.Sequence);

                    //have answer or timeout?  return!
                    if (result.Code != ResultCode.Unspecified)
                    {
                        return;
                    }

                    //sleep
                    Thread.Sleep(15);
                }
            }
            catch (Exception ex)
            {
                Log.Write("Passthrough_Command: Error forwarding request or waiting for response");
                ErrorHandler.LogError(ex);
            }
            finally
            {
                try
                {
                    //create response packet
                    CommandResponsePacket responsePacket;
                    if ((result.Code.In(ResultCode.Accept, ResultCode.Reject)) && (result.ResponsePacket != null))
                    {
                        ////create session?
                        //if ((requestPacket.CommandType == CommandType.ConnectToPlayer) && (result.Code == ResultCode.Accept))
                        //    CreateSession(sourcePlayer.UniqueKey, destinationPlayer.UniqueKey);

                        //confirm session?
                        if ((requestPacket.CommandType == CommandType.ConnectToPlayer) && (result.Code == ResultCode.Accept))
                        {
                            ConfirmSession(sourcePlayer.PlayerKey, destinationPlayer.PlayerKey);
                        }

                        //get original packet
                        responsePacket = result.ResponsePacket;

                        //message
                        Log.Write($"Forwarding '{result.ResponsePacket.CommandType}' ({result.ResponsePacket.Code}) response from '{destinationPlayer.IP}' to '{sourcePlayer.IP}'");
                    }
                    else
                    {
                        //create new timeout/error packet
                        responsePacket = new CommandResponsePacket(
                            gameTitle: requestPacket.GameTitle,
                            gameVersion: requestPacket.GameVersion,
                            sourceIP: requestPacket.DestinationIP,
                            destinationIP: requestPacket.SourceIP,
                            playerName: "",
                            commandType: requestPacket.CommandType,
                            sequence: requestPacket.Sequence,
                            code: result.Code,
                            data: null);

                        //message
                        Log.Write($"Sending '{responsePacket.CommandType}' ({responsePacket.Code}) response to '{sourceClient.RemoteIP}'");
                    }

                    //send response to source
                    sourceClient.SendPacket(responsePacket);

                    //send session-ended command?
                    if (sessionEnded)
                    {
                        SendEndSessionCommand(sourceClient, sourcePlayer);
                    }
                }
                catch (Exception ex)
                {
                    Log.Write("Passthrough_Command: Error sending command response to source");
                    ErrorHandler.LogError(ex);
                }
            }
        }