gamespy_query 0.2.0pre9 → 0.2.0pre10
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/gamespy_query/base.rb
CHANGED
@@ -128,8 +128,9 @@ module GamespyQuery
|
|
128
128
|
|
129
129
|
run do |opts, args, cmd|
|
130
130
|
opts = GamespyQuery::Options.setup_master_opts opts
|
131
|
-
process = GamespyQuery::SocketMaster.process_master(opts[:game], opts[:geo])
|
132
|
-
puts process
|
131
|
+
process = GamespyQuery::SocketMaster.process_master(opts[:game], opts[:geo], nil, false, true, true)
|
132
|
+
puts process.size
|
133
|
+
#puts process
|
133
134
|
end
|
134
135
|
end
|
135
136
|
|
data/lib/gamespy_query/socket.rb
CHANGED
@@ -11,8 +11,9 @@ module GamespyQuery
|
|
11
11
|
class Socket < UDPSocket
|
12
12
|
include Funcs
|
13
13
|
|
14
|
+
|
14
15
|
# Default timeout per connection state
|
15
|
-
DEFAULT_TIMEOUT =
|
16
|
+
DEFAULT_TIMEOUT = 4
|
16
17
|
|
17
18
|
# Maximum amount of packets sent by the server
|
18
19
|
# This is a limit set by gamespy
|
@@ -113,7 +114,7 @@ module GamespyQuery
|
|
113
114
|
|
114
115
|
# Temp Workaround for IO.select issue on IR
|
115
116
|
def _read_non_block
|
116
|
-
if
|
117
|
+
if PLATFORM_IR
|
117
118
|
time_end = Time.now + DEFAULT_TIMEOUT
|
118
119
|
success = false
|
119
120
|
until success || Time.now >= time_end
|
@@ -222,7 +223,8 @@ module GamespyQuery
|
|
222
223
|
end
|
223
224
|
|
224
225
|
# Determine Read/Write/Exception state
|
225
|
-
|
226
|
+
WRITE_STATES = [STATE_INIT, STATE_RECEIVED_CHALLENGE]
|
227
|
+
def handle_state; WRITE_STATES.include? state; end
|
226
228
|
|
227
229
|
# Process data
|
228
230
|
# Supports challenge/response and multi-packet
|
@@ -250,13 +252,13 @@ module GamespyQuery
|
|
250
252
|
begin
|
251
253
|
until valid? || failed
|
252
254
|
if handle_state
|
253
|
-
if
|
255
|
+
if PLATFORM_IR || IO.select(nil, [self], nil, DEFAULT_TIMEOUT)
|
254
256
|
handle_write
|
255
257
|
else
|
256
258
|
raise TimeOutError, "TimeOut during write, #{self}"
|
257
259
|
end
|
258
260
|
else
|
259
|
-
if
|
261
|
+
if PLATFORM_IR || IO.select([self], nil, nil, DEFAULT_TIMEOUT)
|
260
262
|
handle_read
|
261
263
|
else
|
262
264
|
raise TimeOutError, "TimeOut during read, #{self}"
|
@@ -8,6 +8,8 @@ module GamespyQuery
|
|
8
8
|
# Default maximum concurrent connections
|
9
9
|
DEFAULT_MAX_CONNECTIONS = 128
|
10
10
|
|
11
|
+
DEFAULT_THREADS = 0
|
12
|
+
|
11
13
|
# Configurable timeout in seconds
|
12
14
|
attr_accessor :timeout
|
13
15
|
|
@@ -16,33 +18,64 @@ module GamespyQuery
|
|
16
18
|
|
17
19
|
# Initializes the object
|
18
20
|
# @param [Array] addrs List of addresses to process
|
19
|
-
def initialize addrs
|
21
|
+
def initialize addrs, info = false
|
20
22
|
@addrs = addrs
|
23
|
+
@info = info
|
21
24
|
|
22
25
|
@timeout, @max_connections = Socket::DEFAULT_TIMEOUT, DEFAULT_MAX_CONNECTIONS # Per select iteration
|
23
26
|
end
|
24
27
|
|
25
28
|
# Process the list of addresses
|
26
|
-
def process!
|
29
|
+
def process! use_threads = DEFAULT_THREADS
|
27
30
|
sockets = []
|
31
|
+
if use_threads.to_i > 0
|
32
|
+
monitor = Monitor.new # TODO...
|
33
|
+
threads = []
|
34
|
+
addrs_list = @addrs.each_slice(@addrs.size / use_threads).to_a
|
35
|
+
use_threads.times.each do |i|
|
36
|
+
list = addrs_list.shift
|
37
|
+
break if list.nil? || list.empty?
|
38
|
+
puts "Spawning thread #{i}" if @info
|
39
|
+
|
40
|
+
threads << Thread.new(list, i) do |addrs, id|
|
41
|
+
puts "Thread: #{id} Start, #{addrs.size}" if @info
|
42
|
+
out = proc(addrs, monitor)
|
43
|
+
|
44
|
+
puts "Thread: #{id} Pushing output to list. #{out.size}" if @info
|
45
|
+
monitor.synchronize do
|
46
|
+
sockets += out
|
47
|
+
end
|
48
|
+
puts "Thread: #{id} End" if @info
|
49
|
+
end
|
50
|
+
end
|
51
|
+
threads.each {|t| t.join}
|
52
|
+
else
|
53
|
+
sockets = proc @addrs
|
54
|
+
end
|
28
55
|
|
29
|
-
|
30
|
-
|
31
|
-
|
56
|
+
return sockets
|
57
|
+
end
|
58
|
+
|
59
|
+
def proc addrs_list
|
60
|
+
sockets = []
|
32
61
|
|
62
|
+
until addrs_list.empty?
|
63
|
+
addrs = addrs_list.shift @max_connections
|
64
|
+
|
65
|
+
queue = addrs.map { |addr| Socket.new(addr) }
|
33
66
|
sockets += queue
|
34
67
|
|
35
68
|
until queue.empty?
|
36
69
|
# Fill up the Sockets pool until max_conn
|
37
|
-
if FILL_UP_ON_SPACE && queue.size < @max_connections
|
38
|
-
addrs =
|
70
|
+
if FILL_UP_ON_SPACE && queue.size < @max_connections && !addrs_list.empty?
|
71
|
+
addrs = addrs_list.shift (@max_connections - queue.size)
|
39
72
|
socks = addrs.map { |addr| Socket.new(addr) }
|
40
73
|
|
41
74
|
queue += socks
|
42
75
|
sockets += socks
|
43
76
|
end
|
44
77
|
|
45
|
-
write_sockets, read_sockets = queue.
|
78
|
+
write_sockets, read_sockets = queue.partition {|s| s.handle_state }
|
46
79
|
|
47
80
|
unless ready = IO.select(read_sockets, write_sockets, nil, @timeout)
|
48
81
|
Tools.logger.warn "Timeout, no usable sockets in current queue, within timeout period (#{@timeout}s)"
|
@@ -51,7 +84,7 @@ module GamespyQuery
|
|
51
84
|
next
|
52
85
|
end
|
53
86
|
|
54
|
-
Tools.debug {"Sockets: #{queue.size}, AddrsLeft: #{
|
87
|
+
Tools.debug {"Sockets: #{queue.size}, AddrsLeft: #{addrs_list.size}, ReadReady: #{"#{ready[0].size} / #{read_sockets.size}, WriteReady: #{ready[1].size} / #{write_sockets.size}, ExcReady: #{ready[2].size} / #{queue.size}" unless ready.nil?}"}
|
55
88
|
|
56
89
|
# Read
|
57
90
|
ready[0].each { |s| begin; s.handle_read(); rescue nil, Exception => e; queue.delete(s); end }
|
@@ -61,10 +94,11 @@ module GamespyQuery
|
|
61
94
|
|
62
95
|
# Exceptions
|
63
96
|
#ready[2].each { |s| queue.delete(s) unless s.handle_exc }
|
97
|
+
queue.reject! {|s| s.valid? }
|
64
98
|
end
|
65
99
|
end
|
66
100
|
|
67
|
-
|
101
|
+
sockets
|
68
102
|
end
|
69
103
|
|
70
104
|
class <<self
|
@@ -73,7 +107,7 @@ module GamespyQuery
|
|
73
107
|
# @param [String] game Game to fetch info from
|
74
108
|
# @param [String] geo Geo location enabled?
|
75
109
|
# @param [Array] remote Hostname and path+filename strings if the list needs to be fetched from http server
|
76
|
-
def process_master(game = "arma2oapc", geo = nil, remote = nil, dedicated_only = false, sm_dedicated_only = true)
|
110
|
+
def process_master(game = "arma2oapc", geo = nil, remote = nil, dedicated_only = false, sm_dedicated_only = true, info = false)
|
77
111
|
master = GamespyQuery::Master.new(geo, game)
|
78
112
|
list = if remote
|
79
113
|
Net::HTTP.start(remote[0]) do |http|
|
@@ -98,9 +132,11 @@ module GamespyQuery
|
|
98
132
|
dat
|
99
133
|
end
|
100
134
|
|
101
|
-
sm = GamespyQuery::SocketMaster.new(gm_dat.keys)
|
135
|
+
sm = GamespyQuery::SocketMaster.new(gm_dat.keys, info)
|
102
136
|
sockets = sm.process!
|
103
|
-
sockets.select{|s| s.valid? }
|
137
|
+
valid_sockets = sockets.select{|s| s.valid? }
|
138
|
+
puts "Sockets: #{sockets.size}, Valid: #{valid_sockets.size}" if info
|
139
|
+
valid_sockets.each do |s|
|
104
140
|
begin
|
105
141
|
data = gm_dat[s.addr]
|
106
142
|
data[:ip], data[:port] = s.addr.split(":")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gamespy_query
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.0pre10
|
5
5
|
prerelease: 5
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cri
|