Class: Rcon::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/rcon/client.rb

Overview

Basic client for executing commands on your server remotely using the Source RCON protocol. See here for more details.

This is intended to be flexible enough to suit the needs of various flavors of RCON (for example, Minecraft).

See individual method summaries for more information.

Instance Method Summary collapse

Constructor Details

#initialize(host:, port:, password:) ⇒ Client

Instantiates an Rcon::Client.

Parameters:

  • host (String)

    IP address of the server running RCON

  • port (Integer)

    RCON port

  • password (String)

    RCON password



22
23
24
25
26
27
# File 'lib/rcon/client.rb', line 22

def initialize(host:, port:, password:)
  @host = host
  @port = port
  @password = password
  @socket = nil
end

Instance Method Details

#authenticate!(ignore_first_packet: true) ⇒ AuthResponse

Opens a TCP socket and authenticates with RCON.

According to the RCON spec, the server will respond to an authentication request with a SERVERDATA_RESPONSE_VALUE packet, followed by a SERVERDATA_AUTH_RESPONSE packet by default.

However, this is not the case in every implementation (looking at you Minecraft). For the sake of being flexible, we include a param which allows us to enable / disable this default behavior (see below).

It is not recommended to call this method more than once before ending the session.

Parameters:

  • ignore_first_packet (Boolean) (defaults to: true)

Returns:

Raises:



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/rcon/client.rb', line 43

def authenticate!(ignore_first_packet: true)
  packet_id = SecureRandom.rand(1000)
  auth_packet = Packet.new(packet_id, :SERVERDATA_AUTH, password)
  @socket = SocketWrapper.new(TCPSocket.open(host, port))
  socket.deliver_packet(auth_packet)
  read_packet_from_socket if ignore_first_packet

  read_packet_from_socket.
    then { |packet| Response.from_packet(packet) }.
    tap { |response| raise Error::AuthError unless response.success? }
end

#end_session!nil

Close the TCP socket and end the RCON session.

Returns:

  • (nil)


87
88
89
# File 'lib/rcon/client.rb', line 87

def end_session!
  @socket = socket.close
end

#execute(command, opts = {}) ⇒ CommandResponse

Execute the given command.

Some commands require their responses to be sent across several packets because they are larger than the maximum (default) RCON packet size of 4096 bytes.

In order to deal with this, we send an additional “trash” packet immediately following the initial command packet. SRCDS guarantees that requests are processed in order, and the subsequent responses are also in order, so we use this fact to append the packet bodies to the result on the client side until we see the trash packet id.

Many commands won’t require a segmented response, so we disable this behavior by default. You can enable it if you’d like using the option describe below.

Additionally, some implementations of RCON servers (MINECRAFT) cannot handle two packets in quick succession, so you may want to wait a short duration (i.e. <= 1 second) before sending the trash packet. We give the ability to do this using the wait option described below.

Parameters:

  • opts (Hash) (defaults to: {})

    options for executing the command

Options Hash (opts):

  • :expect_segmented_response (Boolean)

    follow segmented response logic described above if true

  • :wait (Integer)

    seconds to wait before sending trash packet (i.e. Minecraft 😡)

Returns:



78
79
80
81
82
83
# File 'lib/rcon/client.rb', line 78

def execute(command, opts = {})
  packet_id = SecureRandom.rand(1000)
  socket.deliver_packet(Packet.new(packet_id, :SERVERDATA_EXECCOMMAND, command))
  trash_packet_id = build_and_send_trash_packet(opts) if opts[:expect_segmented_response]
  build_response(trash_packet_id)
end