steam-condenser 0.10.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. data/VERSION.yml +2 -2
  2. data/lib/datagram_channel.rb +30 -33
  3. data/lib/exceptions/packet_format_exception.rb +7 -3
  4. data/lib/exceptions/rcon_ban_exception.rb +7 -5
  5. data/lib/exceptions/rcon_no_auth_exception.rb +8 -6
  6. data/lib/exceptions/timeout_exception.rb +10 -4
  7. data/lib/socket_channel.rb +11 -17
  8. data/lib/steam/community/cacheable.rb +5 -7
  9. data/lib/steam/community/css/css_map.rb +31 -0
  10. data/lib/steam/community/css/css_stats.rb +116 -0
  11. data/lib/steam/community/css/css_weapon.rb +33 -0
  12. data/lib/steam/community/dods/dods_stats.rb +3 -3
  13. data/lib/steam/community/game_stats.rb +14 -13
  14. data/lib/steam/community/game_weapon.rb +3 -5
  15. data/lib/steam/community/l4d/abstract_l4d_stats.rb +4 -2
  16. data/lib/steam/community/l4d/l4d_explosive.rb +2 -2
  17. data/lib/steam/community/l4d/l4d_map.rb +3 -3
  18. data/lib/steam/community/steam_group.rb +2 -4
  19. data/lib/steam/community/steam_id.rb +2 -2
  20. data/lib/steam/community/tf2/tf2_class.rb +17 -17
  21. data/lib/steam/community/tf2/tf2_class_factory.rb +17 -17
  22. data/lib/steam/community/tf2/tf2_engineer.rb +9 -9
  23. data/lib/steam/community/tf2/tf2_medic.rb +9 -9
  24. data/lib/steam/community/tf2/tf2_sniper.rb +7 -7
  25. data/lib/steam/community/tf2/tf2_spy.rb +9 -9
  26. data/lib/steam/community/tf2/tf2_stats.rb +9 -9
  27. data/lib/steam/packets/a2a_ack_packet.rb +11 -9
  28. data/lib/steam/packets/a2a_ping_packet.rb +5 -4
  29. data/lib/steam/packets/a2m_get_servers_batch2_packet.rb +13 -12
  30. data/lib/steam/packets/a2s_info_packet.rb +8 -7
  31. data/lib/steam/packets/a2s_player_packet.rb +6 -6
  32. data/lib/steam/packets/a2s_rules_packet.rb +5 -5
  33. data/lib/steam/packets/a2s_serverquery_getchallenge_packet.rb +4 -3
  34. data/lib/steam/packets/m2a_server_batch_packet.rb +20 -22
  35. data/lib/steam/packets/rcon/rcon_auth_request.rb +5 -5
  36. data/lib/steam/packets/rcon/rcon_auth_response.rb +6 -6
  37. data/lib/steam/packets/rcon/rcon_exec_request.rb +5 -5
  38. data/lib/steam/packets/rcon/rcon_exec_response.rb +2 -2
  39. data/lib/steam/packets/rcon/rcon_goldsrc_request.rb +7 -7
  40. data/lib/steam/packets/rcon/rcon_goldsrc_response.rb +8 -8
  41. data/lib/steam/packets/rcon/rcon_packet.rb +12 -16
  42. data/lib/steam/packets/rcon/rcon_packet_factory.rb +19 -19
  43. data/lib/steam/packets/request_with_challenge.rb +5 -5
  44. data/lib/steam/packets/s2a_info2_packet.rb +28 -30
  45. data/lib/steam/packets/s2a_info_base_packet.rb +11 -16
  46. data/lib/steam/packets/s2a_info_detailed_packet.rb +30 -28
  47. data/lib/steam/packets/s2a_player_packet.rb +7 -9
  48. data/lib/steam/packets/s2a_rules_packet.rb +8 -12
  49. data/lib/steam/packets/s2c_challenge_packet.rb +7 -6
  50. data/lib/steam/packets/steam_packet.rb +7 -6
  51. data/lib/steam/packets/steam_packet_factory.rb +37 -38
  52. data/lib/steam/servers/game_server.rb +76 -86
  53. data/lib/steam/servers/goldsrc_server.rb +5 -5
  54. data/lib/steam/servers/master_server.rb +24 -24
  55. data/lib/steam/servers/source_server.rb +17 -19
  56. data/lib/steam/sockets/goldsrc_socket.rb +43 -46
  57. data/lib/steam/sockets/master_server_socket.rb +11 -13
  58. data/lib/steam/sockets/rcon_socket.rb +15 -17
  59. data/lib/steam/sockets/source_socket.rb +21 -21
  60. data/lib/steam/sockets/steam_socket.rb +25 -28
  61. data/lib/steam/steam_player.rb +3 -1
  62. data/lib/stringio_additions.rb +48 -0
  63. data/test/datagram_channel_tests.rb +8 -8
  64. data/test/query_tests.rb +15 -14
  65. data/test/rcon_tests.rb +32 -31
  66. data/test/socket_channel_tests.rb +7 -7
  67. data/test/steam/communtiy/steam_community_test_suite.rb +5 -2
  68. data/test/steam_community_tests.rb +4 -3
  69. data/test/stringio_additions_tests.rb +77 -0
  70. metadata +15 -8
  71. data/lib/byte_buffer.rb +0 -126
  72. data/lib/exceptions/buffer_underflow_exception.rb +0 -8
  73. data/test/byte_buffer_tests.rb +0 -76
