/// <summary> /// Sends the authentication to the server /// </summary> /// <param name="password">RCON Password</param> public void Authenticate(string password) { _packetId++; var packet = new RemoteConPacket(_packetId, RemoteConPacket.PacketType.Auth, password, UseUTF8); SendPacket(packet); }
/// <summary> /// Sends the specified packet to the client /// </summary> /// <param name="packet">The packet to send</param> /// <exception cref="Exception">Not connected</exception> private void SendPacket(RemoteConPacket packet) { if (!_client.Connected) { throw new Exception("Not connected."); } var packetBytes = packet.GetBytes(); //_ns.Write(packetBytes, 0, packetBytes.Length); _ns.BeginWrite(packetBytes, 0, packetBytes.Length - 1, ar => { _ns.EndWrite(ar); }, null); }
/// <summary> /// Parses raw bytes to RemoteConPacket /// </summary> /// <param name="rawPacket"></param> internal void ParsePacket(byte[] rawPacket) { try { var packet = new RemoteConPacket(rawPacket); if (!Authenticated) { // ExecCommand is AuthResponse too. if (packet.Type == RemoteConPacket.PacketType.ExecCommand) { if (packet.Id == -1) { Log("Authentication failed."); Authenticated = false; if (OnAuthResult != null) { OnAuthResult(false); } } else { Log("Authentication success."); Authenticated = true; if (OnAuthResult != null) { OnAuthResult(false); } } } return; } if (_requestedCommands.ContainsKey(packet.Id) && packet.Type == RemoteConPacket.PacketType.ResponseValue) { _requestedCommands[packet.Id](packet.Payload); } else { Log("Got packet with invalid id " + packet.Id); } } catch (Exception e) { Debug.WriteLine(e); Log(e.ToString()); } }
/// <summary> /// Sends the specified packet to the client /// </summary> /// <param name="packet">The packet to send</param> /// <exception cref="Exception">Not connected</exception> private void SendPacket(RemoteConPacket packet) { if (_client == null || !_client.Connected) { throw new Exception("Not connected."); } var packetBytes = packet.GetBytes(); try { _ns.BeginWrite(packetBytes, 0, packetBytes.Length - 1, ar => { _ns.EndWrite(ar); }, null); } catch (ObjectDisposedException) { } // Do not write to NetworkStream when it's closed. catch (IOException) { } // Do not write to Socket when it's closed. }
/// <summary> /// Sends the specified packet to the client /// </summary> /// <param name="packet">The packet to send</param> /// <exception cref="Exception">Not connected</exception> private void SendPacket(RemoteConPacket packet) { if (_isUnitTest) { return; } if (!_connected) { throw new Exception("Not connected."); } var ackBytes = packet.GetBytes(); _ns.Write(ackBytes, 0, ackBytes.Length - 1); }
/// <summary> /// Sends a RCON Command to the server /// </summary> /// <param name="command">The RCON command with parameters</param> /// <param name="resultFunc">A function that will be executed after the server has processed the request</param> /// <exception cref="NotAuthenticatedException">If we're not authenticated</exception> public void SendCommand(string command, CommandResult resultFunc) { if (!_client.Connected) { return; } if (!Authenticated) { throw new NotAuthenticatedException(); } _packetId++; _requestedCommands.Add(_packetId, resultFunc); var packet = new RemoteConPacket(_packetId, RemoteConPacket.PacketType.ExecCommand, command, UseUTF8); SendPacket(packet); }
/// <summary> /// Parses raw bytes to RemoteConPacket /// </summary> /// <param name="rawPacket"></param> internal void ParsePacket(byte[] rawPacket) { try { var packet = new RemoteConPacket(rawPacket); if (!_isUnitTest) { _remoteConServer.LogDebug(((IPEndPoint)_tcp.Client.RemoteEndPoint).Address + " sent packet " + packet.Type + "!"); } // Do not allow any other packets than auth to be sent when client is not authenticated if (!Authenticated) { if (packet.Type != RemoteConPacket.PacketType.Auth) { if (_isUnitTest) { throw new NotAuthenticatedException(); } CloseConnection(); } _authTries++; if (packet.Payload == _remoteConServer.Password) { if (!_isUnitTest) { _remoteConServer.LogDebug(((IPEndPoint)_tcp.Client.RemoteEndPoint).Address + " successfully authenticated!"); } Authenticated = true; if (!_remoteConServer.SendAuthImmediately) { SendPacket(new RemoteConPacket(packet.Id, RemoteConPacket.PacketType.ResponseValue, "")); } SendPacket(new RemoteConPacket(packet.Id, RemoteConPacket.PacketType.ExecCommand, "")); return; } if (_authTries >= _remoteConServer.MaxPasswordTries) { if (_remoteConServer.BanMinutes > 0) { _remoteConServer.IpBanList.Add(((IPEndPoint)_tcp.Client.RemoteEndPoint).Address.ToString(), DateTime.Now.AddMinutes(_remoteConServer.BanMinutes).ToUnixTimestamp()); } CloseConnection(); return; } if (!_isUnitTest) { _remoteConServer.LogDebug(((IPEndPoint)_tcp.Client.RemoteEndPoint).Address + " entered wrong password!"); } if (!_remoteConServer.SendAuthImmediately) { SendPacket(new RemoteConPacket(packet.Id, RemoteConPacket.PacketType.ResponseValue, "")); } SendPacket(new RemoteConPacket(-1, RemoteConPacket.PacketType.ExecCommand, "")); return; } // Invalid packet type. if (packet.Type != RemoteConPacket.PacketType.ExecCommand) { if (_isUnitTest) { throw new InvalidPacketTypeException(); } _remoteConServer.LogDebug(((IPEndPoint)_tcp.Client.RemoteEndPoint).Address + " sent a packet with invalid type!"); if (_remoteConServer.InvalidPacketKick) { CloseConnection(); } return; } if (packet.Payload == "") { if (_isUnitTest) { throw new EmptyPacketPayloadException(); } _remoteConServer.LogDebug(((IPEndPoint)_tcp.Client.RemoteEndPoint).Address + " sent a packet with empty payload!"); if (_remoteConServer.EmptyPayloadKick) { CloseConnection(); } return; } var args = ArgumentParser.ParseLine(packet.Payload); var cmd = args[0]; args.RemoveAt(0); if (_remoteConServer.UseCustomCommandHandler) { var result = _remoteConServer.ExecuteCustomCommandHandler(cmd, args); SendPacket(new RemoteConPacket(packet.Id, RemoteConPacket.PacketType.ResponseValue, result)); return; } var command = _remoteConServer.CommandManager.GetCommand(cmd); if (command == null) { SendPacket(new RemoteConPacket(packet.Id, RemoteConPacket.PacketType.ResponseValue, "Invalid command \"" + packet.Payload + "\"")); } else { var commandResult = command.Handler(cmd, args); // TODO: Split packets? SendPacket(new RemoteConPacket(packet.Id, RemoteConPacket.PacketType.ResponseValue, commandResult)); } } catch (RconServerException) { throw; } catch (Exception e) { if (_isUnitTest) { throw; } if (!_isUnitTest) { _remoteConServer.LogDebug(string.Format("Client {0} caused an exception: {1} and was killed.", ((IPEndPoint)_tcp.Client.RemoteEndPoint).Address, e.Message)); } CloseConnection(); } }