Class: SteamCondenser::Servers::Sockets::SourceSocket

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

Overview

This class represents a socket used to communicate with game servers based on the Source engine (e.g. Team Fortress 2, Counter-Strike: Source)

Author:

  • Sebastian Staudt

Instance Method Summary collapse

Methods included from Logging

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

Methods included from BaseSocket

#close, #initialize, #receive_packet, #send, timeout=

Instance Method Details

#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. Additionally Source may compress big packets using bzip2. Those packets will be compressed.


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
# File 'lib/steam-condenser/servers/sockets/source_socket.rb', line 29

def reply
  receive_packet 1400
  is_compressed = false
  packet_checksum = 0

  if @buffer.long == 0xFFFFFFFE
    split_packets = []
    begin
      request_id = @buffer.long
      is_compressed = ((request_id & 0x80000000) != 0)
      packet_count = @buffer.getbyte
      packet_number = @buffer.getbyte + 1

      if is_compressed
        @buffer.long
        packet_checksum = @buffer.long
      else
        @buffer.short
      end

      split_packets[packet_number - 1] = @buffer.get

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

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

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

  if log.debug?
    packet_class = packet.class.name[/[^:]*\z/]
    if is_compressed
      log.debug "Got compressed reply of type \"#{packet_class}\"."
    else
      log.debug "Got reply of type \"#{packet_class}\"."
    end
  end

  packet
end