예제 #1
0
        /// <summary>
        /// Send the proper authentication packet and parse the response
        /// </summary>
        /// <param name="password">Current server password</param>
        /// <returns>True if the connection has been authenticated; False elsewhere</returns>
        /// <remarks>This method must be called prior to sending any other command</remarks>
        /// <exception cref="ArgumentException">Is thrown if <paramref name="password"/> parameter is null or empty</exception>
        public async Task <bool> AuthenticateAsync(string password)
        {
            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentException("password parameter must be a non null non empty string");
            }

            var authPacket = new RconPacket(PacketType.Auth, password);
            var response   = await _socket.SendDataAndReadResponseAsync(authPacket.GetBytes());

            var responsePacket = RconPacket.FromBytes(response);

            return(responsePacket.Id != -1);
        }
예제 #2
0
        /// <summary>
        /// Send a command encapsulated into an Rcon message packet and get the response
        /// </summary>
        /// <param name="command">Command to be executed</param>
        /// <returns>The response to this command</returns>
        /// <exception cref="ArgumentException">Is thrown if <paramref name="command"/> parameter is null or empty</exception>
        /// <exception cref="InvalidOperationException">Is thrown if the connection is not properly opened and authenticated</exception>
        public async Task <string> ExecuteCommandAsync(string command)
        {
            if (string.IsNullOrEmpty(command))
            {
                throw new ArgumentException("command parameter must be a non null non empty string");
            }

            if (!_socket.IsConnected)
            {
                throw new InvalidOperationException("You must authenticate the connection before sending any command to the server");
            }

            var commandPacket = new RconPacket(PacketType.ExecCommand, command);
            var response      = await _socket.SendDataAndReadResponseAsync(commandPacket.GetBytes());

            var responsePacket = RconPacket.FromBytes(response);

            return(responsePacket.Body);
        }
예제 #3
0
        private async Task ReadFromPipeAsync(PipeReader reader)
        {
            while (true)
            {
                var readResult = await reader.ReadAsync();

                var buffer        = readResult.Buffer;
                var startPosition = buffer.Start;
                if (buffer.Length < 4)                 // not enough bytes to get the packet length, need to read more
                {
                    if (readResult.IsCompleted)
                    {
                        break;
                    }

                    reader.AdvanceTo(startPosition, buffer.End);
                    continue;
                }

                var packetSize = BitConverter.ToInt32(buffer.Slice(startPosition, 4).ToArray());
                if (buffer.Length >= packetSize + 4)
                {
                    var endPosition = buffer.GetPosition(packetSize + 4, startPosition);
                    var rconPacket  = RconPacket.FromBytes(buffer.Slice(startPosition, endPosition).ToArray());
                    if (!rconPacket.IsDummy)
                    {
                        var currentOperation = operations.Peek();
                        currentOperation.Add(rconPacket);
                        if (currentOperation.OriginalRequest.Type == PacketType.Auth && rconPacket.Type == PacketType.Response)
                        {
                            // According to RCON documentation an empty RESPONSE packet must be sent after the auth request, but at the moment only CS:GO does so ..
                        }
                        else if (currentOperation.IsMultiPacketResponse && !string.IsNullOrEmpty(rconPacket.Body))
                        {
                            // Accumulate and move on
                        }
                        else
                        {
                            operations.Dequeue();
                            if (rconPacket.Id == -1)
                            {
                                currentOperation.TaskCompletionSource.SetException(new AuthenticationException("Invalid password"));
                            }
                            else
                            {
                                currentOperation.TaskCompletionSource.SetResult(currentOperation.Body);
                            }
                        }
                    }

                    reader.AdvanceTo(endPosition);
                }
                else
                {
                    reader.AdvanceTo(startPosition, buffer.End);
                }

                if (buffer.IsEmpty && readResult.IsCompleted)
                {
                    break;
                }
            }

            await reader.CompleteAsync();
        }