Example #1
0
        /// <summary>
        /// Sends 'EndSession' command to client to inform them of opponent disconnect.
        /// Waits for client acknowledgment, but doesn't do anything with it.
        /// </summary>
        private void SendEndSessionCommand(Client client, NetworkPlayer player)
        {
            try
            {
                //vars
                uint          timeoutMs = 1000;
                ushort        sequence  = (ushort)(UInt32.MaxValue - _random.Next(1000));
                CommandResult result;

                //message
                Log.Write($"Sending 'EndSession' request to '{client.RemoteIP}'");

                //create packet
                CommandRequestPacket packet = new CommandRequestPacket(
                    gameTitle: player.GameTitle,
                    gameVersion: player.GameVersion,
                    sourceIP: _ip,
                    destinationIP: player.IP,
                    playerName: player.Name,
                    commandType: CommandType.EndSession,
                    sequence: sequence,
                    retryAttempt: 0,
                    timeoutMs: timeoutMs,
                    data: null);

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

                //forward request to destination
                client.SendPacket(packet);

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

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

                    //sleep
                    Thread.Sleep(15);
                }
            }
            catch (Exception ex)
            {
                Log.Write("SendEndSessionCommand: Error processing expired session");
                ErrorHandler.LogError(ex);
            }
        }
Example #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);
            }
        }
Example #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);
            }
        }
Example #4
0
        /// <summary>
        /// Records when a command request packet was sent, to create a state that can be tied back to a response.
        /// </summary>
        public void RequestSent(CommandRequestPacket packet)
        {
            lock (_commands)
            {
                Command command = _commands
                                  .Where(c => c.Sequence == packet.Sequence)
                                  .OrderBy(c => c.Elapsed)
                                  .FirstOrDefault();

                if (command != null)
                {
                    command.RetryAttempt = packet.RetryAttempt;
                    command.StartTime    = DateTime.Now;
                }
                else
                {
                    command = new Command(packet.CommandType, packet.Sequence, TimeSpan.FromMilliseconds(packet.TimeoutMs));
                    _commands.Add(command);
                }
            }
        }
        private void CommandRequestPacketHandle(CommandRequestPacket pk)
        {
            string command = pk.Command.Remove(0, 1);

            Server.Instance.CommandManager.HandlePlayerCommand(this, command);
        }
Example #6
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);
                }
            }
        }
Example #7
0
        /// <summary>
        /// Sends command request, blocks until response or timeout.  Data is optional.
        /// </summary>
        public CommandResult SendCommandRequest(IPAddress destinationIP, CommandType type, byte[] data, TimeSpan timeout)
        {
            try
            {
                //disabled?
                if (_connectionState == ConnectionState.Disabled)
                {
                    return(new CommandResult(ResultCode.Error));
                }

                //vars
                int sequence;
                lock (this)
                {
                    sequence = _random.Next(Int32.MinValue, Int32.MaxValue);
                }

                //create packet
                CommandRequestPacket packet = new CommandRequestPacket(
                    gameTitle: _config.GameTitle,
                    gameVersion: _config.GameVersion,
                    sourceIP: _config.LocalIP,
                    destinationIP: destinationIP,
                    playerName: _localPlayer.Name,
                    commandType: type,
                    sequence: sequence,
                    retryAttempt: 0,
                    timeoutMs: (uint)timeout.TotalMilliseconds,
                    data: data);

                //record command request
                _commandManager.RequestSent(packet);

                //send packet
                _client.SendPacket(packet);
                _commandRequestsSent++;

                //loop
                while (true)
                {
                    //get current status
                    CommandResult result = _commandManager.GetCommandStatus(sequence);

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

                    //sleep
                    Thread.Sleep(15);
                }
            }
            catch (Exception ex)
            {
                _tcpErrors++;
                Log.Write("SendCommandRequest: Error sending data");
                ErrorHandler.LogError(ex);
                return(new CommandResult(ResultCode.Error));
            }
        }