private void Client_MessageReceived(RconClient sender, RconPacket packet)
        {
            switch (packet.Type)
            {
            case PacketType.SERVERDATA_AUTH:
                Authenticate(sender, packet);
                break;

            case PacketType.SERVERDATA_EXECCOMMAND:
                if (sender.IsAuthed)
                {
                    HandleCommand(sender, packet);
                }
                else
                {
                    sender.SendPacket(new RconPacket(packet.Id, PacketType.SERVERDATA_RESPONSE_VALUE, "Not authenticated"));
                }
                break;

            default:
                Log.Error($"Recieved an unsupported packet type {packet.Type}. Id: {packet.Id}");
                sender.SendPacket(new RconPacket(packet.Id, PacketType.SERVERDATA_RESPONSE_VALUE, "Invalid packet type"));
                break;
            }
        }
Exemple #2
0
        public void SendPacket(RconPacket packet)
        {
            _outboundQueue.Enqueue(packet);
            //TODO: split if necessary
            //_outboundQueue.Enqueue(new RconPacket(packet.Id, PacketType.SERVERDATA_RESPONSE_VALUE, string.Empty));

            if (!_isSending)
            {
                FlushQueueAsync().ConfigureAwait(false);
            }
        }
        private void HandleCommand(RconClient sender, RconPacket packet)
        {
            var message = CommandHandler?.Invoke(packet.Body) ?? "No command handler defined on host.";

            var response = new RconPacket
            {
                Id   = packet.Id,
                Type = PacketType.SERVERDATA_RESPONSE_VALUE,
                Body = message
            };

            sender.SendPacket(response);
        }
        private void Authenticate(RconClient sender, RconPacket packet)
        {
            var hash = Md5Util.HashString(packet.Body);

            if (_pwHash != null && hash.SequenceEqual(_pwHash))
            {
                Log.Info($"{sender.RemoteEndPoint}: Authorized");
                sender.SendPacket(new RconPacket(packet.Id, PacketType.SERVERDATA_AUTHRESPONSE, string.Empty));
                sender.IsAuthed = true;
            }
            else
            {
                Log.Warn($"{sender.RemoteEndPoint}: Incorrect password attempt");
                sender.SendPacket(new RconPacket(-1, PacketType.SERVERDATA_AUTHRESPONSE, string.Empty));
                sender.IsAuthed = false;
            }
        }
        public static RconPacket FromBytes(byte[] buffer, int offset, int length)
        {
            //TODO validate byte length

            var packet = new RconPacket();

            packet.Size = BitConverter.ToInt32(buffer, offset);
            offset     += sizeof(int);
            packet.Id   = BitConverter.ToInt32(buffer, offset);
            offset     += sizeof(int);
            packet.Type = (PacketType)BitConverter.ToInt32(buffer, offset);
            offset     += sizeof(int);
            var readLength = packet.Size - (HEADER_SIZE + END_TERMINATION);

            packet.Body = Encoding.ASCII.GetString(buffer, offset, readLength);

            return(packet);
        }
Exemple #6
0
        private void Authenticate(RconClient sender, RconPacket packet)
        {
            var hash = Md5Util.HashString(packet.Body);

            if (_pwHash != null && hash.SequenceEqual(_pwHash))
            {
                Log.Info($"{sender.RemoteEndPoint}: Authorized");
                // Necessary to send an empty RESPONSE_VALUE before sending the AUTHRESPONSE, otherwise most RCON clients don´t realize AUTH has been successfully.
                // See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol#SERVERDATA_AUTH_RESPONSE
                // >>  When the server receives an auth request, it will respond with an empty SERVERDATA_RESPONSE_VALUE, followed immediately by a SERVERDATA_AUTH_RESPONSE indicating whether authentication succeeded or failed.
                sender.SendPacket(new RconPacket(packet.Id, PacketType.SERVERDATA_RESPONSE_VALUE, string.Empty));
                sender.SendPacket(new RconPacket(packet.Id, PacketType.SERVERDATA_AUTHRESPONSE, string.Empty));
                sender.IsAuthed = true;
            }
            else
            {
                Log.Warn($"{sender.RemoteEndPoint}: Incorrect password attempt");
                sender.SendPacket(new RconPacket(packet.Id, PacketType.SERVERDATA_RESPONSE_VALUE, string.Empty)); // same here by definition although most clients realized the wrong AUTH info
                sender.SendPacket(new RconPacket(-1, PacketType.SERVERDATA_AUTHRESPONSE, string.Empty));
                sender.IsAuthed = false;
            }
        }
Exemple #7
0
        private void EndReceivePacket(IAsyncResult ar)
        {
            var receiveData      = (Tuple <Socket, byte[]>)ar.AsyncState;
            var client           = receiveData.Item1;
            var rconMessageBytes = receiveData.Item2;

            try
            {
                client.EndReceive(ar);

                Log.Debug($"Message: {string.Join("", rconMessageBytes.Select(x => x.ToString("x2")))}");

                var rconMessage = RconPacket.FromBytes(rconMessageBytes, 0, rconMessageBytes.Length);
                Log.Debug($"Got packet: {rconMessage.Size} bytes\n  Type: {rconMessage.Type:G}\n  Id: {rconMessage.Id}\n  Body: {rconMessage.Body}");
                BeginReceivePacket(client);

                MessageReceived?.Invoke(this, rconMessage);
            }
            catch (Exception e)
            {
                OnConnectionException(e);
            }
        }