Пример #1
0
        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;
            }
        }
Пример #2
0
 /// <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();
 }