protected CommandResponsePacket SendRequestAndWaitForResponse(Server server, byte[] command, string message) { CommandResponsePacket commandResponsePacket = new CommandResponsePacket(); server.Send(command); int num = commandResponsePacket.Read(server.Stream); bool flag = num >= 0; CommandResponsePacket result; if (flag) { Log.Write("Command {0} executed: result = {1}", new object[] { message, (commandResponsePacket.Result == 0) ? "success" : "failure" }); result = commandResponsePacket; } else { Log.Write("Command {0} sent: result did not arrived", new object[] { message }); result = null; } return(result); }
protected void MainThreadRun(object arg) { this.Broadcast(Packet.DiscoverRequest, this.BroadcastPort); Thread.Sleep(10); Packet packet = new Packet(); CommandResponsePacket commandResponsePacket = new CommandResponsePacket(); packet.ReadHeader(this.Stream); packet = Packet.DeriveAndLoadData(packet, this.Stream); bool flag = packet is DiscoverResponsePacket; if (flag) { DiscoverResponsePacket discoverResponsePacket = packet as DiscoverResponsePacket; Log.Write("Got discover response: {0}", new object[] { packet }); Log.Write("Sending port select request.."); byte portFromMask = this.GetPortFromMask(discoverResponsePacket.PortMask); Packet.PortSelectRequest[6] = portFromMask; this.Broadcast(Packet.PortSelectRequest, this.BroadcastPort); commandResponsePacket.Read(this.Stream); Log.Write("Got port select response: {0}", new object[] { commandResponsePacket }); Client.CurrentServer.RemoteAddress.Port = 61576 + (int)portFromMask; this.SendRequestAndWaitForResponse(Client.CurrentServer, Packet.CheckConnectionRequest, "check connection"); this.SendRequestAndWaitForResponse(Client.CurrentServer, Packet.InitCANTranslationRequest, "init CAN"); Thread.Sleep(1000); } }
/// <summary> /// Records when a command response packet was received, to update the cooresponding state and release another blocking call. /// </summary> public void ResponseReceived(CommandResponsePacket packet) { lock (_commands) { Command command = _commands .Where(c => c.Sequence == packet.Sequence) .OrderBy(c => c.Elapsed) .FirstOrDefault(); if (command == null) { ErrorHandler.LogError(new Exception($"Error processing response.. command with sequence '{packet.Sequence}' not found")); return; } if ((packet.Code == ResultCode.Accept) || (packet.Code == ResultCode.Reject)) { command.Code = packet.Code; command.ResponsePacket = packet; } else if (packet.Code == ResultCode.Timeout) { command.Code = ResultCode.Timeout; } else { command.Code = ResultCode.Error; } } }
/// <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); } }
/// <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); } }
/// <summary> /// Sends command response. Data is optional. /// </summary> public bool SendCommandResponse(IPAddress destinationIP, CommandType type, int sequence, ResultCode code, byte[] data = null) { try { //disabled? if (_connectionState == ConnectionState.Disabled) { return(false); } //create packet CommandResponsePacket packet = new CommandResponsePacket( gameTitle: _config.GameTitle, gameVersion: _config.GameVersion, sourceIP: _config.LocalIP, destinationIP: destinationIP, playerName: _localPlayer.Name, commandType: type, sequence: sequence, code: code, data: data); //send packet _client.SendPacket(packet); _commandResponsesSent++; //success return(true); } catch (Exception ex) { _tcpErrors++; Log.Write("SendCommandResponse: Error sending data"); ErrorHandler.LogError(ex); return(false); } }
public CommandResult(ResultCode code, CommandResponsePacket responsePacket = null) { Code = code; ResponsePacket = responsePacket; }
/// <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); } } }