girl 0.88.0 → 0.93.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.

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