@@ -1,12 +1,12 @@
1
1
  # This code is free software; you can redistribute it and/or modify it under the
2
2
  # terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008-2009, Sebastian Staudt
4
+ # Copyright (c) 2008-2010, Sebastian Staudt
5
5
 
6
- require "byte_buffer"
7
- require "steam/packets/steam_packet_factory"
8
- require "steam/packets/rcon/rcon_goldsrc_request"
9
- require "steam/sockets/steam_socket"
6
+ require 'stringio_additions'
7
+ require 'steam/packets/steam_packet_factory'
8
+ require 'steam/packets/rcon/rcon_goldsrc_request'
9
+ require 'steam/sockets/steam_socket'
10
10
 
11
11
  # The SourceSocket class is a sub class of SteamSocket respecting the
12
12
  # specifications of the Source query protocol.
@@ -21,18 +21,18 @@ class GoldSrcSocket < SteamSocket
21
21
  # maximum packet size of 1400 byte. Greater packets will be split over several
22
22
  # UDP packets. This method reassembles split packets into single packet
23
23
  # objects.
24
- def get_reply
25
- bytes_read = self.receive_packet 1400
26
-
27
- if @buffer.get_long == 0xFFFFFFFE
28
- split_packets = Array.new
24
+ def reply
25
+ bytes_read = receive_packet 1400
26
+
27
+ if @buffer.long == 0xFFFFFFFE
28
+ split_packets = []
29
29
  begin
30
30
  # Parsing of split packet headers
31
- request_id = @buffer.get_long
32
- packet_number_and_count = @buffer.get_byte.to_i
31
+ request_id = @buffer.long
32
+ packet_number_and_count = @buffer.byte.to_i
33
33
  packet_count = packet_number_and_count & 0xF
34
34
  packet_number = (packet_number_and_count >> 4) + 1
35
-
35
+
36
36
  # Caching of split packet data
37
37
  split_packets[packet_number - 1] = @buffer.get
38
38
 
@@ -41,68 +41,65 @@ class GoldSrcSocket < SteamSocket
41
41
  # Receiving the next packet
42
42
  if split_packets.size < packet_count
43
43
  begin
44
- bytes_read = self.receive_packet
44
+ bytes_read = receive_packet
45
45
  rescue TimeoutException
46
46
  bytes_read = 0
47
47
  end
48
48
  else
49
49
  bytes_read = 0
50
50
  end
51
- end while bytes_read > 0 && @buffer.get_long == 0xFFFFFFFE
52
-
51
+ end while bytes_read > 0 && @buffer.long == 0xFFFFFFFE
52
+
53
53
  packet = SteamPacketFactory.reassemble_packet(split_packets)
54
-
55
54
  else
56
- packet = SteamPacketFactory.get_packet_from_data(@buffer.get)
55
+ packet = SteamPacketFactory.packet_from_data(@buffer.get)
57
56
  end
58
57
 
59
58
  puts "Got reply of type \"#{packet.class.to_s}\"." if $DEBUG
60
59
 
61
- return packet
60
+ packet
62
61
  end
63
-
62
+
64
63
  def rcon_exec(password, command)
