Class: Rcon::Packet

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

Overview

Data structure representing packets sent to / received from RCON server.

Constant Summary collapse

REQUEST_PACKET_TYPE =

Types of packets that the server expects to receive.

The keys correspond with the Source RCON spec names, the values correspond with what the server expects to see in the type segment of a packet.

{
  SERVERDATA_AUTH: 3,
  SERVERDATA_EXECCOMMAND: 2
}.freeze
RESPONSE_PACKET_TYPE =

Types of packets that the client can expect to receive back from the server.

The keys correspond with the Source RCON spec names, the values correspond with what the client expects to see in the type segment of a packet.

{
  SERVERDATA_AUTH_RESPONSE: 2,
  SERVERDATA_RESPONSE_VALUE: 0
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id, type, body) ⇒ Packet

Instantiates a Rcon::Packet

Parameters:



62
63
64
65
66
# File 'lib/rcon/packet.rb', line 62

def initialize(id, type, body)
  @id = id
  @type = type
  @body = body
end

Instance Attribute Details

#bodyObject (readonly)

Returns the value of attribute body.



117
118
119
# File 'lib/rcon/packet.rb', line 117

def body
  @body
end

#idObject (readonly)

Returns the value of attribute id.



117
118
119
# File 'lib/rcon/packet.rb', line 117

def id
  @id
end

#typeObject (readonly)

Returns the value of attribute type.



117
118
119
# File 'lib/rcon/packet.rb', line 117

def type
  @type
end

Class Method Details

.read_from_socket_wrapper(socket_wrapper) ⇒ Packet

Read a packet from the given SocketWrapper.

Parameters:

Returns:

Raises:



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

def self.read_from_socket_wrapper(socket_wrapper)
  if socket_wrapper.ready_to_read?
    size = socket_wrapper.recv(INT_BYTE_SIZE).unpack(INTEGER_PACK_DIRECTIVE).first
    id_and_type_length = 2 * INT_BYTE_SIZE
    body_length = size - id_and_type_length - (2 * TRAILER_BYTE_SIZE) # ignore trailing nulls

    payload = socket_wrapper.recv(size)
    id, type_int = payload[0...id_and_type_length].unpack("#{INTEGER_PACK_DIRECTIVE}*")
    body = payload[id_and_type_length..].unpack("#{STR_PACK_DIRECTIVE}#{body_length}").first
    type = RESPONSE_PACKET_TYPE.key(type_int) || raise(Error::InvalidResponsePacketTypeCodeError.new(type_int))

    new(id, RESPONSE_PACKET_TYPE.key(type_int), body)
  end
end

Instance Method Details

#==(other) ⇒ Boolean

Compares two objects to see if they are equal

Returns true if other is a Packet and attributes match self, false otherwise.

Parameters:

Returns:

  • (Boolean)


73
74
75
# File 'lib/rcon/packet.rb', line 73

def ==(other)
  eql?(other)
end

#eql?(other) ⇒ Boolean

Compares two objects to see if they are equal Returns true if other is a Packet and attributes match self, false otherwise.

Parameters:

Returns:

  • (Boolean)


82
83
84
85
86
87
88
# File 'lib/rcon/packet.rb', line 82

def eql?(other)
  if other.is_a?(Packet)
    id == other.id && type == other.type && body == other.body
  else
    false
  end
end

#to_sString

Converts the packet into an ASCII-encoded RCON Packet string for transmitting to the server.

Returns:

  • (String)


94
95
96
97
98
# File 'lib/rcon/packet.rb', line 94

def to_s
  [id, type_to_i, "#{body}#{TRAILER}", TRAILER].pack(PACKET_PACK_DIRECTIVE).then do |packet_str|
    "#{[packet_str.length].pack(INTEGER_PACK_DIRECTIVE)}#{packet_str}".force_encoding(ENCODING)
  end
end

#type_to_iInteger

Get the integer representation of the packet’s type, which is used in the string representation of the packet.

Returns:

  • (Integer)

Raises:



105
106
107
108
109
110
111
112
113
114
115
# File 'lib/rcon/packet.rb', line 105

def type_to_i
  type_sym = type.to_sym
  case type_sym
  when ->(t) { REQUEST_PACKET_TYPE.keys.include?(t) }
    REQUEST_PACKET_TYPE[type_sym]
  when ->(t) { RESPONSE_PACKET_TYPE.keys.include?(t) }
    RESPONSE_PACKET_TYPE[type_sym]
  else
    raise Error::InvalidPacketTypeError.new(type)
  end
end