steam-condenser 0.8.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/LICENSE +25 -0
- data/README.md +30 -0
- data/Rakefile +42 -0
- data/lib/abstract_class.rb +40 -0
- data/lib/byte_buffer.rb +126 -0
- data/lib/datagram_channel.rb +70 -0
- data/lib/exceptions/buffer_underflow_exception.rb +10 -0
- data/lib/exceptions/packet_format_exception.rb +12 -0
- data/lib/exceptions/rcon_no_auth_exception.rb +14 -0
- data/lib/exceptions/steam_condenser_exception.rb +8 -0
- data/lib/exceptions/timeout_exception.rb +10 -0
- data/lib/socket_channel.rb +54 -0
- data/lib/steam-condenser.rb +3 -0
- data/lib/steam/community/dods/dods_class.rb +32 -0
- data/lib/steam/community/dods/dods_stats.rb +47 -0
- data/lib/steam/community/dods/dods_weapon.rb +54 -0
- data/lib/steam/community/game_achievement.rb +26 -0
- data/lib/steam/community/game_class.rb +15 -0
- data/lib/steam/community/game_stats.rb +92 -0
- data/lib/steam/community/game_weapon.rb +29 -0
- data/lib/steam/community/l4d/l4d_explosive.rb +23 -0
- data/lib/steam/community/l4d/l4d_map.rb +34 -0
- data/lib/steam/community/l4d/l4d_stats.rb +166 -0
- data/lib/steam/community/l4d/l4d_weapon.rb +23 -0
- data/lib/steam/community/steam_group.rb +16 -0
- data/lib/steam/community/steam_id.rb +212 -0
- data/lib/steam/community/tf2/tf2_class.rb +31 -0
- data/lib/steam/community/tf2/tf2_class_factory.rb +38 -0
- data/lib/steam/community/tf2/tf2_engineer.rb +25 -0
- data/lib/steam/community/tf2/tf2_medic.rb +22 -0
- data/lib/steam/community/tf2/tf2_sniper.rb +20 -0
- data/lib/steam/community/tf2/tf2_spy.rb +23 -0
- data/lib/steam/community/tf2/tf2_stats.rb +39 -0
- data/lib/steam/packets/a2a_ack_packet.rb +21 -0
- data/lib/steam/packets/a2a_ping_packet.rb +18 -0
- data/lib/steam/packets/a2m_get_servers_batch2_packet.rb +25 -0
- data/lib/steam/packets/a2s_info_packet.rb +18 -0
- data/lib/steam/packets/a2s_player_packet.rb +22 -0
- data/lib/steam/packets/a2s_rules_packet.rb +21 -0
- data/lib/steam/packets/a2s_serverquery_getchallenge_packet.rb +18 -0
- data/lib/steam/packets/m2a_server_batch_packet.rb +37 -0
- data/lib/steam/packets/rcon/rcon_auth_request.rb +16 -0
- data/lib/steam/packets/rcon/rcon_auth_response.rb +16 -0
- data/lib/steam/packets/rcon/rcon_exec_request.rb +16 -0
- data/lib/steam/packets/rcon/rcon_exec_response.rb +20 -0
- data/lib/steam/packets/rcon/rcon_goldsrc_request.rb +20 -0
- data/lib/steam/packets/rcon/rcon_goldsrc_response.rb +20 -0
- data/lib/steam/packets/rcon/rcon_packet.rb +36 -0
- data/lib/steam/packets/rcon/rcon_packet_factory.rb +37 -0
- data/lib/steam/packets/request_with_challenge.rb +16 -0
- data/lib/steam/packets/s2a_info2_packet.rb +48 -0
- data/lib/steam/packets/s2a_info_base_packet.rb +29 -0
- data/lib/steam/packets/s2a_info_detailed_packet.rb +50 -0
- data/lib/steam/packets/s2a_player_packet.rb +32 -0
- data/lib/steam/packets/s2a_rules_packet.rb +33 -0
- data/lib/steam/packets/s2c_challenge_packet.rb +23 -0
- data/lib/steam/packets/steam_packet.rb +48 -0
- data/lib/steam/packets/steam_packet_factory.rb +90 -0
- data/lib/steam/servers/game_server.rb +222 -0
- data/lib/steam/servers/goldsrc_server.rb +36 -0
- data/lib/steam/servers/master_server.rb +60 -0
- data/lib/steam/servers/source_server.rb +65 -0
- data/lib/steam/sockets/goldsrc_socket.rb +108 -0
- data/lib/steam/sockets/master_server_socket.rb +20 -0
- data/lib/steam/sockets/rcon_socket.rb +50 -0
- data/lib/steam/sockets/source_socket.rb +72 -0
- data/lib/steam/sockets/steam_socket.rb +63 -0
- data/lib/steam/steam_player.rb +51 -0
- data/test/query_tests.rb +71 -0
- data/test/rcon_tests.rb +79 -0
- data/test/steam_community_tests.rb +36 -0
- metadata +132 -0
@@ -0,0 +1,36 @@
|
|
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) 2008-2009, Sebastian Staudt
|
5
|
+
|
6
|
+
require "steam/servers/game_server"
|
7
|
+
require "steam/sockets/goldsrc_socket"
|
8
|
+
|
9
|
+
class GoldSrcServer < GameServer
|
10
|
+
|
11
|
+
# Splits the player status obtained with +rcon status+
|
12
|
+
def self.split_player_status(player_status)
|
13
|
+
player_data = player_status.match(/#( \d|\d\d) +"(.*)" +(\d+) +(.*)/).to_a[1..-1]
|
14
|
+
player_data[3] = player_data[3].split
|
15
|
+
player_data.flatten!
|
16
|
+
player_data[0] = player_data[2]
|
17
|
+
player_data.delete_at(2)
|
18
|
+
player_data.delete_at(4)
|
19
|
+
player_data
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(ip_address, port_number = 27015, is_hltv = false)
|
23
|
+
super port_number
|
24
|
+
@socket = GoldSrcSocket.new ip_address, port_number, is_hltv
|
25
|
+
end
|
26
|
+
|
27
|
+
def rcon_auth(password)
|
28
|
+
@rcon_password = password
|
29
|
+
return true
|
30
|
+
end
|
31
|
+
|
32
|
+
def rcon_exec(command)
|
33
|
+
return @socket.rcon_exec(@rcon_password, command).strip
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,60 @@
|
|
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) 2008-2009, Sebastian Staudt
|
5
|
+
#
|
6
|
+
# $Id$
|
7
|
+
|
8
|
+
require "steam/packets/a2m_get_servers_batch2_packet"
|
9
|
+
require "steam/sockets/master_server_socket"
|
10
|
+
|
11
|
+
class MasterServer
|
12
|
+
|
13
|
+
GOLDSRC_MASTER_SERVER = "hl1master.steampowered.com", 27010
|
14
|
+
SOURCE_MASTER_SERVER = "hl2master.steampowered.com", 27011
|
15
|
+
|
16
|
+
REGION_US_EAST_COAST = 0x00
|
17
|
+
REGION_US_WEST_COAST = 0x01
|
18
|
+
REGION_SOUTH_AMERICA = 0x02
|
19
|
+
REGION_EUROPE = 0x03
|
20
|
+
REGION_ASIA = 0x04
|
21
|
+
REGION_AUSTRALIA = 0x05
|
22
|
+
REGION_MIDDLE_EAST = 0x06
|
23
|
+
REGION_AFRICA = 0x07
|
24
|
+
REGION_ALL = 0xFF
|
25
|
+
|
26
|
+
def initialize(master_server_address, master_server_port)
|
27
|
+
@socket = MasterServerSocket.new master_server_address, master_server_port
|
28
|
+
@server_array = Array.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_servers(region_code = MasterServer::REGION_ALL, filters = "")
|
32
|
+
if @server_array.empty?
|
33
|
+
self.update_servers region_code, filters
|
34
|
+
end
|
35
|
+
|
36
|
+
return @server_array
|
37
|
+
end
|
38
|
+
|
39
|
+
def update_servers(region_code, filters)
|
40
|
+
finished = false
|
41
|
+
current_server = "0.0.0.0:0"
|
42
|
+
|
43
|
+
begin
|
44
|
+
@socket.send A2M_GET_SERVERS_BATCH2_Packet.new(region_code, current_server, filters)
|
45
|
+
begin
|
46
|
+
servers = @socket.get_reply.get_servers
|
47
|
+
servers.each do |server|
|
48
|
+
if server == "0.0.0.0:0"
|
49
|
+
finished = true
|
50
|
+
else
|
51
|
+
current_server = server
|
52
|
+
@server_array << server.split(":")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
rescue TimeoutException
|
56
|
+
end
|
57
|
+
end while !finished
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,65 @@
|
|
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) 2008-2009, Sebastian Staudt
|
5
|
+
|
6
|
+
require "exceptions/rcon_no_auth_exception"
|
7
|
+
require "steam/packets/rcon/rcon_auth_request"
|
8
|
+
require "steam/packets/rcon/rcon_auth_response"
|
9
|
+
require "steam/packets/rcon/rcon_exec_request"
|
10
|
+
require "steam/servers/game_server"
|
11
|
+
require "steam/sockets/rcon_socket"
|
12
|
+
require "steam/sockets/source_socket"
|
13
|
+
|
14
|
+
class SourceServer < GameServer
|
15
|
+
|
16
|
+
# Splits the player status obtained with +rcon status+
|
17
|
+
def self.split_player_status(player_status)
|
18
|
+
player_data = player_status.match(/#( \d|\d\d) +"(.*)" +(.*)/).to_a[1..-1]
|
19
|
+
player_data[2] = player_data[2].split
|
20
|
+
player_data.flatten
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(ip_address, port_number = 27015)
|
24
|
+
super port_number
|
25
|
+
@rcon_socket = RCONSocket.new ip_address, port_number
|
26
|
+
@socket = SourceSocket.new ip_address, port_number
|
27
|
+
end
|
28
|
+
|
29
|
+
def rcon_auth(password)
|
30
|
+
@rcon_request_id = rand 2**16
|
31
|
+
|
32
|
+
@rcon_socket.send RCONAuthRequest.new(@rcon_request_id, password)
|
33
|
+
@rcon_socket.get_reply
|
34
|
+
reply = @rcon_socket.get_reply
|
35
|
+
|
36
|
+
if reply.request_id == -1
|
37
|
+
raise RCONNoAuthException.new
|
38
|
+
end
|
39
|
+
|
40
|
+
return reply.get_request_id == @rcon_request_id
|
41
|
+
end
|
42
|
+
|
43
|
+
def rcon_exec(command)
|
44
|
+
@rcon_socket.send RCONExecRequest.new(@rcon_request_id, command)
|
45
|
+
response_packets = Array.new
|
46
|
+
|
47
|
+
begin
|
48
|
+
begin
|
49
|
+
response_packet = @rcon_socket.get_reply
|
50
|
+
raise RCONNoAuthException.new if response_packet.is_a? RCONAuthResponse
|
51
|
+
response_packets << response_packet
|
52
|
+
end while true
|
53
|
+
rescue TimeoutException
|
54
|
+
raise $! if response_packets.empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
response = String.new
|
58
|
+
response_packets.each do |packet|
|
59
|
+
response << packet.get_response
|
60
|
+
end
|
61
|
+
|
62
|
+
return response.strip
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,108 @@
|
|
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) 2008-2009, Sebastian Staudt
|
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"
|
10
|
+
|
11
|
+
# The SourceSocket class is a sub class of SteamSocket respecting the
|
12
|
+
# specifications of the Source query protocol.
|
13
|
+
class GoldSrcSocket < SteamSocket
|
14
|
+
|
15
|
+
def initialize(ipaddress, port_number = 27015, is_hltv = false)
|
16
|
+
super ipaddress, port_number
|
17
|
+
@is_hltv = is_hltv
|
18
|
+
end
|
19
|
+
|
20
|
+
# Reads a packet from the channel. The Source query protocol specifies a
|
21
|
+
# maximum packet size of 1400 byte. Greater packets will be split over several
|
22
|
+
# UDP packets. This method reassembles split packets into single packet
|
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
|
29
|
+
begin
|
30
|
+
# Parsing of split packet headers
|
31
|
+
request_id = @buffer.get_long
|
32
|
+
packet_number_and_count = @buffer.get_byte.to_i
|
33
|
+
packet_count = packet_number_and_count & 0xF
|
34
|
+
packet_number = (packet_number_and_count >> 4) + 1
|
35
|
+
|
36
|
+
# Caching of split packet data
|
37
|
+
split_packets[packet_number - 1] = @buffer.get
|
38
|
+
|
39
|
+
warn "Received packet #{packet_number} of #{packet_count} for request ##{request_id}"
|
40
|
+
|
41
|
+
# Receiving the next packet
|
42
|
+
if split_packets.size < packet_count
|
43
|
+
begin
|
44
|
+
bytes_read = self.receive_packet
|
45
|
+
rescue TimeoutException
|
46
|
+
bytes_read = 0
|
47
|
+
end
|
48
|
+
else
|
49
|
+
bytes_read = 0
|
50
|
+
end
|
51
|
+
end while bytes_read > 0 && @buffer.get_long == 0xFFFFFFFE
|
52
|
+
|
53
|
+
packet = SteamPacketFactory.reassemble_packet(split_packets)
|
54
|
+
|
55
|
+
else
|
56
|
+
packet = SteamPacketFactory.get_packet_from_data(@buffer.get)
|
57
|
+
end
|
58
|
+
|
59
|
+
warn "Got reply of type \"#{packet.class.to_s}\"."
|
60
|
+
|
61
|
+
return packet
|
62
|
+
end
|
63
|
+
|
64
|
+
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}"
|
68
|
+
if @is_hltv
|
69
|
+
begin
|
70
|
+
response = self.get_reply.get_response
|
71
|
+
rescue TimeoutException
|
72
|
+
response = ""
|
73
|
+
end
|
74
|
+
else
|
75
|
+
response = self.get_reply.get_response
|
76
|
+
end
|
77
|
+
|
78
|
+
if response.strip == "Bad rcon_password." or response.strip == "You have been banned from this server."
|
79
|
+
raise RCONNoAuthException.new
|
80
|
+
end
|
81
|
+
|
82
|
+
begin
|
83
|
+
while true
|
84
|
+
response_part = self.get_reply.get_response
|
85
|
+
response << response_part
|
86
|
+
end
|
87
|
+
rescue TimeoutException
|
88
|
+
end
|
89
|
+
|
90
|
+
return response
|
91
|
+
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
|
+
|
101
|
+
@rcon_challenge = response[14..-1]
|
102
|
+
end
|
103
|
+
|
104
|
+
def rcon_send(command)
|
105
|
+
self.send RCONGoldSrcRequest.new(command)
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
@@ -0,0 +1,20 @@
|
|
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) 2008-2009, Sebastian Staudt
|
5
|
+
|
6
|
+
require "steam/sockets/steam_socket"
|
7
|
+
|
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)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,50 @@
|
|
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) 2008, Sebastian Staudt
|
5
|
+
#
|
6
|
+
# $Id$
|
7
|
+
|
8
|
+
require "socket_channel"
|
9
|
+
require "steam/packets/rcon/rcon_packet"
|
10
|
+
require "steam/packets/rcon/rcon_packet_factory"
|
11
|
+
require "steam/sockets/steam_socket"
|
12
|
+
|
13
|
+
class RCONSocket < SteamSocket
|
14
|
+
|
15
|
+
def initialize(ip_address, port_number)
|
16
|
+
super ip_address, port_number
|
17
|
+
@channel = SocketChannel.open
|
18
|
+
end
|
19
|
+
|
20
|
+
def send(data_packet)
|
21
|
+
if !@channel.connected?
|
22
|
+
@channel.connect @remote_socket
|
23
|
+
end
|
24
|
+
|
25
|
+
@buffer = ByteBuffer.wrap data_packet.get_bytes
|
26
|
+
@channel.write @buffer
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_reply
|
30
|
+
self.receive_packet 1440
|
31
|
+
packet_data = @buffer.array[0..@buffer.limit]
|
32
|
+
packet_size = @buffer.get_long + 4
|
33
|
+
|
34
|
+
if packet_size > 1440
|
35
|
+
remaining_bytes = packet_size - 1440
|
36
|
+
begin
|
37
|
+
if remaining_bytes < 1440
|
38
|
+
self.receive_packet remaining_bytes
|
39
|
+
else
|
40
|
+
self.receive_packet 1440
|
41
|
+
end
|
42
|
+
packet_data << @buffer.array[0..@buffer.limit]
|
43
|
+
remaining_bytes -= @buffer.limit
|
44
|
+
end while remaining_bytes > 0
|
45
|
+
end
|
46
|
+
|
47
|
+
return RCONPacketFactory.get_packet_from_data(packet_data)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,72 @@
|
|
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) 2008-2009, Sebastian Staudt
|
5
|
+
|
6
|
+
require "byte_buffer"
|
7
|
+
require "steam/sockets/steam_socket"
|
8
|
+
|
9
|
+
# The SourceSocket class is a sub class of SteamSocket respecting the
|
10
|
+
# specifications of the Source query protocol.
|
11
|
+
class SourceSocket < SteamSocket
|
12
|
+
|
13
|
+
# Reads a packet from the channel. The Source query protocol specifies a
|
14
|
+
# maximum packet size of 1400 byte. Greater packets will be split over several
|
15
|
+
# UDP packets. This method reassembles split packets into single packet
|
16
|
+
# objects.
|
17
|
+
def get_reply
|
18
|
+
bytes_read = self.receive_packet 1400
|
19
|
+
is_compressed = false
|
20
|
+
|
21
|
+
if @buffer.get_long == 0xFFFFFFFE
|
22
|
+
split_packets = Array.new
|
23
|
+
begin
|
24
|
+
# Parsing of split packet headers
|
25
|
+
request_id = @buffer.get_long
|
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
|
+
|
30
|
+
if is_compressed
|
31
|
+
split_size = @buffer.get_long
|
32
|
+
packet_checksum = @buffer.get_long
|
33
|
+
else
|
34
|
+
split_size = @buffer.get_short
|
35
|
+
end
|
36
|
+
|
37
|
+
# Caching of split packet data
|
38
|
+
split_packets[packet_number - 1] = @buffer.get
|
39
|
+
|
40
|
+
warn "Received packet #{packet_number} of #{packet_count} for request ##{request_id}"
|
41
|
+
|
42
|
+
# Receiving the next packet
|
43
|
+
if split_packets.size < packet_count
|
44
|
+
begin
|
45
|
+
bytes_read = self.receive_packet
|
46
|
+
rescue TimeoutException
|
47
|
+
bytes_read = 0
|
48
|
+
end
|
49
|
+
else
|
50
|
+
bytes_read = 0
|
51
|
+
end
|
52
|
+
end while bytes_read > 0 && @buffer.get_long == 0xFFFFFFFE
|
53
|
+
|
54
|
+
if is_compressed
|
55
|
+
packet = SteamPacketFactory.reassemble_packet(split_packets, true, packet_checksum)
|
56
|
+
else
|
57
|
+
packet = SteamPacketFactory.reassemble_packet(split_packets)
|
58
|
+
end
|
59
|
+
else
|
60
|
+
packet = SteamPacketFactory.get_packet_from_data(@buffer.get)
|
61
|
+
end
|
62
|
+
|
63
|
+
if is_compressed
|
64
|
+
warn "Got compressed reply of type \"#{packet.class.to_s}\"."
|
65
|
+
else
|
66
|
+
warn "Got reply of type \"#{packet.class.to_s}\"."
|
67
|
+
end
|
68
|
+
|
69
|
+
return packet
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,63 @@
|
|
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) 2008, Sebastian Staudt
|
5
|
+
#
|
6
|
+
# $Id$
|
7
|
+
|
8
|
+
require "abstract_class"
|
9
|
+
require "byte_buffer"
|
10
|
+
require "datagram_channel"
|
11
|
+
require "ipaddr"
|
12
|
+
require "exceptions/timeout_exception"
|
13
|
+
|
14
|
+
# The SteamSocket class is a sub class of CondenserSocket respecting the
|
15
|
+
# specifications of the Source query protocol.
|
16
|
+
class SteamSocket
|
17
|
+
|
18
|
+
include AbstractClass
|
19
|
+
|
20
|
+
def initialize(*args)
|
21
|
+
@channel = DatagramChannel.open
|
22
|
+
@channel.connect *args
|
23
|
+
@channel.configure_blocking false
|
24
|
+
|
25
|
+
@remote_socket = Socket.getaddrinfo args[0].to_s, args[1]
|
26
|
+
end
|
27
|
+
|
28
|
+
# Abstract get_reply method
|
29
|
+
def get_reply
|
30
|
+
raise NotImplementedError
|
31
|
+
end
|
32
|
+
|
33
|
+
def receive_packet(buffer_length = 0)
|
34
|
+
if select([@channel.socket], nil, nil, 1) == nil
|
35
|
+
raise TimeoutException.new
|
36
|
+
end
|
37
|
+
|
38
|
+
if buffer_length == 0
|
39
|
+
@buffer.clear
|
40
|
+
else
|
41
|
+
@buffer = ByteBuffer.allocate buffer_length
|
42
|
+
end
|
43
|
+
|
44
|
+
@channel.read @buffer
|
45
|
+
bytes_read = @buffer.position
|
46
|
+
@buffer.rewind
|
47
|
+
@buffer.limit = bytes_read
|
48
|
+
|
49
|
+
return bytes_read
|
50
|
+
end
|
51
|
+
|
52
|
+
def send(data_packet)
|
53
|
+
warn "Sending data packet of type \"#{data_packet.class.to_s}\"."
|
54
|
+
|
55
|
+
@buffer = ByteBuffer.wrap data_packet.to_s
|
56
|
+
@channel.write @buffer
|
57
|
+
end
|
58
|
+
|
59
|
+
def finalize
|
60
|
+
@channel.close
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|