gamespy_query 0.2.0pre9 → 0.2.0pre10
Sign up to get free protection for your applications and to get access to all the features.
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
|