Class: SteamCondenser::Servers::Sockets::GoldSrcSocket

Inherits:
Object
  • Object
show all
Includes:
Logging, BaseSocket
Defined in:
lib/steam-condenser/servers/sockets/goldsrc_socket.rb

Overview

This class represents a socket used to communicate with game servers based on the GoldSrc engine (e.g. Half-Life, Counter-Strike)

Author:

  • Sebastian Staudt

Instance Method Summary collapse

Methods included from Logging

formatter=, included, level=, #log, logdev=

Methods included from BaseSocket

#close, #receive_packet, #send, timeout=

Constructor Details

#initialize(ipaddress, port_number = 27015, is_hltv = false) ⇒ GoldSrcSocket

Creates a new socket to communicate with the server on the given IP address and port

Parameters:

  • ipaddress (String)

    Either the IP address or the DNS name of the server

  • port_number (Fixnum) (defaults to: 27015)

    The port the server is listening on

  • is_hltv (Boolean) (defaults to: false)

    true if the target server is a HTLV instance. HLTV behaves slightly different for RCON commands, this flag increases compatibility.


35
36
37
38
39
# File 'lib/steam-condenser/servers/sockets/goldsrc_socket.rb', line 35

def initialize(ipaddress, port_number = 27015, is_hltv = false)
  super ipaddress, port_number

  @is_hltv = is_hltv
end

Instance Method Details

#rcon_challengeObject

Requests a challenge number from the server to be used for further requests

Raises:

  • (Error::RCONBan)

    if the IP of the local machine has been banned on the game server

See Also:


130
131
132
133
134
135
136
137
138
139
# File 'lib/steam-condenser/servers/sockets/goldsrc_socket.rb', line 130

def rcon_challenge
  rcon_send 'challenge rcon'
  response = reply.response.strip

  if response.strip == 'You have been banned from this server.'
    raise SteamCondenser::Error::RCONBan
  end

  @rcon_challenge = response[14..-1]
end

#rcon_exec(password, command) ⇒ RCONGoldSrcResponse

Executes the given command on the server via RCON

Parameters:

  • password (String)

    The password to authenticate with the server

  • command (String)

    The command to execute on the server

Returns:

  • (RCONGoldSrcResponse)

    The response replied by the server

Raises:

See Also:


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/steam-condenser/servers/sockets/goldsrc_socket.rb', line 94

def rcon_exec(password, command)
  rcon_challenge if @rcon_challenge.nil? || @is_hltv

  rcon_send "rcon #@rcon_challenge #{password} #{command}"
  if @is_hltv
    begin
      response = reply.response
    rescue SteamCondenser::Error::Timeout
      response = ''
    end
  else
    response = reply.response
  end

  if response.strip == 'Bad rcon_password.'
    raise SteamCondenser::Error::RCONNoAuth
  elsif response.strip == 'You have been banned from this server.'
    raise SteamCondenser::Error::RCONBan
  end

  rcon_send "rcon #@rcon_challenge #{password}"

  begin
    response_part = reply.response
    response << response_part
  end while response_part.size > 0

  response
end

#rcon_send(command) ⇒ Object

Wraps the given command in a RCON request packet and send it to the server

Parameters:

  • command (String)

    The RCON command to send to the server


145
146
147
# File 'lib/steam-condenser/servers/sockets/goldsrc_socket.rb', line 145

def rcon_send(command)
  send SteamCondenser::Servers::Packets::RCON::RCONGoldSrcRequest.new(command)
end

#replyBasePacket

Reads a packet from the socket

The Source query protocol specifies a maximum packet size of 1,400 bytes. Bigger packets will be split over several UDP packets. This method reassembles split packets into single packet objects.

Returns:

  • (BasePacket)

    The packet replied from the server


48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/steam-condenser/servers/sockets/goldsrc_socket.rb', line 48

def reply
  receive_packet 1400

  if @buffer.long == 0xFFFFFFFE
    split_packets = []
    begin
      request_id = @buffer.long
      packet_number_and_count = @buffer.getbyte
      packet_count = packet_number_and_count & 0xF
      packet_number = (packet_number_and_count >> 4) + 1

      split_packets[packet_number - 1] = @buffer.get

      log.debug "Received packet #{packet_number} of #{packet_count} for request ##{request_id}"

      if split_packets.size < packet_count
        begin
          bytes_read = receive_packet
        rescue SteamCondenser::Error::Timeout
          bytes_read = 0
        end
      else
        bytes_read = 0
      end
    end while bytes_read > 0 && @buffer.long == 0xFFFFFFFE

    packet = SteamCondenser::Servers::Packets::SteamPacketFactory.reassemble_packet(split_packets)
  else
    packet = SteamCondenser::Servers::Packets::SteamPacketFactory.packet_from_data(@buffer.get)
  end

  log.debug "Got reply of type \"#{packet.class.to_s}\"."

  packet
end