65
- self.rcon_get_challenge if @rcon_challenge.nil? or @is_hltv
66
-
67
- self.rcon_send "rcon #{@rcon_challenge} #{password} #{command}"
64
+ rcon_challenge if @rcon_challenge.nil? or @is_hltv
65
+
66
+ rcon_send "rcon #{@rcon_challenge} #{password} #{command}"
68
67
  if @is_hltv
69
68
  begin
70
- response = self.get_reply.get_response
69
+ response = reply.response
71
70
  rescue TimeoutException
72
- response = ""
71
+ response = ''
73
72
  end
74
73
  else
75
- response = self.get_reply.get_response
74
+ response = reply.response
76
75
  end
77
-
78
- if response.strip == "Bad rcon_password." or response.strip == "You have been banned from this server."
79
- raise RCONNoAuthException.new
76
+
77
+ if response.strip == 'Bad rcon_password.' or response.strip == 'You have been banned from this server.'
78
+ raise RCONNoAuthException
80
79
  end
81
-
80
+
82
81
  begin
83
- while true
84
- response_part = self.get_reply.get_response
82
+ loop do
83
+ response_part = reply.response
85
84
  response << response_part
86
85
  end
87
86
  rescue TimeoutException
88
87
  end
89
-
90
- return response
88
+
89
+ response
91
90
  end
92
-
93
- def rcon_get_challenge
94
- self.rcon_send "challenge rcon"
95
- response = self.get_reply.get_response.strip
96
-
97
- if response == "You have been banned from this server."
98
- raise RCONNoAuthException.new;
99
- end
100
-
91
+
92
+ def rcon_challenge
93
+ rcon_send 'challenge rcon'
94
+ response = reply.response.strip
95
+
96
+ raise RCONNoAuthException if response == 'You have been banned from this server.'
97
+
101
98
  @rcon_challenge = response[14..-1]
102
99
  end
103
-
100
+
104
101
  def rcon_send(command)
105
- self.send RCONGoldSrcRequest.new(command)
102
+ send RCONGoldSrcRequest.new(command)
106
103
  end
107
-
104
+
108
105
  end
@@ -1,20 +1,18 @@
1
1
  # This code is free software; you can redistribute it and/or modify it under the
2
2
  # terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008-2009, Sebastian Staudt
4
+ # Copyright (c) 2008-2010, Sebastian Staudt
5
5
 
6
- require "steam/sockets/steam_socket"
6
+ require 'steam/sockets/steam_socket'
7
7
 
8
8
  class MasterServerSocket < SteamSocket
9
-
10
- def get_reply
11
- self.receive_packet 1500
12
-
13
- if @buffer.get_long != 0xFFFFFFFF
14
- raise Exception.new("Master query response has wrong packet header.")
15
- end
16
-
17
- return SteamPacketFactory.get_packet_from_data(@buffer.get)
9
+
10
+ def reply
11
+ receive_packet 1500
12
+
13
+ raise Exception.new("Master query response has wrong packet header.") unless @buffer.long == 0xFFFFFFFF
14
+
15
+ SteamPacketFactory.packet_from_data(@buffer.get)
18
16
  end
19
-
20
- end
17
+
18
+ end
@@ -1,7 +1,7 @@
1
1
  # This code is free software; you can redistribute it and/or modify it under the
2
2
  # terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008-2009, Sebastian Staudt
4
+ # Copyright (c) 2008-2010, Sebastian Staudt
5
5
 
6
6
  require 'socket_channel'
7
7
  require 'exceptions/rcon_ban_exception'
@@ -17,35 +17,33 @@ class RCONSocket < SteamSocket
17
17
  end
18
18
 
19
19
  def send(data_packet)
20
- if !@channel.connected?
21
- @channel.connect @remote_socket
22
- end
20
+ @channel.connect @remote_socket unless @channel.connected?
23
21
 
24
- @buffer = ByteBuffer.wrap data_packet.get_bytes
22
+ @buffer = StringIO.new data_packet.bytes
25
23
  @channel.write @buffer
26
24
  end
27
25
 
28
- def get_reply
29
- if self.receive_packet(1440) == 0
30
- raise RCONBanException
31
- end
32
- packet_data = @buffer.array[0..@buffer.limit]
33
- packet_size = @buffer.get_long + 4
26
+ def reply
27
+ raise RCONBanException if receive_packet(1440) == 0
28
+
29
+ packet_data = @buffer.get
30
+ packet_size = @buffer.long + 4
31
+ @buffer.rewind
34
32
 
