private void HandlePacket(RCONPacket packet) { switch (packet.Type) { case RCONPacketType.SERVERDATA_AUTH: { bool authenticated = packet.Body == Settings.settingsStore.rconPassword; // send response SendPacket(new RCONPacket() { ID = (authenticated ? packet.ID : -1), // match packet id if pass good, otherwise -1 Type = RCONPacketType.SERVERDATA_AUTH_RESPONSE }); if (authenticated) { State = RCONClientState.AUTHENTICATED; } else { DarkLog.Normal(RemoteIP.ToString() + ": Bad RCON Password"); Close(); } } break; case RCONPacketType.SERVERDATA_EXECCOMMAND: // command { if (State != RCONClientState.AUTHENTICATED) { // not authenticated Close(); break; } // we use a wait handle because the server must always execute RCON commands in order using (AutoResetEvent waitHandle = new AutoResetEvent(false)) { DarkLog.Normal("RCON command from " + RemoteIP.ToString() + ": " + packet.Body); CommandHandler.HandleServerInput(packet.Body, (string output) => { // we can fit 4082 characters in a single packet List <string> responses = new List <string> { output.Substring(0, Math.Min(RCONPacket.MAXIMUM_BODY_LENGTH, output.Length)) }; while (output.Length - (RCONPacket.MAXIMUM_BODY_LENGTH * responses.Count) > RCONPacket.MAXIMUM_BODY_LENGTH) { responses.Add(output.Substring(RCONPacket.MAXIMUM_BODY_LENGTH * responses.Count, RCONPacket.MAXIMUM_BODY_LENGTH)); } // send the packet(s) foreach (string response in responses) { SendPacket(new RCONPacket() { Body = response, Type = RCONPacketType.SERVERDATA_RESPONSE_VALUE, ID = packet.ID }); } // release wait handle waitHandle.Set(); }); waitHandle.WaitOne(); } } break; case RCONPacketType.SERVERDATA_RESPONSE_VALUE: // see comment below { // see: https://developer.valvesoftware.com/wiki/Source_RCON_Protocol#Multiple-packet_Responses SendPacket(packet); SendPacket(new RCONPacket() { Type = RCONPacketType.SERVERDATA_RESPONSE_VALUE, BodyRaw = new List <byte>(new byte[] { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 }) }); } break; } }
/// <summary> /// Sends an <see cref="RCONPacket"/> to the RCON client /// </summary> /// <param name="packet"></param> public void SendPacket(RCONPacket packet) { TcpClient.GetStream().Write(packet.RawData.ToArray(), 0, packet.RawData.Count); TcpClient.GetStream().Flush(); }