steam-condenser 0.13.1 → 0.14.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.
- data/lib/exceptions/packet_format_exception.rb +12 -5
- data/lib/exceptions/rcon_ban_exception.rb +11 -3
- data/lib/exceptions/rcon_no_auth_exception.rb +10 -3
- data/lib/exceptions/steam_condenser_exception.rb +8 -5
- data/lib/exceptions/timeout_exception.rb +13 -3
- data/lib/exceptions/web_api_exception.rb +31 -23
- data/lib/steam-condenser.rb +9 -3
- data/lib/steam-condenser/community.rb +8 -1
- data/lib/steam-condenser/servers.rb +7 -1
- data/lib/steam-condenser/version.rb +2 -1
- data/lib/steam/community/cacheable.rb +4 -4
- data/lib/steam/community/game_inventory.rb +119 -0
- data/lib/steam/community/game_item.rb +38 -0
- data/lib/steam/community/game_stats.rb +10 -4
- data/lib/steam/community/portal2/portal2_inventory.rb +21 -0
- data/lib/steam/community/portal2/portal2_item.rb +35 -0
- data/lib/steam/community/portal2/portal2_stats.rb +28 -0
- data/lib/steam/community/tf2/tf2_inventory.rb +7 -37
- data/lib/steam/community/tf2/tf2_item.rb +8 -79
- data/lib/steam/community/tf2/tf2_stats.rb +10 -13
- data/lib/steam/community/web_api.rb +1 -0
- data/lib/steam/packets/a2m_get_servers_batch2_packet.rb +37 -4
- data/lib/steam/packets/a2s_info_packet.rb +10 -5
- data/lib/steam/packets/a2s_player_packet.rb +16 -6
- data/lib/steam/packets/a2s_rules_packet.rb +16 -4
- data/lib/steam/packets/a2s_serverquery_getchallenge_packet.rb +11 -5
- data/lib/steam/packets/c2m_checkmd5_packet.rb +10 -4
- data/lib/steam/packets/m2a_server_batch_packet.rb +19 -3
- data/lib/steam/packets/m2c_isvalidmd5_packet.rb +14 -5
- data/lib/steam/packets/m2s_requestrestart_packet.rb +14 -4
- data/lib/steam/packets/rcon/rcon_auth_request.rb +15 -3
- data/lib/steam/packets/rcon/rcon_auth_response.rb +17 -3
- data/lib/steam/packets/rcon/rcon_exec_request.rb +15 -3
- data/lib/steam/packets/rcon/rcon_exec_response.rb +20 -3
- data/lib/steam/packets/rcon/rcon_goldsrc_request.rb +18 -3
- data/lib/steam/packets/rcon/rcon_goldsrc_response.rb +17 -3
- data/lib/steam/packets/rcon/rcon_packet.rb +31 -3
- data/lib/steam/packets/rcon/rcon_packet_factory.rb +15 -5
- data/lib/steam/packets/rcon/rcon_terminator.rb +14 -5
- data/lib/steam/packets/request_with_challenge.rb +10 -5
- data/lib/steam/packets/s2a_info2_packet.rb +14 -5
- data/lib/steam/packets/s2a_info_base_packet.rb +16 -6
- data/lib/steam/packets/s2a_info_detailed_packet.rb +15 -8
- data/lib/steam/packets/s2a_logstring_packet.rb +11 -5
- data/lib/steam/packets/s2a_player_packet.rb +14 -6
- data/lib/steam/packets/s2a_rules_packet.rb +15 -5
- data/lib/steam/packets/s2c_challenge_packet.rb +17 -6
- data/lib/steam/packets/s2m_heartbeat2_packet.rb +18 -4
- data/lib/steam/packets/steam_packet.rb +14 -5
- data/lib/steam/packets/steam_packet_factory.rb +25 -2
- data/lib/steam/servers/game_server.rb +154 -25
- data/lib/steam/servers/goldsrc_server.rb +35 -3
- data/lib/steam/servers/master_server.rb +77 -23
- data/lib/steam/servers/server.rb +42 -3
- data/lib/steam/servers/source_server.rb +35 -11
- data/lib/stringio_additions.rb +48 -3
- data/test/query_tests.rb +4 -4
- metadata +11 -6
@@ -1,15 +1,33 @@
|
|
1
|
-
# This code is free software; you can redistribute it and/or modify it under
|
2
|
-
# terms of the new BSD License.
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2008-
|
4
|
+
# Copyright (c) 2008-2011, Sebastian Staudt
|
5
5
|
|
6
6
|
require 'steam/servers/game_server'
|
7
7
|
require 'steam/sockets/goldsrc_socket'
|
8
8
|
|
9
|
+
# This class represents a GoldSrc game server and can be used to query
|
10
|
+
# information about and remotely execute commands via RCON on the server
|
11
|
+
#
|
12
|
+
# A GoldSrc game server is an instance of the Half-Life Dedicated Server (HLDS)
|
13
|
+
# running games using Valve's GoldSrc engine, like Half-Life Deathmatch,
|
14
|
+
# Counter-Strike 1.6 or Team Fortress Classic.
|
15
|
+
#
|
16
|
+
# @author Sebastian Staudt
|
17
|
+
# @see SourceServer
|
9
18
|
class GoldSrcServer
|
10
19
|
|
11
20
|
include GameServer
|
12
21
|
|
22
|
+
# Creates a new instance of a GoldSrc server object
|
23
|
+
#
|
24
|
+
# @param [String] address Either an IP address, a DNS name or one of them
|
25
|
+
# combined with the port number. If a port number is given, e.g.
|
26
|
+
# 'server.example.com:27016' it will override the second argument.
|
27
|
+
# @param [Fixnum] port The port the server is listening on
|
28
|
+
# @raise [SteamCondenserException] if an host name cannot be resolved
|
29
|
+
# @param [Boolean] is_hltv HLTV servers need special treatment, so this is
|
30
|
+
# used to determine if the server is a HLTV server
|
13
31
|
def initialize(address, port = 27015, is_hltv = false)
|
14
32
|
super address, port
|
15
33
|
|
@@ -17,15 +35,29 @@ class GoldSrcServer
|
|
17
35
|
end
|
18
36
|
|
19
37
|
# Initializes the socket to communicate with the GoldSrc server
|
38
|
+
#
|
39
|
+
# @see GoldSrcSocket
|
20
40
|
def init_socket
|
21
41
|
@socket = GoldSrcSocket.new @ip_address, @port, @is_hltv
|
22
42
|
end
|
23
43
|
|
44
|
+
# Saves the password for authenticating the RCON communication with the
|
45
|
+
# server
|
46
|
+
#
|
47
|
+
# @param [String] password The RCON password of the server
|
48
|
+
# @return [true] GoldSrc's RCON does not preauthenticate connections so this
|
49
|
+
# method always returns `true`
|
50
|
+
# @see #rcon_exec
|
24
51
|
def rcon_auth(password)
|
25
52
|
@rcon_password = password
|
26
53
|
true
|
27
54
|
end
|
28
55
|
|
56
|
+
# Remotely executes a command on the server via RCON
|
57
|
+
#
|
58
|
+
# @param [String] command The command to execute on the server via RCON
|
59
|
+
# @return [String] The output of the executed command
|
60
|
+
# @see #rcon_auth
|
29
61
|
def rcon_exec(command)
|
30
62
|
@socket.rcon_exec(@rcon_password, command).strip
|
31
63
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
# This code is free software; you can redistribute it and/or modify it under
|
2
|
-
# terms of the new BSD License.
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
3
|
#
|
4
4
|
# Copyright (c) 2008-2011, Sebastian Staudt
|
5
5
|
|
@@ -9,35 +9,59 @@ require 'steam/packets/s2m_heartbeat2_packet'
|
|
9
9
|
require 'steam/servers/server'
|
10
10
|
require 'steam/sockets/master_server_socket'
|
11
11
|
|
12
|
+
# This class represents a Steam master server and can be used to get game
|
13
|
+
# servers which are publicly available
|
14
|
+
#
|
15
|
+
# An intance of this class can be used much like Steam's server browser to get
|
16
|
+
# a list of available game servers, including filters to narrow down the search
|
17
|
+
# results.
|
18
|
+
#
|
19
|
+
# @author Sebastian Staudt
|
12
20
|
class MasterServer
|
13
21
|
|
14
22
|
include Server
|
15
23
|
|
24
|
+
# The master server address to query for GoldSrc game servers
|
16
25
|
GOLDSRC_MASTER_SERVER = 'hl1master.steampowered.com', 27010
|
26
|
+
|
27
|
+
# The master server address to query for GoldSrc game servers
|
17
28
|
SOURCE_MASTER_SERVER = 'hl2master.steampowered.com', 27011
|
18
29
|
|
30
|
+
# The region code for the US east coast
|
19
31
|
REGION_US_EAST_COAST = 0x00
|
32
|
+
|
33
|
+
# The region code for the US west coast
|
20
34
|
REGION_US_WEST_COAST = 0x01
|
35
|
+
|
36
|
+
# The region code for South America
|
21
37
|
REGION_SOUTH_AMERICA = 0x02
|
38
|
+
|
39
|
+
# The region code for Europe
|
22
40
|
REGION_EUROPE = 0x03
|
41
|
+
|
42
|
+
# The region code for Asia
|
23
43
|
REGION_ASIA = 0x04
|
44
|
+
|
45
|
+
# The region code for Australia
|
24
46
|
REGION_AUSTRALIA = 0x05
|
47
|
+
|
48
|
+
# The region code for the Middle East
|
25
49
|
REGION_MIDDLE_EAST = 0x06
|
26
|
-
REGION_AFRICA = 0x07
|
27
|
-
REGION_ALL = 0xFF
|
28
50
|
|
29
|
-
#
|
30
|
-
|
31
|
-
super
|
51
|
+
# The region code for Africa
|
52
|
+
REGION_AFRICA = 0x07
|
32
53
|
|
33
|
-
|
34
|
-
|
54
|
+
# The region code for the whole world
|
55
|
+
REGION_ALL = 0xFF
|
35
56
|
|
36
|
-
# Request a challenge number from the master server.
|
37
|
-
#
|
57
|
+
# Request a challenge number from the master server.
|
58
|
+
#
|
59
|
+
# This is used for further communication with the master server.
|
38
60
|
#
|
39
|
-
# Please note that this is
|
40
|
-
#
|
61
|
+
# @note Please note that this is **not** needed for finding servers using
|
62
|
+
# {#servers}.
|
63
|
+
# @return The challenge number from the master server
|
64
|
+
# @see #send_heartbeat
|
41
65
|
def challenge
|
42
66
|
failsafe do
|
43
67
|
@socket.send C2M_CHECKMD5_Packet.new
|
@@ -46,19 +70,43 @@ class MasterServer
|
|
46
70
|
end
|
47
71
|
|
48
72
|
# Initializes the socket to communicate with the master server
|
73
|
+
#
|
74
|
+
# @see MasterServerSocket
|
49
75
|
def init_socket
|
50
76
|
@socket = MasterServerSocket.new @ip_address, @port
|
51
77
|
end
|
52
78
|
|
79
|
+
# Returns a list of game server matching the given region and filters
|
80
|
+
#
|
81
|
+
# Filtering:
|
82
|
+
# Instead of filtering the results sent by the master server locally, you
|
83
|
+
# should at least use the following filters to narrow down the results sent by
|
84
|
+
# the master server.
|
85
|
+
#
|
86
|
+
# Available filters:
|
87
|
+
#
|
88
|
+
# * `\type\d`: Request only dedicated servers
|
89
|
+
# * `\secure\1`: Request only secure servers
|
90
|
+
# * `\gamedir\[mod]`: Request only servers of a specific mod
|
91
|
+
# * `\map\[mapname]`: Request only servers running a specific map
|
92
|
+
# * `\linux\1`: Request only linux servers
|
93
|
+
# * `\emtpy\1`: Request only **non**-empty servers
|
94
|
+
# * `\full\`: Request only servers **not** full
|
95
|
+
# * `\proxy\1`: Request only spectator proxy servers
|
96
|
+
#
|
97
|
+
# @note Receiving all servers from the master server is taking quite some
|
98
|
+
# time.
|
99
|
+
# @param [Fixnum] region_code The region code to specify a location of the
|
100
|
+
# game servers
|
101
|
+
# @param [String] filters The filters that game servers should match
|
102
|
+
# @return [Array<Array<String>>] A list of game servers matching the given
|
103
|
+
# region and filters
|
104
|
+
# @see A2M_GET_SERVERS_BATCH2_Packet
|
53
105
|
def servers(region_code = MasterServer::REGION_ALL, filters = '')
|
54
|
-
update_servers region_code, filters if @server_array.empty?
|
55
|
-
@server_array
|
56
|
-
end
|
57
|
-
|
58
|
-
def update_servers(region_code, filters)
|
59
106
|
fail_count = 0
|
60
107
|
finished = false
|
61
108
|
current_server = '0.0.0.0:0'
|
109
|
+
server_array = []
|
62
110
|
|
63
111
|
failsafe do
|
64
112
|
begin
|
@@ -70,7 +118,7 @@ class MasterServer
|
|
70
118
|
finished = true
|
71
119
|
else
|
72
120
|
current_server = server
|
73
|
-
|
121
|
+
server_array << server.split(':')
|
74
122
|
end
|
75
123
|
end
|
76
124
|
fail_count = 0
|
@@ -79,16 +127,22 @@ class MasterServer
|
|
79
127
|
end
|
80
128
|
end while !finished
|
81
129
|
end
|
130
|
+
|
131
|
+
server_array
|
82
132
|
end
|
83
133
|
|
84
134
|
# Sends a constructed heartbeat to the master server
|
85
135
|
#
|
86
136
|
# This can be used to check server versions externally.
|
87
137
|
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
91
|
-
# packets.
|
138
|
+
# @param [Hash<Symbol, Object>] The data to send with the heartbeat request
|
139
|
+
# @raise [SteamCondenserException] if heartbeat data is missing the
|
140
|
+
# challenge number or the reply cannot be parsed
|
141
|
+
# @return [Array<SteamPacket>] Zero or more reply packets from the server.
|
142
|
+
# Zero means either the heartbeat was accepted by the master or there
|
143
|
+
# was a timeout. So usually it's best to repeat a heartbeat a few
|
144
|
+
# times when not receiving any packets.
|
145
|
+
# @see S2M_HEARTBEAT2_Packet
|
92
146
|
def send_heartbeat(data)
|
93
147
|
failsafe do
|
94
148
|
@socket.send S2M_HEARTBEAT2_Packet.new(data)
|
data/lib/steam/servers/server.rb
CHANGED
@@ -7,10 +7,30 @@ require 'socket'
|
|
7
7
|
|
8
8
|
# This module is included by all classes implementing server functionality
|
9
9
|
#
|
10
|
-
# It provides basic name resolution features
|
10
|
+
# It provides basic name resolution features and the ability to rotate between
|
11
|
+
# different IP addresses belonging to a single DNS name.
|
12
|
+
#
|
13
|
+
# @author Sebastian Staudt
|
11
14
|
module Server
|
12
15
|
|
16
|
+
# Returns a list of host names associated with this server
|
17
|
+
#
|
18
|
+
# @return [Array<String>] The host names of this server
|
19
|
+
attr_reader :host_names
|
20
|
+
|
21
|
+
# Returns a list of IP addresses associated with this server
|
22
|
+
#
|
23
|
+
# @return [Array<String>] The IP addresses of this server
|
24
|
+
attr_reader :ip_addresses
|
25
|
+
|
13
26
|
# Creates a new server instance with the given address and port
|
27
|
+
#
|
28
|
+
# @param [String] address Either an IP address, a DNS name or one of them
|
29
|
+
# combined with the port number. If a port number is given, e.g.
|
30
|
+
# 'server.example.com:27016' it will override the second argument.
|
31
|
+
# @param [Fixnum] port The port the server is listening on
|
32
|
+
# @see init_socket
|
33
|
+
# @raise [SteamCondenserException] if an host name cannot be resolved
|
14
34
|
def initialize(address, port = nil)
|
15
35
|
address = address.to_s
|
16
36
|
address, port = address.split(':', 2) if address.include? ':'
|
@@ -33,8 +53,17 @@ module Server
|
|
33
53
|
|
34
54
|
# Rotate this server's IP address to the next one in the IP list
|
35
55
|
#
|
36
|
-
#
|
37
|
-
#
|
56
|
+
# If this method returns `true`, it indicates that all IP addresses have been
|
57
|
+
# used, hinting at the server(s) being unreachable. An appropriate action
|
58
|
+
# should be taken to inform the user.
|
59
|
+
#
|
60
|
+
# Servers with only one IP address will always cause this method to return
|
61
|
+
# `true` and the sockets will not be reinitialized.
|
62
|
+
#
|
63
|
+
# @return [Boolean] `true`, if the IP list reached its end. If the list
|
64
|
+
# contains only one IP address, this method will instantly return
|
65
|
+
# `true`
|
66
|
+
# @see #init_socket
|
38
67
|
def rotate_ip
|
39
68
|
return true if @ip_addresses.size == 1
|
40
69
|
|
@@ -54,6 +83,9 @@ module Server
|
|
54
83
|
# in the server's IP list and the execution will be repeated for the next IP
|
55
84
|
# address. If the IP rotation reaches the end of the list, the exception will
|
56
85
|
# be reraised.
|
86
|
+
#
|
87
|
+
# @param [Proc] proc The action to be executed in a failsafe way
|
88
|
+
# @see #rotate_ip
|
57
89
|
def failsafe(&proc)
|
58
90
|
begin
|
59
91
|
proc.call
|
@@ -63,4 +95,11 @@ module Server
|
|
63
95
|
end
|
64
96
|
end
|
65
97
|
|
98
|
+
# Initializes the socket(s) to communicate with the server
|
99
|
+
#
|
100
|
+
# @abstract Must be implemented in including classes to prepare sockets for
|
101
|
+
# server communication
|
102
|
+
def init_socket
|
103
|
+
end
|
104
|
+
|
66
105
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
# This code is free software; you can redistribute it and/or modify it under
|
2
|
-
# terms of the new BSD License.
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
3
|
#
|
4
4
|
# Copyright (c) 2008-2011, Sebastian Staudt
|
5
5
|
|
@@ -12,20 +12,45 @@ require 'steam/servers/game_server'
|
|
12
12
|
require 'steam/sockets/rcon_socket'
|
13
13
|
require 'steam/sockets/source_socket'
|
14
14
|
|
15
|
+
# This class represents a Source game server and can be used to query
|
16
|
+
# information about and remotely execute commands via RCON on the server
|
17
|
+
#
|
18
|
+
# A Source game server is an instance of the Source Dedicated Server (SrcDS)
|
19
|
+
# running games using Valve's Source engine, like Counter-Strike: Source,
|
20
|
+
# Team Fortress 2 or Left4Dead.
|
21
|
+
#
|
22
|
+
# @author Sebastian Staudt
|
23
|
+
# @see GoldSrcServer
|
15
24
|
class SourceServer
|
16
25
|
|
17
26
|
include GameServer
|
18
27
|
|
28
|
+
# Creates a new instance of a server object representing a Source server,
|
29
|
+
# i.e. SrcDS instance
|
30
|
+
#
|
31
|
+
# @param [String] address Either an IP address, a DNS name or one of them
|
32
|
+
# combined with the port number. If a port number is given, e.g.
|
33
|
+
# 'server.example.com:27016' it will override the second argument.
|
34
|
+
# @param [Fixnum] port The port the server is listening on
|
35
|
+
# @raise [SteamCondenserException] if an host name cannot be resolved
|
19
36
|
def initialize(address, port = 27015)
|
20
37
|
super
|
21
38
|
end
|
22
39
|
|
23
40
|
# Initializes the sockets to communicate with the Source server
|
41
|
+
#
|
42
|
+
# @see RCONSocket
|
43
|
+
# @see SourceSocket
|
24
44
|
def init_socket
|
25
45
|
@rcon_socket = RCONSocket.new @ip_address, @port
|
26
46
|
@socket = SourceSocket.new @ip_address, @port
|
27
47
|
end
|
28
48
|
|
49
|
+
# Authenticates the connection for RCON communication with the server
|
50
|
+
#
|
51
|
+
# @param [String] password The RCON password of the server
|
52
|
+
# @return [Boolean] whether authentication was successful
|
53
|
+
# @see #rcon_exec
|
29
54
|
def rcon_auth(password)
|
30
55
|
@rcon_request_id = rand 2**16
|
31
56
|
|
@@ -38,22 +63,21 @@ class SourceServer
|
|
38
63
|
reply.request_id == @rcon_request_id
|
39
64
|
end
|
40
65
|
|
66
|
+
# Remotely executes a command on the server via RCON
|
67
|
+
#
|
68
|
+
# @param [String] command The command to execute on the server via RCON
|
69
|
+
# @return [String] The output of the executed command
|
70
|
+
# @see #rcon_auth
|
41
71
|
def rcon_exec(command)
|
42
72
|
@rcon_socket.send RCONExecRequest.new(@rcon_request_id, command)
|
43
73
|
@rcon_socket.send RCONTerminator.new(@rcon_request_id)
|
44
|
-
response_packets = []
|
45
74
|
|
75
|
+
response = ''
|
46
76
|
begin
|
47
77
|
response_packet = @rcon_socket.reply
|
48
|
-
redo if response_packet.nil?
|
49
78
|
raise RCONNoAuthException.new if response_packet.is_a? RCONAuthResponse
|
50
|
-
|
51
|
-
end while response_packet.response.size > 0
|
52
|
-
|
53
|
-
response = ''
|
54
|
-
response_packets.each do |packet|
|
55
|
-
response << packet.response
|
56
|
-
end
|
79
|
+
response << response_packet.response
|
80
|
+
end while response.length == 0 || response_packet.response.size > 0
|
57
81
|
|
58
82
|
response.strip
|
59
83
|
end
|
data/lib/stringio_additions.rb
CHANGED
@@ -1,44 +1,89 @@
|
|
1
|
-
# This code is free software; you can redistribute it and/or modify it under
|
2
|
-
# terms of the new BSD License.
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
3
|
#
|
4
|
-
# Copyright (c) 2010, Sebastian Staudt
|
4
|
+
# Copyright (c) 2010-2011, Sebastian Staudt
|
5
5
|
|
6
6
|
require 'stringio'
|
7
7
|
|
8
|
+
# This extends the `StringIO` class from Ruby's standard library. It adds some
|
9
|
+
# methods to handle byte-wise input from a `StringIO` object.
|
10
|
+
#
|
11
|
+
# @author Sebastian Staudt
|
8
12
|
class StringIO
|
9
13
|
|
14
|
+
# Creates a new instance of `StringIO` with the given size and fills it with
|
15
|
+
# zero-bytes.
|
16
|
+
#
|
17
|
+
# @param [Fixnum] size The size the new instance should have
|
18
|
+
# @return [StringIO] A new `StringIO` instance with the given size, filled
|
19
|
+
# with zero-bytes
|
10
20
|
def self.allocate(size)
|
11
21
|
new "\0" * size
|
12
22
|
end
|
13
23
|
|
24
|
+
# Reads a single byte from the current position of the byte stream
|
25
|
+
#
|
26
|
+
# @return [Fixnum] The numeric value of the byte at the current position
|
14
27
|
def byte
|
15
28
|
read(1)[0].ord
|
16
29
|
end
|
17
30
|
|
31
|
+
# Reads a floating-point integer (32 bit) from the current position of the
|
32
|
+
# byte stream
|
33
|
+
#
|
34
|
+
# @return [Float] The floating-point integer read from the byte stream
|
18
35
|
def float
|
19
36
|
read(4).unpack('e')[0]
|
20
37
|
end
|
21
38
|
|
39
|
+
# Reads the whole remaining content of the byte stream from the current
|
40
|
+
# position to the end
|
41
|
+
#
|
42
|
+
# @return [String] The remainder of the byte stream starting from the current
|
43
|
+
# position of the byte stream
|
22
44
|
def get
|
23
45
|
read remaining
|
24
46
|
end
|
25
47
|
|
48
|
+
# Reads an unsigned long integer (32 bit) from the current position of the
|
49
|
+
# byte stream
|
50
|
+
#
|
51
|
+
# @return [Fixnum] The unsigned long integer read from the byte stream
|
26
52
|
def long
|
27
53
|
read(4).unpack('V')[0]
|
28
54
|
end
|
29
55
|
|
56
|
+
# Returns the remaining number of bytes from the current position to the end
|
57
|
+
# of the byte stream
|
58
|
+
#
|
59
|
+
# @return [Fixnum] The number of bytes until the end of the stream
|
30
60
|
def remaining
|
31
61
|
size - pos
|
32
62
|
end
|
33
63
|
|
64
|
+
# Reads an unsigned short integer (16 bit) from the current position of the
|
65
|
+
# byte stream
|
66
|
+
#
|
67
|
+
# @return [Fixnum] The unsigned short integer read from the byte stream
|
34
68
|
def short
|
35
69
|
read(2).unpack('v')[0]
|
36
70
|
end
|
37
71
|
|
72
|
+
# Reads a signed long integer (32 bit) from the current position of the byte
|
73
|
+
# stream
|
74
|
+
#
|
75
|
+
# @return [Fixnum] The signed long integer read from the byte stream
|
38
76
|
def signed_long
|
39
77
|
read(4).unpack('l')[0]
|
40
78
|
end
|
41
79
|
|
80
|
+
# Reads a zero-byte terminated string from the current position of the byte
|
81
|
+
# stream
|
82
|
+
#
|
83
|
+
# This reads the stream up until the first occurance of a zero-byte or the
|
84
|
+
# end of the stream. The zero-byte is not included in the returned string.
|
85
|
+
#
|
86
|
+
# @return [String] The zero-byte terminated string read from the byte stream
|
42
87
|
def cstring
|
43
88
|
gets("\0")[0..-2]
|
44
89
|
end
|