35
33
  if packet_size > 1440
36
- remaining_bytes = packet_size - @buffer.limit
34
+ remaining_bytes = packet_size - @buffer.size
37
35
  begin
38
36
  if remaining_bytes < 1440
39
- self.receive_packet remaining_bytes
37
+ receive_packet remaining_bytes
40
38
  else
41
- self.receive_packet 1440
39
+ receive_packet 1440
42
40
  end
43
- packet_data << @buffer.array[0..@buffer.limit]
44
- remaining_bytes -= @buffer.limit
41
+ packet_data << @buffer.get
42
+ remaining_bytes -= @buffer.size
45
43
  end while remaining_bytes > 0
46
44
  end
47
45
 
48
- return RCONPacketFactory.get_packet_from_data(packet_data)
46
+ RCONPacketFactory.packet_from_data(packet_data)
49
47
  end
50
48
 
51
49
  end
@@ -1,10 +1,10 @@
1
1
  # This code is free software; you can redistribute it and/or modify it under the
2
2
  # terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008-2009, Sebastian Staudt
4
+ # Copyright (c) 2008-2010, Sebastian Staudt
5
5
 
6
- require "byte_buffer"
7
- require "steam/sockets/steam_socket"
6
+ require 'stringio_additions'
7
+ require 'steam/sockets/steam_socket'
8
8
 
9
9
  # The SourceSocket class is a sub class of SteamSocket respecting the
10
10
  # specifications of the Source query protocol.
@@ -14,24 +14,24 @@ class SourceSocket < SteamSocket
14
14
  # maximum packet size of 1400 byte. Greater packets will be split over several
15
15
  # UDP packets. This method reassembles split packets into single packet
16
16
  # objects.
17
- def get_reply
18
- bytes_read = self.receive_packet 1400
17
+ def reply
18
+ bytes_read = receive_packet 1400
19
19
  is_compressed = false
20
20
 
21
- if @buffer.get_long == 0xFFFFFFFE
22
- split_packets = Array.new
21
+ if @buffer.long == 0xFFFFFFFE
22
+ split_packets = []
23
23
  begin
24
24
  # Parsing of split packet headers
25
- request_id = @buffer.get_long
25
+ request_id = @buffer.long
26
26
  is_compressed = ((request_id & 0x80000000) != 0)
27
- packet_count = @buffer.get_byte.to_i
28
- packet_number = @buffer.get_byte.to_i + 1
29
-
27
+ packet_count = @buffer.byte.to_i
28
+ packet_number = @buffer.byte.to_i + 1
29
+
30
30
  if is_compressed
31
- split_size = @buffer.get_long
32
- packet_checksum = @buffer.get_long
31
+ @buffer.long
32
+ packet_checksum = @buffer.long
33
33
  else
34
- split_size = @buffer.get_short
34
+ @buffer.short
35
35
  end
36
36
 
37
37
  # Caching of split packet data
@@ -42,22 +42,22 @@ class SourceSocket < SteamSocket
42
42
  # Receiving the next packet
43
43
  if split_packets.size < packet_count
44
44
  begin
45
- bytes_read = self.receive_packet
45
+ bytes_read = receive_packet
46
46
  rescue TimeoutException
47
47
  bytes_read = 0
48
48
  end
49
49
  else
50
50
  bytes_read = 0
51
51
  end
52
- end while bytes_read > 0 && @buffer.get_long == 0xFFFFFFFE
53
-
52
+ end while bytes_read > 0 && @buffer.long == 0xFFFFFFFE
53
+
54
54
  if is_compressed
55
55
  packet = SteamPacketFactory.reassemble_packet(split_packets, true, packet_checksum)
56
56
  else
57
57
  packet = SteamPacketFactory.reassemble_packet(split_packets)
58
58
  end
59
59
  else
60
- packet = SteamPacketFactory.get_packet_from_data(@buffer.get)
60
+ packet = SteamPacketFactory.packet_from_data(@buffer.get)
61
61
  end
62
62
 
63
63
  if is_compressed
@@ -65,8 +65,8 @@ class SourceSocket < SteamSocket
65
65
  else
66
66
  puts "Got reply of type \"#{packet.class.to_s}\"." if $DEBUG
67
67
  end
68
-
69
- return packet
68
+
69
+ packet
70
70
  end
