girl 0.88.0 → 0.89.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of girl might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/girl/head.rb +38 -29
- data/lib/girl/proxy.rb +49 -90
- data/lib/girl/proxy_worker.rb +900 -838
- data/lib/girl/proxyd.rb +6 -25
- data/lib/girl/proxyd_worker.rb +655 -609
- data/lib/girl/udp.rb +37 -47
- data/lib/girl/udpd.rb +26 -36
- data/lib/girl/version.rb +1 -1
- metadata +2 -2
data/lib/girl/proxyd.rb
CHANGED
@@ -13,23 +13,20 @@ module Girl
|
|
13
13
|
class Proxyd
|
14
14
|
|
15
15
|
def initialize( config_path = nil )
|
16
|
-
if config_path
|
17
|
-
unless File.exist?( config_path )
|
18
|
-
raise "not found config file #{ config_path }"
|
19
|
-
end
|
20
|
-
|
16
|
+
if config_path then
|
17
|
+
raise "not found config file #{ config_path }" unless File.exist?( config_path )
|
21
18
|
conf = JSON.parse( IO.binread( config_path ), symbolize_names: true )
|
22
19
|
proxyd_port = conf[ :proxyd_port ]
|
23
20
|
worker_count = conf[ :worker_count ]
|
24
21
|
end
|
25
22
|
|
26
|
-
unless proxyd_port
|
23
|
+
unless proxyd_port then
|
27
24
|
proxyd_port = 6060
|
28
25
|
end
|
29
26
|
|
30
27
|
nprocessors = Etc.nprocessors
|
31
28
|
|
32
|
-
if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors
|
29
|
+
if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors then
|
33
30
|
worker_count = nprocessors
|
34
31
|
end
|
35
32
|
|
@@ -38,25 +35,9 @@ module Girl
|
|
38
35
|
puts "proxyd port #{ proxyd_port }"
|
39
36
|
puts "worker count #{ worker_count }"
|
40
37
|
|
41
|
-
|
42
|
-
PACK_SIZE
|
43
|
-
READ_SIZE
|
44
|
-
WMEMS_LIMIT
|
45
|
-
RESUME_BELOW
|
46
|
-
EXPIRE_NEW
|
47
|
-
EXPIRE_AFTER
|
48
|
-
CHECK_EXPIRE_INTERVAL
|
49
|
-
CHECK_STATUS_INTERVAL
|
50
|
-
SEND_STATUS_UNTIL
|
51
|
-
MULTI_MISS_SIZE
|
52
|
-
MISS_RANGE_LIMIT
|
53
|
-
CONFUSE_UNTIL
|
54
|
-
RESOLV_CACHE_EXPIRE
|
55
|
-
]
|
56
|
-
|
57
|
-
len = names.map{ | name | name.size }.max
|
38
|
+
len = CONSTS.map{ | name | name.size }.max
|
58
39
|
|
59
|
-
|
40
|
+
CONSTS.each do | name |
|
60
41
|
puts "#{ name.gsub( '_', ' ' ).ljust( len ) } #{ Girl.const_get( name ) }"
|
61
42
|
end
|
62
43
|
|
data/lib/girl/proxyd_worker.rb
CHANGED
@@ -9,11 +9,11 @@ module Girl
|
|
9
9
|
@mutex = Mutex.new
|
10
10
|
@reads = []
|
11
11
|
@writes = []
|
12
|
-
@
|
13
|
-
@roles = {} # sock => :dotr / :proxyd / :dst / :tund
|
14
|
-
@dst_infos = {} # dst => {}
|
15
|
-
@tunds = {} # port => tund
|
12
|
+
@roles = {} # sock => :dotr / :proxyd / :dst / :tund / :tcpd / :streamd
|
16
13
|
@tund_infos = {} # tund => {}
|
14
|
+
@tcpd_infos = {} # tcpd => {}
|
15
|
+
@dst_infos = {} # dst => {}
|
16
|
+
@streamd_infos = {} # streamd => {}
|
17
17
|
@tunneling_tunds = {} # tunneling_addr => tund
|
18
18
|
@resolv_caches = {} # domain => [ ip, created_at ]
|
19
19
|
|
@@ -29,32 +29,40 @@ module Girl
|
|
29
29
|
def looping
|
30
30
|
puts "p#{ Process.pid } #{ Time.new } looping"
|
31
31
|
loop_check_expire
|
32
|
-
|
32
|
+
loop_check_resume
|
33
33
|
|
34
34
|
loop do
|
35
35
|
rs, ws = IO.select( @reads, @writes )
|
36
36
|
|
37
37
|
@mutex.synchronize do
|
38
|
-
#
|
39
|
-
ws.each do | sock |
|
40
|
-
case @roles[ sock ]
|
41
|
-
when :dst
|
42
|
-
write_dst( sock )
|
43
|
-
when :tund
|
44
|
-
write_tund( sock )
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
38
|
+
# 先读,再写,避免打上关闭标记后读到
|
48
39
|
rs.each do | sock |
|
49
40
|
case @roles[ sock ]
|
50
|
-
when :dotr
|
41
|
+
when :dotr then
|
51
42
|
read_dotr( sock )
|
52
|
-
when :proxyd
|
43
|
+
when :proxyd then
|
53
44
|
read_proxyd( sock )
|
54
|
-
when :
|
55
|
-
read_dst( sock )
|
56
|
-
when :tund
|
45
|
+
when :tund then
|
57
46
|
read_tund( sock )
|
47
|
+
when :tcpd then
|
48
|
+
read_tcpd( sock )
|
49
|
+
when :dst then
|
50
|
+
read_dst( sock )
|
51
|
+
when :streamd then
|
52
|
+
read_streamd( sock )
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
ws.each do | sock |
|
57
|
+
case @roles[ sock ]
|
58
|
+
when :proxyd then
|
59
|
+
write_proxyd( sock )
|
60
|
+
when :tund then
|
61
|
+
write_tund( sock )
|
62
|
+
when :dst then
|
63
|
+
write_dst( sock )
|
64
|
+
when :streamd then
|
65
|
+
write_streamd( sock )
|
58
66
|
end
|
59
67
|
end
|
60
68
|
end
|
@@ -71,7 +79,7 @@ module Girl
|
|
71
79
|
data = [ 0, TUND_FIN ].pack( 'Q>C' )
|
72
80
|
|
73
81
|
@tund_infos.each do | tund, tund_info |
|
74
|
-
if !tund.closed? && tund_info[ :tun_addr ]
|
82
|
+
if !tund.closed? && tund_info[ :tun_addr ] then
|
75
83
|
# puts "debug1 send tund fin"
|
76
84
|
tund.sendmsg( data, 0, tund_info[ :tun_addr ] )
|
77
85
|
end
|
@@ -84,185 +92,175 @@ module Girl
|
|
84
92
|
private
|
85
93
|
|
86
94
|
##
|
87
|
-
#
|
95
|
+
# add proxyd ctlmsg
|
88
96
|
#
|
89
|
-
def
|
90
|
-
|
91
|
-
|
92
|
-
|
97
|
+
def add_proxyd_ctlmsg_tund_port( tund_info )
|
98
|
+
data = [ 0, TUND_PORT, tund_info[ :port ], tund_info[ :tcpd_port ] ].pack( 'Q>Cnn' )
|
99
|
+
@proxyd_info[ :ctlmsgs ] << [ data, tund_info[ :tun_addr ] ]
|
100
|
+
add_write( @proxyd )
|
101
|
+
end
|
93
102
|
|
94
|
-
|
95
|
-
|
96
|
-
|
103
|
+
##
|
104
|
+
# add ctlmsg resend ready
|
105
|
+
#
|
106
|
+
def add_ctlmsg_resend_ready( tund )
|
107
|
+
tund_info = @tund_infos[ tund ]
|
108
|
+
data = [ 0, RESEND_READY ].pack( 'Q>C' )
|
109
|
+
add_ctlmsg( tund, data )
|
110
|
+
end
|
97
111
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
else
|
107
|
-
data = [ 0, HEARTBEAT, rand( 128 ) ].pack( 'Q>CC' )
|
108
|
-
# puts "debug1 #{ Time.new } #{ tund_info[ :port ] } heartbeat"
|
109
|
-
send_data( tund, data, tund_info[ :tun_addr ] )
|
110
|
-
del_dst_ids = []
|
111
|
-
|
112
|
-
tund_info[ :dsts ].each do | dst_id, dst |
|
113
|
-
if dst.closed?
|
114
|
-
dst_info = @dst_infos[ dst ]
|
115
|
-
|
116
|
-
if dst_info && ( now - dst_info[ :last_continue_at ] > EXPIRE_AFTER )
|
117
|
-
puts "p#{ Process.pid } #{ Time.new } expire dst ext #{ dst_info[ :domain_port ] }"
|
118
|
-
tund_info[ :wmems ].delete_if { | dst_id_pack_id, _ | dst_id_pack_id.first == dst_id }
|
119
|
-
tund_info[ :dst_ids ].delete( dst_info[ :src_id ] )
|
120
|
-
@dst_infos.delete( dst )
|
121
|
-
del_dst_ids << dst_id
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
if del_dst_ids.any?
|
127
|
-
tund_info[ :dsts ].delete_if { | dst_id, _ | del_dst_ids.include?( dst_id ) }
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
112
|
+
##
|
113
|
+
# add ctlmsg
|
114
|
+
#
|
115
|
+
def add_ctlmsg( tund, data )
|
116
|
+
tund_info = @tund_infos[ tund ]
|
117
|
+
tund_info[ :ctlmsgs ] << data
|
118
|
+
add_write( tund )
|
119
|
+
end
|
132
120
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end
|
121
|
+
##
|
122
|
+
# add read
|
123
|
+
#
|
124
|
+
def add_read( sock, role = nil )
|
125
|
+
unless @reads.include?( sock ) then
|
126
|
+
@reads << sock
|
140
127
|
|
141
|
-
|
142
|
-
|
143
|
-
end
|
144
|
-
end
|
128
|
+
if role then
|
129
|
+
@roles[ sock ] = role
|
145
130
|
end
|
146
131
|
end
|
147
132
|
end
|
148
133
|
|
149
134
|
##
|
150
|
-
#
|
135
|
+
# add write
|
151
136
|
#
|
152
|
-
def
|
153
|
-
|
154
|
-
|
155
|
-
|
137
|
+
def add_write( sock )
|
138
|
+
unless @writes.include?( sock ) then
|
139
|
+
@writes << sock
|
140
|
+
end
|
141
|
+
end
|
156
142
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
tund_info[ :dsts ].each do | dst_id, dst |
|
166
|
-
dst_info = @dst_infos[ dst ]
|
167
|
-
|
168
|
-
if dst_info && ( now - dst_info[ :last_continue_at ] < SEND_STATUS_UNTIL )
|
169
|
-
data = [ 0, DEST_STATUS, dst_id, dst_info[ :biggest_pack_id ], dst_info[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
|
170
|
-
send_data( tund, data, tund_info[ :tun_addr ] )
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
143
|
+
##
|
144
|
+
# close dst
|
145
|
+
#
|
146
|
+
def close_dst( dst )
|
147
|
+
# puts "debug1 close dst"
|
148
|
+
close_sock( dst )
|
149
|
+
del_dst_info( dst )
|
150
|
+
end
|
176
151
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
tund = dst_info[ :tund ]
|
186
|
-
|
187
|
-
if tund.closed?
|
188
|
-
ignore_dsts << dst
|
189
|
-
else
|
190
|
-
tund_info = @tund_infos[ tund ]
|
191
|
-
|
192
|
-
if tund_info[ :wmems ].size < RESUME_BELOW
|
193
|
-
puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain_port ] }"
|
194
|
-
resume_dsts << dst
|
195
|
-
end
|
196
|
-
end
|
197
|
-
else
|
198
|
-
ignore_dsts << dst
|
199
|
-
end
|
200
|
-
end
|
152
|
+
##
|
153
|
+
# close read dst
|
154
|
+
#
|
155
|
+
def close_read_dst( dst )
|
156
|
+
return if dst.closed?
|
157
|
+
# puts "debug1 close read dst"
|
158
|
+
dst.close_read
|
159
|
+
@reads.delete( dst )
|
201
160
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
161
|
+
if dst.closed? then
|
162
|
+
# puts "debug1 delete dst info"
|
163
|
+
@roles.delete( dst )
|
164
|
+
dst_info = del_dst_info( dst )
|
165
|
+
else
|
166
|
+
dst_info = @dst_infos[ dst ]
|
167
|
+
end
|
206
168
|
|
207
|
-
|
208
|
-
|
209
|
-
|
169
|
+
dst_info[ :paused ] = false
|
170
|
+
dst_info
|
171
|
+
end
|
210
172
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
173
|
+
##
|
174
|
+
# close read streamd
|
175
|
+
#
|
176
|
+
def close_read_streamd( streamd )
|
177
|
+
return if streamd.closed?
|
178
|
+
# puts "debug1 close read streamd"
|
179
|
+
streamd.close_read
|
180
|
+
@reads.delete( streamd )
|
181
|
+
|
182
|
+
if streamd.closed? then
|
183
|
+
# puts "debug1 delete streamd info"
|
184
|
+
@roles.delete( streamd )
|
185
|
+
streamd_info = @streamd_infos.delete( streamd )
|
186
|
+
else
|
187
|
+
streamd_info = @streamd_infos[ streamd ]
|
217
188
|
end
|
189
|
+
|
190
|
+
streamd_info
|
218
191
|
end
|
219
192
|
|
220
193
|
##
|
221
|
-
#
|
194
|
+
# close sock
|
222
195
|
#
|
223
|
-
def
|
224
|
-
|
196
|
+
def close_sock( sock )
|
197
|
+
sock.close
|
198
|
+
@reads.delete( sock )
|
199
|
+
@writes.delete( sock )
|
200
|
+
@roles.delete( sock )
|
201
|
+
end
|
225
202
|
|
226
|
-
|
227
|
-
|
203
|
+
##
|
204
|
+
# close streamd
|
205
|
+
#
|
206
|
+
def close_streamd( streamd )
|
207
|
+
# puts "debug1 close streamd"
|
208
|
+
close_sock( streamd )
|
209
|
+
@streamd_infos.delete( streamd )
|
210
|
+
end
|
228
211
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
212
|
+
##
|
213
|
+
# close tund
|
214
|
+
#
|
215
|
+
def close_tund( tund )
|
216
|
+
# puts "debug1 close tund"
|
217
|
+
close_sock( tund )
|
218
|
+
tund_info = @tund_infos.delete( tund )
|
219
|
+
tcpd = tund_info[ :tcpd ]
|
220
|
+
close_sock( tcpd )
|
221
|
+
@tcpd_infos.delete( tcpd )
|
222
|
+
tund_info[ :dsts ].each{ | _, dst | set_dst_closing( dst ) }
|
223
|
+
@tunneling_tunds.delete( tund_info[ :tun_addr ] )
|
224
|
+
end
|
234
225
|
|
235
|
-
|
236
|
-
|
226
|
+
##
|
227
|
+
# close write dst
|
228
|
+
#
|
229
|
+
def close_write_dst( dst )
|
230
|
+
return if dst.closed?
|
231
|
+
# puts "debug1 close write dst"
|
232
|
+
dst.close_write
|
233
|
+
@writes.delete( dst )
|
234
|
+
|
235
|
+
if dst.closed? then
|
236
|
+
# puts "debug1 delete dst info"
|
237
|
+
@roles.delete( dst )
|
238
|
+
dst_info = del_dst_info( dst )
|
239
|
+
else
|
240
|
+
dst_info = @dst_infos[ dst ]
|
237
241
|
end
|
238
242
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
if colon_idx
|
243
|
-
destination_domain = domain_port[ 0...colon_idx ]
|
244
|
-
destination_port = domain_port[ ( colon_idx + 1 )..-1 ].to_i
|
245
|
-
|
246
|
-
begin
|
247
|
-
destination_addr = Socket.sockaddr_in( destination_port, destination_domain )
|
248
|
-
rescue Exception => e
|
249
|
-
puts "p#{ Process.pid } #{ Time.new } sockaddr in #{ domain_port } #{ e.class }"
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
@mutex.synchronize do
|
254
|
-
if destination_addr
|
255
|
-
# puts "debug1 resolved #{ domain_port } #{ Addrinfo.new( destination_addr ).inspect }"
|
256
|
-
@resolv_caches[ domain_port ] = [ destination_addr, Time.new ]
|
243
|
+
dst_info
|
244
|
+
end
|
257
245
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
246
|
+
##
|
247
|
+
# close write streamd
|
248
|
+
#
|
249
|
+
def close_write_streamd( streamd )
|
250
|
+
return if streamd.closed?
|
251
|
+
# puts "debug1 close write streamd"
|
252
|
+
streamd.close_write
|
253
|
+
@writes.delete( streamd )
|
254
|
+
|
255
|
+
if streamd.closed? then
|
256
|
+
# puts "debug1 delete streamd info"
|
257
|
+
@roles.delete( streamd )
|
258
|
+
streamd_info = @streamd_infos.delete( streamd )
|
259
|
+
else
|
260
|
+
streamd_info = @streamd_infos[ streamd ]
|
265
261
|
end
|
262
|
+
|
263
|
+
streamd_info
|
266
264
|
end
|
267
265
|
|
268
266
|
##
|
@@ -283,20 +281,20 @@ module Girl
|
|
283
281
|
dst_id = dst.local_address.ip_port
|
284
282
|
|
285
283
|
@dst_infos[ dst ] = {
|
286
|
-
id: dst_id,
|
287
|
-
tund: tund,
|
288
|
-
domain_port: domain_port,
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
284
|
+
id: dst_id, # id
|
285
|
+
tund: tund, # 对应tund
|
286
|
+
domain_port: domain_port, # 域名和端口
|
287
|
+
rbuff: '', # 对应的streamd没准备好,暂存读到的流量
|
288
|
+
streamd: nil, # 对应的streamd
|
289
|
+
wbuff: '', # 从streamd读到的流量
|
290
|
+
src_id: src_id, # 近端src id
|
291
|
+
created_at: Time.new, # 创建时间
|
292
|
+
last_recv_at: nil, # 上一次收到新流量(由streamd收到)的时间
|
293
|
+
last_sent_at: nil, # 上一次发出流量(由streamd发出)的时间
|
294
|
+
paused: false, # 是否已暂停
|
295
|
+
closing: false, # 准备关闭
|
296
|
+
closing_read: false, # 准备关闭读
|
297
|
+
closing_write: false # 准备关闭写
|
300
298
|
}
|
301
299
|
|
302
300
|
add_read( dst, :dst )
|
@@ -306,124 +304,165 @@ module Girl
|
|
306
304
|
tund_info[ :dsts ][ dst_id ] = dst
|
307
305
|
|
308
306
|
data = [ 0, PAIRED, src_id, dst_id ].pack( 'Q>CQ>n' )
|
309
|
-
# puts "debug1
|
310
|
-
|
311
|
-
|
307
|
+
# puts "debug1 add ctlmsg paired #{ src_id } #{ dst_id }"
|
308
|
+
add_ctlmsg( tund, data )
|
312
309
|
true
|
313
310
|
end
|
314
311
|
|
315
312
|
##
|
316
|
-
#
|
313
|
+
# del dst info
|
317
314
|
#
|
318
|
-
def
|
319
|
-
|
320
|
-
|
321
|
-
proxyd.bind( Socket.sockaddr_in( proxyd_port, '0.0.0.0' ) )
|
315
|
+
def del_dst_info( dst )
|
316
|
+
dst_info = @dst_infos.delete( dst )
|
317
|
+
tund = dst_info[ :tund ]
|
322
318
|
|
323
|
-
|
324
|
-
|
325
|
-
|
319
|
+
unless tund.closed? then
|
320
|
+
tund_info = @tund_infos[ tund ]
|
321
|
+
tund_info[ :dsts ].delete( dst_info[ :id ] )
|
322
|
+
tund_info[ :dst_ids ].delete( dst_info[ :src_id ] )
|
323
|
+
end
|
324
|
+
|
325
|
+
dst_info
|
326
326
|
end
|
327
327
|
|
328
328
|
##
|
329
|
-
#
|
329
|
+
# loop check expire
|
330
330
|
#
|
331
|
-
def
|
332
|
-
|
333
|
-
|
331
|
+
def loop_check_expire
|
332
|
+
Thread.new do
|
333
|
+
loop do
|
334
|
+
sleep CHECK_EXPIRE_INTERVAL
|
334
335
|
|
335
|
-
|
336
|
-
|
336
|
+
@mutex.synchronize do
|
337
|
+
trigger = false
|
338
|
+
now = Time.new
|
339
|
+
|
340
|
+
@tund_infos.each do | tund, tund_info |
|
341
|
+
last_recv_at = tund_info[ :last_recv_at ] || tund_info[ :created_at ]
|
342
|
+
last_sent_at = tund_info[ :last_sent_at ] || tund_info[ :created_at ]
|
343
|
+
|
344
|
+
if tund_info[ :dsts ].empty? && ( now - last_recv_at >= EXPIRE_AFTER ) && ( now - last_sent_at >= EXPIRE_AFTER ) then
|
345
|
+
puts "p#{ Process.pid } #{ Time.new } expire tund #{ tund_info[ :port ] }"
|
346
|
+
set_tund_closing( tund )
|
347
|
+
trigger = true
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
@dst_infos.each do | dst, dst_info |
|
352
|
+
last_recv_at = dst_info[ :last_recv_at ] || dst_info[ :created_at ]
|
353
|
+
last_sent_at = dst_info[ :last_sent_at ] || dst_info[ :created_at ]
|
354
|
+
|
355
|
+
if ( now - last_recv_at >= EXPIRE_AFTER ) && ( now - last_sent_at >= EXPIRE_AFTER ) then
|
356
|
+
puts "p#{ Process.pid } #{ Time.new } expire dst #{ dst_info[ :domain_port ] }"
|
357
|
+
set_dst_closing( dst )
|
358
|
+
trigger = true
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
next_tick if trigger
|
363
|
+
end
|
337
364
|
end
|
338
365
|
end
|
339
366
|
end
|
340
367
|
|
341
368
|
##
|
342
|
-
#
|
369
|
+
# loop check resume
|
343
370
|
#
|
344
|
-
def
|
345
|
-
|
346
|
-
|
371
|
+
def loop_check_resume
|
372
|
+
Thread.new do
|
373
|
+
loop do
|
374
|
+
sleep CHECK_RESUME_INTERVAL
|
375
|
+
|
376
|
+
@mutex.synchronize do
|
377
|
+
trigger = false
|
378
|
+
|
379
|
+
@dst_infos.select{ | _, dst_info | dst_info[ :paused ] }.each do | dst, dst_info |
|
380
|
+
streamd = dst_info[ :streamd ]
|
381
|
+
streamd_info = @streamd_infos[ streamd ]
|
382
|
+
|
383
|
+
if streamd_info[ :wbuff ].size < RESUME_BELOW then
|
384
|
+
puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain_port ] }"
|
385
|
+
dst_info[ :paused ] = false
|
386
|
+
add_read( dst )
|
387
|
+
trigger = true
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
next_tick if trigger
|
392
|
+
end
|
393
|
+
end
|
347
394
|
end
|
348
395
|
end
|
349
396
|
|
350
397
|
##
|
351
|
-
#
|
398
|
+
# new a proxyd
|
352
399
|
#
|
353
|
-
def
|
354
|
-
|
400
|
+
def new_a_proxyd( proxyd_port )
|
401
|
+
proxyd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
402
|
+
proxyd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
403
|
+
proxyd.bind( Socket.sockaddr_in( proxyd_port, '0.0.0.0' ) )
|
355
404
|
|
356
|
-
|
357
|
-
|
358
|
-
|
405
|
+
puts "p#{ Process.pid } #{ Time.new } proxyd bind on #{ proxyd_port }"
|
406
|
+
@proxyd = proxyd
|
407
|
+
@proxyd_info = {
|
408
|
+
ctlmsgs: [] # [ ctlmsg, to_addr ]
|
409
|
+
}
|
410
|
+
|
411
|
+
add_read( proxyd, :proxyd )
|
359
412
|
end
|
360
413
|
|
361
414
|
##
|
362
|
-
#
|
415
|
+
# next tick
|
363
416
|
#
|
364
|
-
def
|
365
|
-
|
366
|
-
role = @roles[ sock ]
|
367
|
-
# puts "debug1 set #{ role.to_s } is closing"
|
368
|
-
|
369
|
-
case role
|
370
|
-
when :dst
|
371
|
-
dst_info = @dst_infos[ sock ]
|
372
|
-
dst_info[ :is_closing ] = true
|
373
|
-
when :tund
|
374
|
-
tund_info = @tund_infos[ sock ]
|
375
|
-
tund_info[ :is_closing ] = true
|
376
|
-
end
|
377
|
-
|
378
|
-
@reads.delete( sock )
|
379
|
-
add_write( sock )
|
380
|
-
end
|
417
|
+
def next_tick
|
418
|
+
@dotw.write( '.' )
|
381
419
|
end
|
382
420
|
|
383
421
|
##
|
384
|
-
#
|
422
|
+
# resolve domain
|
385
423
|
#
|
386
|
-
def
|
387
|
-
|
388
|
-
tund = dst_info[ :tund ]
|
424
|
+
def resolve_domain( tund, src_id, domain_port )
|
425
|
+
resolv_cache = @resolv_caches[ domain_port ]
|
389
426
|
|
390
|
-
if
|
391
|
-
|
392
|
-
set_is_closing( dst )
|
393
|
-
return
|
394
|
-
end
|
427
|
+
if resolv_cache then
|
428
|
+
destination_addr, created_at = resolv_cache
|
395
429
|
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
idx = 0
|
401
|
-
len = data.bytesize
|
402
|
-
|
403
|
-
while idx < len
|
404
|
-
chunk = data[ idx, PACK_SIZE ]
|
405
|
-
pack_id += 1
|
406
|
-
|
407
|
-
if pack_id <= CONFUSE_UNTIL
|
408
|
-
chunk = @custom.encode( chunk )
|
409
|
-
# puts "debug1 encoded chunk #{ pack_id }"
|
430
|
+
if Time.new - created_at < RESOLV_CACHE_EXPIRE then
|
431
|
+
# puts "debug1 #{ domain_port } hit resolv cache #{ Addrinfo.new( destination_addr ).inspect }"
|
432
|
+
deal_with_destination_addr( tund, src_id, destination_addr, domain_port )
|
433
|
+
return
|
410
434
|
end
|
411
435
|
|
412
|
-
|
413
|
-
|
414
|
-
# puts "debug2 written pack #{ pack_id } #{ sent }"
|
415
|
-
tund_info[ :wmems ][ [ dst_id, pack_id ] ] = data2
|
416
|
-
dst_info[ :send_ats ][ pack_id ] = now
|
417
|
-
idx += PACK_SIZE
|
436
|
+
# puts "debug1 expire #{ domain_port } resolv cache"
|
437
|
+
@resolv_caches.delete( domain_port )
|
418
438
|
end
|
419
439
|
|
420
|
-
|
421
|
-
|
440
|
+
Thread.new do
|
441
|
+
colon_idx = domain_port.rindex( ':' )
|
442
|
+
|
443
|
+
if colon_idx then
|
444
|
+
destination_domain = domain_port[ 0...colon_idx ]
|
445
|
+
destination_port = domain_port[ ( colon_idx + 1 )..-1 ].to_i
|
446
|
+
|
447
|
+
begin
|
448
|
+
destination_addr = Socket.sockaddr_in( destination_port, destination_domain )
|
449
|
+
rescue Exception => e
|
450
|
+
puts "p#{ Process.pid } #{ Time.new } sockaddr in #{ domain_port } #{ e.class }"
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
@mutex.synchronize do
|
455
|
+
if destination_addr then
|
456
|
+
# puts "debug1 resolved #{ domain_port } #{ Addrinfo.new( destination_addr ).inspect }"
|
457
|
+
@resolv_caches[ domain_port ] = [ destination_addr, Time.new ]
|
422
458
|
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
459
|
+
unless tund.closed? then
|
460
|
+
if deal_with_destination_addr( tund, src_id, destination_addr, domain_port ) then
|
461
|
+
next_tick
|
462
|
+
end
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
427
466
|
end
|
428
467
|
end
|
429
468
|
|
@@ -431,170 +470,69 @@ module Girl
|
|
431
470
|
# send data
|
432
471
|
#
|
433
472
|
def send_data( sock, data, to_addr )
|
434
|
-
unless to_addr
|
435
|
-
return false
|
436
|
-
end
|
437
|
-
|
438
473
|
begin
|
439
|
-
sock.
|
474
|
+
written = sock.sendmsg_nonblock( data, 0, to_addr )
|
440
475
|
rescue IO::WaitWritable, Errno::EINTR
|
441
|
-
|
476
|
+
print '.'
|
477
|
+
return :wait
|
442
478
|
rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
|
443
|
-
|
444
|
-
puts "#{ Time.new } #{ e.class }, close tund"
|
445
|
-
close_tund( sock )
|
446
|
-
return false
|
447
|
-
end
|
479
|
+
return :fatal
|
448
480
|
end
|
449
481
|
|
450
|
-
|
482
|
+
written
|
451
483
|
end
|
452
484
|
|
453
485
|
##
|
454
|
-
#
|
486
|
+
# set dst closing
|
455
487
|
#
|
456
|
-
def
|
457
|
-
|
458
|
-
close_sock( dst )
|
459
|
-
@pause_dsts.delete( dst )
|
488
|
+
def set_dst_closing( dst )
|
489
|
+
return if dst.closed?
|
460
490
|
dst_info = @dst_infos[ dst ]
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
@dst_infos.delete( dst )
|
465
|
-
return
|
466
|
-
end
|
467
|
-
|
468
|
-
tund_info = @tund_infos[ tund ]
|
469
|
-
dst_id = dst_info[ :id ]
|
470
|
-
|
471
|
-
if dst_info[ :is_src_closed ]
|
472
|
-
# puts "debug1 4-3. after close dst -> src closed ? yes -> del dst ext -> send fin2"
|
473
|
-
del_dst_ext( tund_info, dst_id )
|
474
|
-
data = [ 0, FIN2, dst_id ].pack( 'Q>Cn' )
|
475
|
-
else
|
476
|
-
# puts "debug1 3-1. after close dst -> src closed ? no -> send fin1"
|
477
|
-
data = [ 0, FIN1, dst_id, dst_info[ :biggest_pack_id ], dst_info[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
|
478
|
-
end
|
479
|
-
|
480
|
-
send_data( tund, data, tund_info[ :tun_addr ] )
|
481
|
-
end
|
482
|
-
|
483
|
-
##
|
484
|
-
# close tund
|
485
|
-
#
|
486
|
-
def close_tund( tund )
|
487
|
-
# puts "debug1 close tund"
|
488
|
-
close_sock( tund )
|
489
|
-
tund_info = @tund_infos.delete( tund )
|
490
|
-
tund_info[ :dsts ].each{ | _, dst | set_is_closing( dst ) }
|
491
|
-
@tunneling_tunds.delete( tund_info[ :tun_addr ] )
|
492
|
-
@tunds.delete( tund_info[ :port ] )
|
493
|
-
end
|
494
|
-
|
495
|
-
##
|
496
|
-
# close sock
|
497
|
-
#
|
498
|
-
def close_sock( sock )
|
499
|
-
sock.close
|
500
|
-
@reads.delete( sock )
|
501
|
-
@writes.delete( sock )
|
502
|
-
@roles.delete( sock )
|
503
|
-
end
|
504
|
-
|
505
|
-
##
|
506
|
-
# del dst ext
|
507
|
-
#
|
508
|
-
def del_dst_ext( tund_info, dst_id )
|
509
|
-
dst = tund_info[ :dsts ][ dst_id ]
|
510
|
-
|
511
|
-
if dst && dst.closed?
|
512
|
-
tund_info[ :wmems ].delete_if { | dst_id_pack_id, _ | dst_id_pack_id.first == dst_id }
|
513
|
-
tund_info[ :dsts ].delete( dst_id )
|
514
|
-
dst_info = @dst_infos.delete( dst )
|
515
|
-
|
516
|
-
if dst_info
|
517
|
-
tund_info[ :dst_ids ].delete( dst_info[ :src_id ] )
|
518
|
-
end
|
519
|
-
end
|
491
|
+
dst_info[ :closing ] = true
|
492
|
+
@reads.delete( dst )
|
493
|
+
add_write( dst )
|
520
494
|
end
|
521
495
|
|
522
496
|
##
|
523
|
-
#
|
497
|
+
# set dst closing write
|
524
498
|
#
|
525
|
-
def
|
526
|
-
if
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
pack_ids.each do | pack_id |
|
532
|
-
tund_info[ :wmems ].delete( [ dst_info[ :id ], pack_id ] )
|
533
|
-
dst_info[ :send_ats ].delete( pack_id )
|
534
|
-
end
|
535
|
-
|
536
|
-
dst_info[ :completed_pack_id ] = completed_pack_id
|
537
|
-
end
|
499
|
+
def set_dst_closing_write( dst )
|
500
|
+
return if dst.closed?
|
501
|
+
dst_info = @dst_infos[ dst ]
|
502
|
+
dst_info[ :closing_write ] = true
|
503
|
+
add_write( dst )
|
538
504
|
end
|
539
505
|
|
540
506
|
##
|
541
|
-
#
|
507
|
+
# set streamd closing
|
542
508
|
#
|
543
|
-
def
|
544
|
-
|
509
|
+
def set_streamd_closing( streamd )
|
510
|
+
return if streamd.closed?
|
511
|
+
streamd_info = @streamd_infos[ streamd ]
|
512
|
+
streamd_info[ :closing ] = true
|
513
|
+
@reads.delete( streamd )
|
514
|
+
add_write( streamd )
|
545
515
|
end
|
546
516
|
|
547
517
|
##
|
548
|
-
# write
|
518
|
+
# set streamd closing write
|
549
519
|
#
|
550
|
-
def
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
return
|
556
|
-
end
|
557
|
-
|
558
|
-
data = dst_info[ :wbuff ]
|
559
|
-
|
560
|
-
if data.empty?
|
561
|
-
@writes.delete( dst )
|
562
|
-
return
|
563
|
-
end
|
564
|
-
|
565
|
-
begin
|
566
|
-
written = dst.write_nonblock( data )
|
567
|
-
rescue IO::WaitWritable, Errno::EINTR
|
568
|
-
return
|
569
|
-
rescue Exception => e
|
570
|
-
# puts "debug1 write dst #{ e.class }"
|
571
|
-
close_dst( dst )
|
572
|
-
return
|
573
|
-
end
|
574
|
-
|
575
|
-
# puts "debug2 write dst #{ written }"
|
576
|
-
data = data[ written..-1 ]
|
577
|
-
dst_info[ :wbuff ] = data
|
578
|
-
dst_info[ :last_continue_at ] = Time.new
|
520
|
+
def set_streamd_closing_write( streamd )
|
521
|
+
return if streamd.closed?
|
522
|
+
streamd_info = @streamd_infos[ streamd ]
|
523
|
+
streamd_info[ :closing_write ] = true
|
524
|
+
add_write( streamd )
|
579
525
|
end
|
580
526
|
|
581
527
|
##
|
582
|
-
#
|
528
|
+
# set tund is closing
|
583
529
|
#
|
584
|
-
def
|
530
|
+
def set_tund_closing( tund )
|
531
|
+
return if tund.closed?
|
585
532
|
tund_info = @tund_infos[ tund ]
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
data = [ 0, IP_CHANGED ].pack( 'Q>C' )
|
590
|
-
send_data( tund, data, tund_info[ :changed_tun_addr ] )
|
591
|
-
end
|
592
|
-
|
593
|
-
close_tund( tund )
|
594
|
-
return
|
595
|
-
end
|
596
|
-
|
597
|
-
@writes.delete( tund )
|
533
|
+
tund_info[ :closing ] = true
|
534
|
+
@reads.delete( tund )
|
535
|
+
add_write( tund )
|
598
536
|
end
|
599
537
|
|
600
538
|
##
|
@@ -611,302 +549,410 @@ module Girl
|
|
611
549
|
data, addrinfo, rflags, *controls = proxyd.recvmsg
|
612
550
|
from_addr = addrinfo.to_sockaddr
|
613
551
|
|
614
|
-
if @tunneling_tunds.include?( from_addr )
|
552
|
+
if @tunneling_tunds.include?( from_addr ) then
|
615
553
|
tund = @tunneling_tunds[ from_addr ]
|
616
554
|
tund_info = @tund_infos[ tund ]
|
617
|
-
port
|
618
|
-
|
619
|
-
puts "p#{ Process.pid } #{ Time.new } resend tund port #{ port }"
|
620
|
-
send_data( proxyd, data, from_addr )
|
555
|
+
puts "p#{ Process.pid } #{ Time.new } resend tund port #{ tund_info[ :port ] }, #{ tund_info[ :stream_port ] }"
|
556
|
+
add_proxyd_ctlmsg_tund_port( tund_info )
|
621
557
|
return
|
622
558
|
end
|
623
559
|
|
624
560
|
result = @custom.check( data, addrinfo )
|
625
561
|
|
626
|
-
if result != :success
|
562
|
+
if result != :success then
|
627
563
|
puts "p#{ Process.pid } #{ Time.new } #{ result }"
|
628
564
|
return
|
629
565
|
end
|
630
566
|
|
631
567
|
tund = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
632
568
|
tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
633
|
-
|
569
|
+
tund_port = tund.local_address.ip_port
|
570
|
+
add_read( tund, :tund )
|
634
571
|
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
572
|
+
tcpd = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
573
|
+
tcpd.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 ) if RUBY_PLATFORM.include?( 'linux' )
|
574
|
+
tcpd.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
575
|
+
tcpd_port = tcpd.local_address.ip_port
|
576
|
+
tcpd.listen( 127 )
|
577
|
+
add_read( tcpd, :tcpd )
|
578
|
+
|
579
|
+
tund_info = {
|
580
|
+
port: tund_port, # 端口
|
581
|
+
tcpd: tcpd, # 对应的tcpd
|
582
|
+
tcpd_port: tcpd_port, # tcpd端口
|
583
|
+
ctlmsgs: [], # [ ctlmsg, to_addr ]
|
584
|
+
tun_addr: from_addr, # tun地址
|
585
|
+
dsts: {}, # dst_id => dst
|
586
|
+
dst_ids: {}, # src_id => dst_id
|
587
|
+
created_at: Time.new, # 创建时间
|
588
|
+
last_recv_at: nil, # 上一次收到流量的时间
|
589
|
+
last_sent_at: nil, # 上一次发出流量的时间
|
590
|
+
closing: false, # 准备关闭
|
591
|
+
closing_read: false, # 准备关闭读
|
592
|
+
closing_write: false, # 准备关闭写
|
593
|
+
changed_tun_addr: nil # 记录到和tun addr不符的来源地址
|
648
594
|
}
|
649
595
|
|
650
|
-
|
596
|
+
@tunneling_tunds[ from_addr ] = tund
|
597
|
+
@tund_infos[ tund ] = tund_info
|
598
|
+
@tcpd_infos[ tcpd ] = {
|
599
|
+
tund: tund
|
600
|
+
}
|
651
601
|
|
652
|
-
|
653
|
-
|
654
|
-
send_data( proxyd, data, from_addr )
|
602
|
+
puts "p#{ Process.pid } #{ Time.new } a new tunnel #{ addrinfo.ip_unpack.inspect } - #{ tund_port }, #{ tcpd_port }, #{ @tund_infos.size } tunds"
|
603
|
+
add_proxyd_ctlmsg_tund_port( tund_info )
|
655
604
|
end
|
656
605
|
|
657
606
|
##
|
658
|
-
# read
|
607
|
+
# read tund
|
659
608
|
#
|
660
|
-
def
|
609
|
+
def read_tund( tund )
|
661
610
|
begin
|
662
|
-
data =
|
611
|
+
data, addrinfo, rflags, *controls = tund.recvmsg_nonblock
|
663
612
|
rescue IO::WaitReadable, Errno::EINTR
|
664
|
-
|
665
|
-
rescue Exception => e
|
666
|
-
# puts "debug1 read dst #{ e.class }"
|
667
|
-
set_is_closing( dst )
|
613
|
+
print 'r'
|
668
614
|
return
|
669
615
|
end
|
670
616
|
|
671
|
-
tunnel_data( dst, data )
|
672
|
-
end
|
673
|
-
|
674
|
-
##
|
675
|
-
# read tund
|
676
|
-
#
|
677
|
-
def read_tund( tund )
|
678
|
-
data, addrinfo, rflags, *controls = tund.recvmsg
|
679
617
|
from_addr = addrinfo.to_sockaddr
|
680
|
-
now = Time.new
|
681
618
|
tund_info = @tund_infos[ tund ]
|
682
619
|
|
683
|
-
if from_addr != tund_info[ :tun_addr ]
|
684
|
-
# 通常是光猫刷新ip
|
620
|
+
if from_addr != tund_info[ :tun_addr ] then
|
621
|
+
# 通常是光猫刷新ip和端口,但万一不是,为了避免脏数据注入,关闭tund
|
685
622
|
puts "p#{ Process.pid } #{ Time.new } from #{ addrinfo.inspect } not match tun addr #{ Addrinfo.new( tund_info[ :tun_addr ] ).inspect }"
|
686
623
|
tund_info[ :changed_tun_addr ] = from_addr
|
687
|
-
|
624
|
+
set_tund_closing( tund )
|
688
625
|
return
|
689
626
|
end
|
690
627
|
|
691
|
-
tund_info[ :last_recv_at ] =
|
628
|
+
tund_info[ :last_recv_at ] = Time.new
|
692
629
|
pack_id = data[ 0, 8 ].unpack( 'Q>' ).first
|
630
|
+
return if pack_id != 0
|
693
631
|
|
694
|
-
|
695
|
-
ctl_num = data[ 8 ].unpack( 'C' ).first
|
696
|
-
|
697
|
-
case ctl_num
|
698
|
-
when A_NEW_SOURCE
|
699
|
-
src_id = data[ 9, 8 ].unpack( 'Q>' ).first
|
700
|
-
dst_id = tund_info[ :dst_ids ][ src_id ]
|
632
|
+
ctl_num = data[ 8 ].unpack( 'C' ).first
|
701
633
|
|
702
|
-
|
703
|
-
|
704
|
-
|
634
|
+
case ctl_num
|
635
|
+
when A_NEW_SOURCE then
|
636
|
+
src_id = data[ 9, 8 ].unpack( 'Q>' ).first
|
637
|
+
dst_id = tund_info[ :dst_ids ][ src_id ]
|
705
638
|
|
706
|
-
|
707
|
-
|
708
|
-
|
639
|
+
if dst_id then
|
640
|
+
dst = tund_info[ :dsts ][ dst_id ]
|
641
|
+
return unless dst
|
709
642
|
|
710
|
-
|
711
|
-
|
712
|
-
send_data( tund, data2, tund_info[ :tun_addr ] )
|
713
|
-
return
|
643
|
+
if dst.closed? then
|
644
|
+
dst_id = 0
|
714
645
|
end
|
715
646
|
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
src_id, relay_src_pack_id, continue_dst_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
|
722
|
-
|
723
|
-
dst_id = tund_info[ :dst_ids ][ src_id ]
|
724
|
-
return unless dst_id
|
647
|
+
# puts "debug1 resend paired #{ dst_id }"
|
648
|
+
data2 = [ 0, PAIRED, src_id, dst_id ].pack( 'Q>CQ>n' )
|
649
|
+
add_ctlmsg( tund, data2 )
|
650
|
+
return
|
651
|
+
end
|
725
652
|
|
726
|
-
|
727
|
-
|
653
|
+
data = data[ 17..-1 ]
|
654
|
+
domain_port = @custom.decode( data )
|
655
|
+
# puts "debug1 a new source #{ src_id } #{ domain_port }"
|
656
|
+
resolve_domain( tund, src_id, domain_port )
|
657
|
+
when TUN_FIN then
|
658
|
+
puts "p#{ Process.pid } #{ Time.new } recv tun fin"
|
659
|
+
set_tund_closing( tund )
|
660
|
+
end
|
661
|
+
end
|
728
662
|
|
729
|
-
|
730
|
-
|
663
|
+
##
|
664
|
+
# read tcpd
|
665
|
+
#
|
666
|
+
def read_tcpd( tcpd )
|
667
|
+
begin
|
668
|
+
streamd, addrinfo = tcpd.accept_nonblock
|
669
|
+
rescue IO::WaitReadable, Errno::EINTR
|
670
|
+
print 'r'
|
671
|
+
return
|
672
|
+
end
|
731
673
|
|
732
|
-
|
674
|
+
# puts "debug1 accept a streamd"
|
675
|
+
tcpd_info = @tcpd_infos[ tcpd ]
|
676
|
+
tund = tcpd_info[ :tund ]
|
733
677
|
|
734
|
-
|
735
|
-
|
678
|
+
@streamd_infos[ streamd ] = {
|
679
|
+
tund: tund, # 对应tund
|
680
|
+
dst: nil, # 对应dst
|
681
|
+
wbuff: '' # 写前,写往近端stream
|
682
|
+
}
|
736
683
|
|
737
|
-
|
738
|
-
|
739
|
-
ranges = []
|
740
|
-
ignored = false
|
741
|
-
curr_pack_id = dst_info[ :continue_src_pack_id ] + 1
|
684
|
+
add_read( streamd, :streamd )
|
685
|
+
end
|
742
686
|
|
743
|
-
|
744
|
-
|
745
|
-
|
687
|
+
##
|
688
|
+
# read dst
|
689
|
+
#
|
690
|
+
def read_dst( dst )
|
691
|
+
begin
|
692
|
+
data = dst.read_nonblock( READ_SIZE )
|
693
|
+
rescue IO::WaitReadable, Errno::EINTR
|
694
|
+
print 'r'
|
695
|
+
return
|
696
|
+
rescue Exception => e
|
697
|
+
# puts "debug1 read dst #{ e.class }"
|
698
|
+
dst_info = close_read_dst( dst )
|
699
|
+
streamd = dst_info[ :streamd ]
|
700
|
+
set_streamd_closing_write( streamd ) if streamd
|
701
|
+
return
|
702
|
+
end
|
746
703
|
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
704
|
+
dst_info = @dst_infos[ dst ]
|
705
|
+
streamd = dst_info[ :streamd ]
|
706
|
+
|
707
|
+
if streamd then
|
708
|
+
unless streamd.closed? then
|
709
|
+
streamd_info = @streamd_infos[ streamd ]
|
710
|
+
data = @custom.encode( data )
|
711
|
+
# puts "debug2 add streamd.wbuff encoded #{ data.bytesize }"
|
712
|
+
streamd_info[ :wbuff ] << data
|
713
|
+
add_write( streamd )
|
714
|
+
|
715
|
+
if streamd_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
|
716
|
+
puts "p#{ Process.pid } #{ Time.new } pause dst #{ dst_info[ :id ] } #{ dst_info[ :domain_port ] }"
|
717
|
+
dst_info[ :paused ] = true
|
718
|
+
@reads.delete( dst )
|
719
|
+
end
|
720
|
+
end
|
721
|
+
else
|
722
|
+
dst_info[ :rbuff ] << data
|
753
723
|
|
754
|
-
|
755
|
-
|
724
|
+
if dst_info[ :rbuff ].bytesize >= WBUFF_LIMIT then
|
725
|
+
# puts "debug1 dst.rbuff full #{ dst_info[ :rbuff ].bytesize }"
|
726
|
+
set_dst_closing( dst )
|
727
|
+
end
|
728
|
+
end
|
729
|
+
end
|
756
730
|
|
757
|
-
|
758
|
-
|
759
|
-
|
731
|
+
##
|
732
|
+
# read streamd
|
733
|
+
#
|
734
|
+
def read_streamd( streamd )
|
735
|
+
begin
|
736
|
+
data = streamd.read_nonblock( READ_SIZE )
|
737
|
+
rescue IO::WaitReadable, Errno::EINTR
|
738
|
+
print 'r'
|
739
|
+
return
|
740
|
+
rescue Exception => e
|
741
|
+
# puts "debug1 read streamd #{ e.class }"
|
742
|
+
streamd_info = close_read_streamd( streamd )
|
743
|
+
dst = streamd_info[ :dst ]
|
744
|
+
set_dst_closing_write( dst ) if dst
|
745
|
+
return
|
746
|
+
end
|
760
747
|
|
761
|
-
|
762
|
-
|
763
|
-
ranges = ranges.map{ | pack_id_begin, pack_id_end | [ pack_id_begin, pack_id_end ].pack( 'Q>Q>' ) }
|
748
|
+
streamd_info = @streamd_infos[ streamd ]
|
749
|
+
dst = streamd_info[ :dst ]
|
764
750
|
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
send_data( tund, data2, tund_info[ :tun_addr ] )
|
769
|
-
idx += MULTI_MISS_SIZE
|
770
|
-
end
|
771
|
-
end
|
772
|
-
when MULTI_MISS
|
773
|
-
dst_id, *ranges = data[ 9..-1 ].unpack( 'nQ>*' )
|
751
|
+
unless dst then
|
752
|
+
dst_id = data[ 0, 2 ].unpack( 'n' ).first
|
753
|
+
tund = streamd_info[ :tund ]
|
774
754
|
|
775
|
-
|
776
|
-
|
755
|
+
if tund.closed? then
|
756
|
+
set_streamd_closing( streamd )
|
757
|
+
return
|
758
|
+
end
|
777
759
|
|
778
|
-
|
779
|
-
|
760
|
+
tund_info = @tund_infos[ tund ]
|
761
|
+
dst = tund_info[ :dsts ][ dst_id ]
|
780
762
|
|
781
|
-
|
763
|
+
unless dst then
|
764
|
+
set_streamd_closing( streamd )
|
765
|
+
return
|
766
|
+
end
|
782
767
|
|
783
|
-
|
768
|
+
# puts "debug1 set streamd.dst #{ dst_id }"
|
769
|
+
streamd_info[ :dst ] = dst
|
770
|
+
dst_info = @dst_infos[ dst ]
|
784
771
|
|
785
|
-
|
772
|
+
unless dst_info[ :rbuff ].empty? then
|
773
|
+
# puts "debug1 encode and move dst.rbuff to streamd.wbuff"
|
774
|
+
streamd_info[ :wbuff ] << @custom.encode( dst_info[ :rbuff ] )
|
775
|
+
end
|
786
776
|
|
787
|
-
|
788
|
-
|
777
|
+
dst_info[ :streamd ] = streamd
|
778
|
+
data = data[ 2..-1 ]
|
789
779
|
|
790
|
-
|
791
|
-
|
780
|
+
return if data.empty?
|
781
|
+
end
|
792
782
|
|
793
|
-
|
794
|
-
|
795
|
-
|
783
|
+
unless dst.closed? then
|
784
|
+
dst_info = @dst_infos[ dst ]
|
785
|
+
data = @custom.decode( data )
|
786
|
+
# puts "debug2 add dst.wbuff decoded #{ data.bytesize }"
|
787
|
+
dst_info[ :wbuff ] << data
|
788
|
+
dst_info[ :last_recv_at ] = Time.new
|
789
|
+
add_write( dst )
|
790
|
+
end
|
791
|
+
end
|
796
792
|
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
793
|
+
##
|
794
|
+
# write proxyd
|
795
|
+
#
|
796
|
+
def write_proxyd( proxyd )
|
797
|
+
# 发ctlmsg
|
798
|
+
while @proxyd_info[ :ctlmsgs ].any? do
|
799
|
+
data, to_addr = @proxyd_info[ :ctlmsgs ].first
|
800
|
+
sent = send_data( proxyd, data, to_addr )
|
804
801
|
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
802
|
+
if sent == :wait then
|
803
|
+
return
|
804
|
+
else
|
805
|
+
@proxyd_info[ :ctlmsgs ].shift
|
806
|
+
end
|
807
|
+
end
|
809
808
|
|
810
|
-
|
811
|
-
|
809
|
+
@writes.delete( proxyd )
|
810
|
+
end
|
812
811
|
|
813
|
-
|
814
|
-
|
812
|
+
##
|
813
|
+
# write tund
|
814
|
+
#
|
815
|
+
def write_tund( tund )
|
816
|
+
tund_info = @tund_infos[ tund ]
|
815
817
|
|
816
|
-
|
817
|
-
|
818
|
+
# 处理关闭
|
819
|
+
if tund_info[ :closing ] then
|
820
|
+
if tund_info[ :changed_tun_addr ] then
|
821
|
+
data = [ 0, IP_CHANGED ].pack( 'Q>C' )
|
822
|
+
send_data( tund, data, tund_info[ :changed_tun_addr ] )
|
823
|
+
end
|
818
824
|
|
819
|
-
|
820
|
-
|
821
|
-
|
825
|
+
close_tund( tund )
|
826
|
+
return
|
827
|
+
end
|
822
828
|
|
823
|
-
|
824
|
-
if send_data( tund, data2, tund_info[ :tun_addr ] )
|
825
|
-
dst_info[ :last_continue_at ] = now
|
826
|
-
end
|
827
|
-
end
|
828
|
-
end
|
829
|
-
end
|
830
|
-
when FIN1
|
831
|
-
src_id, biggest_src_pack_id, continue_dst_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
|
829
|
+
now = Time.new
|
832
830
|
|
833
|
-
|
834
|
-
|
831
|
+
# 发ctlmsg
|
832
|
+
while tund_info[ :ctlmsgs ].any? do
|
833
|
+
data = tund_info[ :ctlmsgs ].first
|
834
|
+
sent = send_data( tund, data, tund_info[ :tun_addr ] )
|
835
835
|
|
836
|
-
|
837
|
-
|
836
|
+
if sent == :fatal then
|
837
|
+
close_tund( tund )
|
838
|
+
return
|
839
|
+
elsif sent == :wait then
|
840
|
+
# puts "debug1 #{ Time.new } wait send ctlmsg left #{ tund_info[ :ctlmsgs ].size }"
|
841
|
+
tund_info[ :last_sent_at ] = now
|
842
|
+
return
|
843
|
+
end
|
838
844
|
|
839
|
-
|
840
|
-
|
845
|
+
tund_info[ :ctlmsgs ].shift
|
846
|
+
end
|
841
847
|
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
release_wmems( tund_info, dst_info, continue_dst_pack_id )
|
848
|
+
tund_info[ :last_sent_at ] = now
|
849
|
+
@writes.delete( tund )
|
850
|
+
end
|
846
851
|
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
852
|
+
##
|
853
|
+
# write dst
|
854
|
+
#
|
855
|
+
def write_dst( dst )
|
856
|
+
return if dst.closed?
|
857
|
+
dst_info = @dst_infos[ dst ]
|
858
|
+
streamd = dst_info[ :streamd ]
|
853
859
|
|
854
|
-
|
855
|
-
|
860
|
+
# 处理关闭
|
861
|
+
if dst_info[ :closing ] then
|
862
|
+
close_dst( dst )
|
856
863
|
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
puts "p#{ Process.pid } #{ Time.new } recv tun fin"
|
861
|
-
set_is_closing( tund )
|
864
|
+
if streamd then
|
865
|
+
close_read_streamd( streamd )
|
866
|
+
set_streamd_closing_write( streamd )
|
862
867
|
end
|
863
868
|
|
864
869
|
return
|
865
870
|
end
|
866
871
|
|
867
|
-
|
872
|
+
data = dst_info[ :wbuff ]
|
868
873
|
|
869
|
-
|
870
|
-
|
874
|
+
# 写前为空,处理关闭写
|
875
|
+
if data.empty? then
|
876
|
+
if dst_info[ :closing_write ] then
|
877
|
+
close_write_dst( dst )
|
878
|
+
else
|
879
|
+
@writes.delete( dst )
|
880
|
+
end
|
871
881
|
|
872
|
-
|
873
|
-
|
882
|
+
return
|
883
|
+
end
|
874
884
|
|
875
|
-
|
876
|
-
|
885
|
+
# 写入
|
886
|
+
begin
|
887
|
+
written = dst.write_nonblock( data )
|
888
|
+
rescue IO::WaitWritable, Errno::EINTR
|
889
|
+
print 'w'
|
890
|
+
return
|
891
|
+
rescue Exception => e
|
892
|
+
# puts "debug1 write dst #{ e.class }"
|
893
|
+
close_write_dst( dst )
|
894
|
+
close_read_streamd( streamd ) if streamd
|
895
|
+
return
|
896
|
+
end
|
877
897
|
|
878
|
-
|
898
|
+
# puts "debug2 written dst #{ written }"
|
899
|
+
data = data[ written..-1 ]
|
900
|
+
dst_info[ :wbuff ] = data
|
901
|
+
end
|
879
902
|
|
880
|
-
|
881
|
-
|
903
|
+
##
|
904
|
+
# write streamd
|
905
|
+
#
|
906
|
+
def write_streamd( streamd )
|
907
|
+
return if streamd.closed?
|
908
|
+
streamd_info = @streamd_infos[ streamd ]
|
909
|
+
dst = streamd_info[ :dst ]
|
910
|
+
|
911
|
+
# 处理关闭
|
912
|
+
if streamd_info[ :closing ] then
|
913
|
+
close_streamd( streamd )
|
914
|
+
|
915
|
+
if dst then
|
916
|
+
close_read_dst( dst )
|
917
|
+
set_dst_closing_write( dst )
|
918
|
+
end
|
882
919
|
|
883
|
-
|
884
|
-
# puts "debug2 #{ data.inspect }"
|
885
|
-
data = @custom.decode( data )
|
886
|
-
# puts "debug1 decoded pack #{ pack_id }"
|
920
|
+
return
|
887
921
|
end
|
888
922
|
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
923
|
+
data = streamd_info[ :wbuff ]
|
924
|
+
|
925
|
+
# 写前为空,处理关闭写
|
926
|
+
if data.empty? then
|
927
|
+
if streamd_info[ :closing_write ] then
|
928
|
+
close_write_streamd( streamd )
|
929
|
+
else
|
930
|
+
@writes.delete( streamd )
|
894
931
|
end
|
895
932
|
|
896
|
-
|
897
|
-
|
898
|
-
dst_info[ :wbuff ] << data
|
899
|
-
add_write( dst )
|
900
|
-
# puts "debug2 update continue src pack #{ pack_id }"
|
933
|
+
return
|
934
|
+
end
|
901
935
|
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
936
|
+
# 写入
|
937
|
+
begin
|
938
|
+
written = streamd.write_nonblock( data )
|
939
|
+
rescue IO::WaitWritable, Errno::EINTR
|
940
|
+
print 'w'
|
941
|
+
return
|
942
|
+
rescue Exception => e
|
943
|
+
# puts "debug1 write streamd #{ e.class }"
|
944
|
+
close_write_streamd( streamd )
|
945
|
+
close_read_dst( dst ) if dst
|
946
|
+
return
|
947
|
+
end
|
948
|
+
|
949
|
+
# puts "debug2 written streamd #{ written }"
|
950
|
+
data = data[ written..-1 ]
|
951
|
+
streamd_info[ :wbuff ] = data
|
952
|
+
|
953
|
+
if dst && !dst.closed? then
|
954
|
+
dst_info = @dst_infos[ dst ]
|
955
|
+
dst_info[ :last_sent_at ] = Time.new
|
910
956
|
end
|
911
957
|
end
|
912
958
|
|