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