71
-
71
+
72
72
  end
@@ -1,60 +1,57 @@
1
1
  # This code is free software; you can redistribute it and/or modify it under the
2
2
  # terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008-2009, Sebastian Staudt
4
+ # Copyright (c) 2008-2010, Sebastian Staudt
5
5
 
6
- require "abstract_class"
7
- require "byte_buffer"
8
- require "datagram_channel"
9
- require "ipaddr"
10
- require "exceptions/timeout_exception"
6
+ require 'abstract_class'
7
+ require 'datagram_channel'
8
+ require 'ipaddr'
9
+ require 'stringio_additions'
10
+ require 'exceptions/timeout_exception'
11
11
 
12
- # The SteamSocket class is a sub class of CondenserSocket respecting the
13
- # specifications of the Source query protocol.
12
+ # Defines common methods for sockets used to connect to game and master
13
+ # servers.
14
14
  class SteamSocket
15
-
15
+
16
16
  include AbstractClass
17
-
17
+
18
18
  def initialize(*args)
19
19
  @channel = DatagramChannel.open
20
20
  @channel.connect *args
21
21
  @channel.configure_blocking false
22
-
22
+
23
23
  @remote_socket = Socket.getaddrinfo args[0].to_s, args[1]
24
24
  end
25
25
 
26
- # Abstract get_reply method
27
- def get_reply
26
+ # Abstract +reply+ method
27
+ def reply
28
28
  raise NotImplementedError
29
29
  end
30
-
30
+
31
31
  def receive_packet(buffer_length = 0)
32
- if select([@channel.socket], nil, nil, 1) == nil
33
- raise TimeoutException.new
34
- end
32
+ raise TimeoutException if select([@channel.socket], nil, nil, 1).nil?
35
33
 
36
34
  if buffer_length == 0
37
- @buffer.clear
35
+ @buffer.truncate @buffer.size
38
36
  else
39
- @buffer = ByteBuffer.allocate buffer_length
37
+ @buffer = StringIO.allocate buffer_length
40
38
  end
41
-
42
- bytes_read = @channel.read(@buffer)
39
+
40
+ bytes_read = @channel.read @buffer
43
41
  @buffer.rewind
44
- @buffer.limit = bytes_read
45
-
42
+
46
43
  bytes_read
47
44
  end
48
-
45
+
49
46
  def send(data_packet)
50
47
  puts "Sending data packet of type \"#{data_packet.class.to_s}\"." if $DEBUG
51
48
 
52
- @buffer = ByteBuffer.wrap(data_packet.to_s)
53
- @channel.write(@buffer)
49
+ @buffer = StringIO.new data_packet.to_s
50
+ @channel.write @buffer
54
51
  end
55
-
52
+
56
53
  def finalize
57
54
  @channel.close
58
55
  end
59
-
56
+
60
57
  end
@@ -25,7 +25,9 @@ class SteamPlayer
25
25
  def add_info(real_id, name, steam_id, *player_data)
26
26
  @extended = true
27
27
 
28
- raise SteamCondenserException.new('Information to add belongs to a different player.') unless name == @name
28
+ unless name == @name
29
+ raise SteamCondenserException.new('Information to add belongs to a different player.')
30
+ end
29
31
 
30
32
  @real_id = real_id
31
33
  @steam_id = steam_id
@@ -0,0 +1,48 @@
1
+ # This code is free software; you can redistribute it and/or modify it under the
2
+ # terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2010, Sebastian Staudt
5
+
6
+ require 'stringio'
7
+
8
+ class StringIO
9
+
10
+ alias_method :data, :string
11
+
12
+ def self.allocate(size)
13
+ new "\0" * size
14
+ end
15
+
16
+ def byte
17
+ read(1)[0]
18
+ end
19
+
20
+ def float
21
+ read(4).unpack('e')[0]
22
+ end
23
+
24
+ def get
25
+ read remaining
26
+ end
27
+
28
+ def long
29
+ read(4).unpack('V')[0]
30
+ end
31
+
32
+ def remaining
33
+ size - pos
34
+ end
35
+
36
+ def short
37
+ read(2).unpack('v')[0]
38
+ end
39
+
40
+ def signed_long
41
+ read(4).unpack('l')[0]
42
+ end
43
+
44
+ def string
45
+ gets("\0")[0..-2]
46
+ end
47
+
48
+ end