girl 0.82.0 → 0.87.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.

@@ -20,7 +20,6 @@ module Girl
20
20
 
21
21
  conf = JSON.parse( IO.binread( config_path ), symbolize_names: true )
22
22
  proxyd_port = conf[ :proxyd_port ]
23
- proxyd_tmp_dir = conf[ :proxyd_tmp_dir ]
24
23
  worker_count = conf[ :worker_count ]
25
24
  end
26
25
 
@@ -28,26 +27,6 @@ module Girl
28
27
  proxyd_port = 6060
29
28
  end
30
29
 
31
- unless proxyd_tmp_dir
32
- proxyd_tmp_dir = '/tmp/girl.proxyd'
33
- end
34
-
35
- unless File.exist?( proxyd_tmp_dir )
36
- Dir.mkdir( proxyd_tmp_dir )
37
- end
38
-
39
- dst_chunk_dir = File.join( proxyd_tmp_dir, 'dst.chunk' )
40
-
41
- unless Dir.exist?( dst_chunk_dir )
42
- Dir.mkdir( dst_chunk_dir )
43
- end
44
-
45
- tund_chunk_dir = File.join( proxyd_tmp_dir, 'tund.chunk' )
46
-
47
- unless Dir.exist?( tund_chunk_dir )
48
- Dir.mkdir( tund_chunk_dir )
49
- end
50
-
51
30
  nprocessors = Etc.nprocessors
52
31
 
53
32
  if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors
@@ -57,17 +36,37 @@ module Girl
57
36
  title = "girl proxyd #{ Girl::VERSION }"
58
37
  puts title
59
38
  puts "proxyd port #{ proxyd_port }"
60
- puts "dst chunk dir #{ dst_chunk_dir }"
61
- puts "tund chunk dir #{ tund_chunk_dir }"
62
39
  puts "worker count #{ worker_count }"
63
40
 
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
58
+
59
+ names.each do | name |
60
+ puts "#{ name.gsub( '_', ' ' ).ljust( len ) } #{ Girl.const_get( name ) }"
61
+ end
62
+
64
63
  $0 = title
65
64
  workers = []
66
65
 
67
66
  worker_count.times do | i |
68
67
  workers << fork do
69
68
  $0 = 'girl proxyd worker'
70
- worker = Girl::ProxydWorker.new( proxyd_port, dst_chunk_dir, tund_chunk_dir )
69
+ worker = Girl::ProxydWorker.new( proxyd_port )
71
70
 
72
71
  Signal.trap( :TERM ) do
73
72
  puts "w#{ i } exit"
@@ -4,13 +4,12 @@ module Girl
4
4
  ##
5
5
  # initialize
6
6
  #
7
- def initialize( proxyd_port, dst_chunk_dir, tund_chunk_dir )
8
- @dst_chunk_dir = dst_chunk_dir
9
- @tund_chunk_dir = tund_chunk_dir
7
+ def initialize( proxyd_port )
10
8
  @custom = Girl::ProxydCustom.new
11
9
  @mutex = Mutex.new
12
10
  @reads = []
13
11
  @writes = []
12
+ @pause_dsts = []
14
13
  @roles = {} # sock => :dotr / :proxyd / :dst / :tund
15
14
  @dst_infos = {} # dst => {}
16
15
  @tunds = {} # port => tund
@@ -39,8 +38,6 @@ module Girl
39
38
  # 先写,再读
40
39
  ws.each do | sock |
41
40
  case @roles[ sock ]
42
- when :proxyd
43
- write_proxyd( sock )
44
41
  when :dst
45
42
  write_dst( sock )
46
43
  when :tund
@@ -105,20 +102,31 @@ module Girl
105
102
  if is_expired
106
103
  puts "p#{ Process.pid } #{ Time.new } expire tund #{ tund_info[ :port ] }"
107
104
  set_is_closing( tund )
105
+ need_trigger = true
108
106
  else
109
107
  data = [ 0, HEARTBEAT, rand( 128 ) ].pack( 'Q>CC' )
110
108
  # puts "debug1 #{ Time.new } #{ tund_info[ :port ] } heartbeat"
111
- add_tund_ctlmsg( tund, data )
112
-
113
- tund_info[ :dst_exts ].each do | dst_local_port, dst_ext |
114
- if dst_ext[ :dst ].closed? && ( now - dst_ext[ :last_continue_at ] > EXPIRE_AFTER )
115
- puts "p#{ Process.pid } #{ Time.new } expire dst ext #{ dst_ext[ :domain_port ] }"
116
- del_dst_ext( tund, dst_local_port )
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
117
123
  end
118
124
  end
119
- end
120
125
 
121
- need_trigger = true
126
+ if del_dst_ids.any?
127
+ tund_info[ :dsts ].delete_if { | dst_id, _ | del_dst_ids.include?( dst_id ) }
128
+ end
129
+ end
122
130
  end
123
131
  end
124
132
 
@@ -144,38 +152,71 @@ module Girl
144
152
  def loop_check_status
145
153
  Thread.new do
146
154
  loop do
147
- sleep STATUS_INTERVAL
155
+ sleep CHECK_STATUS_INTERVAL
148
156
 
149
- if @tunds.any?
150
- @mutex.synchronize do
151
- need_trigger = false
157
+ @mutex.synchronize do
158
+ need_trigger = false
152
159
 
160
+ if @tunds.any?
153
161
  @tunds.each do | tund_port, tund |
154
162
  tund_info = @tund_infos[ tund ]
155
163
 
156
- if tund_info[ :dst_exts ].any?
164
+ if tund_info[ :dsts ].any?
157
165
  now = Time.new
158
166
 
159
- tund_info[ :dst_exts ].each do | dst_local_port, dst_ext |
160
- if now - dst_ext[ :last_continue_at ] < SEND_STATUS_UNTIL
161
- data = [ 0, DEST_STATUS, dst_local_port, dst_ext[ :relay_pack_id ], dst_ext[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
162
- add_tund_ctlmsg( tund, data )
163
- need_trigger = true
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 ] )
164
173
  end
165
174
  end
166
175
  end
176
+ end
177
+ end
167
178
 
168
- if tund_info[ :paused ] && ( tund_info[ :dst_exts ].map{ | _, dst_ext | dst_ext[ :wmems ].size }.sum < RESUME_BELOW )
169
- puts "p#{ Process.pid } #{ Time.new } resume tund"
170
- tund_info[ :paused ] = false
171
- add_write( tund )
172
- need_trigger = true
179
+ if @pause_dsts.any?
180
+ resume_dsts = []
181
+ ignore_dsts = []
182
+
183
+ @pause_dsts.each do | dst |
184
+ dst_info = @dst_infos[ dst ]
185
+
186
+ if dst_info
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
173
201
  end
174
202
  end
175
203
 
176
- if need_trigger
177
- next_tick
204
+ if resume_dsts.any?
205
+ resume_dsts.each do | dst |
206
+ add_read( dst )
207
+ end
208
+
209
+ @pause_dsts -= resume_dsts
210
+ need_trigger = true
178
211
  end
212
+
213
+ if ignore_dsts.any?
214
+ @pause_dsts -= ignore_dsts
215
+ end
216
+ end
217
+
218
+ if need_trigger
219
+ next_tick
179
220
  end
180
221
  end
181
222
  end
@@ -185,43 +226,43 @@ module Girl
185
226
  ##
186
227
  # resolve domain
187
228
  #
188
- def resolve_domain( tund, src_id, destination_domain_port )
189
- resolv_cache = @resolv_caches[ destination_domain_port ]
229
+ def resolve_domain( tund, src_id, domain_port )
230
+ resolv_cache = @resolv_caches[ domain_port ]
190
231
 
191
232
  if resolv_cache
192
233
  destination_addr, created_at = resolv_cache
193
234
 
194
235
  if Time.new - created_at < RESOLV_CACHE_EXPIRE
195
- # puts "debug1 #{ destination_domain_port } hit resolv cache #{ Addrinfo.new( destination_addr ).inspect }"
196
- deal_with_destination_addr( tund, src_id, destination_addr, destination_domain_port )
236
+ # puts "debug1 #{ domain_port } hit resolv cache #{ Addrinfo.new( destination_addr ).inspect }"
237
+ deal_with_destination_addr( tund, src_id, destination_addr, domain_port )
197
238
  return
198
239
  end
199
240
 
200
- # puts "debug1 expire #{ destination_domain_port } resolv cache"
201
- @resolv_caches.delete( destination_domain_port )
241
+ # puts "debug1 expire #{ domain_port } resolv cache"
242
+ @resolv_caches.delete( domain_port )
202
243
  end
203
244
 
204
245
  Thread.new do
205
- colon_idx = destination_domain_port.rindex( ':' )
246
+ colon_idx = domain_port.rindex( ':' )
206
247
 
207
248
  if colon_idx
208
- destination_domain = destination_domain_port[ 0...colon_idx ]
209
- destination_port = destination_domain_port[ ( colon_idx + 1 )..-1 ].to_i
249
+ destination_domain = domain_port[ 0...colon_idx ]
250
+ destination_port = domain_port[ ( colon_idx + 1 )..-1 ].to_i
210
251
 
211
252
  begin
212
253
  destination_addr = Socket.sockaddr_in( destination_port, destination_domain )
213
254
  rescue Exception => e
214
- puts "p#{ Process.pid } #{ Time.new } sockaddr in #{ destination_domain_port } #{ e.class }"
255
+ puts "p#{ Process.pid } #{ Time.new } sockaddr in #{ domain_port } #{ e.class }"
215
256
  end
216
257
  end
217
258
 
218
259
  @mutex.synchronize do
219
260
  if destination_addr
220
- # puts "debug1 resolved #{ destination_domain_port } #{ Addrinfo.new( destination_addr ).inspect }"
221
- @resolv_caches[ destination_domain_port ] = [ destination_addr, Time.new ]
261
+ # puts "debug1 resolved #{ domain_port } #{ Addrinfo.new( destination_addr ).inspect }"
262
+ @resolv_caches[ domain_port ] = [ destination_addr, Time.new ]
222
263
 
223
264
  unless tund.closed?
224
- if deal_with_destination_addr( tund, src_id, destination_addr, destination_domain_port )
265
+ if deal_with_destination_addr( tund, src_id, destination_addr, domain_port )
225
266
  next_tick
226
267
  end
227
268
  end
@@ -233,7 +274,7 @@ module Girl
233
274
  ##
234
275
  # deal with destination addr
235
276
  #
236
- def deal_with_destination_addr( tund, src_id, destination_addr, destination_domain_port )
277
+ def deal_with_destination_addr( tund, src_id, destination_addr, domain_port )
237
278
  dst = Socket.new( Addrinfo.new( destination_addr ).ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
238
279
  dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
239
280
 
@@ -245,42 +286,34 @@ module Girl
245
286
  return false
246
287
  end
247
288
 
248
- local_port = dst.local_address.ip_port
289
+ dst_id = dst.local_address.ip_port
249
290
 
250
291
  @dst_infos[ dst ] = {
251
- local_port: local_port, # 本地端口
252
- tund: tund, # 对应tund
253
- domain_port: destination_domain_port, # 域名和端口
254
- biggest_pack_id: 0, # 最大包号码
255
- wbuff: '', # 写前
256
- cache: '', # 块读出缓存
257
- chunks: [], # 块队列,写前达到块大小时结一个块 filename
258
- spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
259
- last_continue_at: Time.new, # 上一次发生流量的时间
260
- is_closing: false # 是否准备关闭
292
+ id: dst_id, # id
293
+ tund: tund, # 对应tund
294
+ domain_port: domain_port, # 域名和端口
295
+ biggest_pack_id: 0, # 最大包号码
296
+ wbuff: '', # 写前
297
+ src_id: src_id, # 近端src id
298
+ send_ats: {}, # 上一次发出时间 pack_id => send_at
299
+ continue_src_pack_id: 0, # 收到几
300
+ pieces: {}, # 跳号包 src_pack_id => data
301
+ is_src_closed: false, # src是否已关闭
302
+ biggest_src_pack_id: 0, # src最大包号码
303
+ completed_pack_id: 0, # 完成到几(对面收到几)
304
+ last_continue_at: Time.new, # 上一次发生流量的时间
305
+ is_closing: false # 是否准备关闭
261
306
  }
307
+
262
308
  add_read( dst, :dst )
263
309
 
264
310
  tund_info = @tund_infos[ tund ]
265
- tund_info[ :dst_local_ports ][ src_id ] = local_port
266
- tund_info[ :dst_exts ][ local_port ] = {
267
- dst: dst, # dst
268
- src_id: src_id, # 近端src id
269
- domain_port: destination_domain_port, # 域名和端口
270
- wmems: {}, # 写后 pack_id => data
271
- send_ats: {}, # 上一次发出时间 pack_id => send_at
272
- relay_pack_id: 0, # 转发到几
273
- continue_src_pack_id: 0, # 收到几
274
- pieces: {}, # 跳号包 src_pack_id => data
275
- is_src_closed: false, # src是否已关闭
276
- biggest_src_pack_id: 0, # src最大包号码
277
- completed_pack_id: 0, # 完成到几(对面收到几)
278
- last_continue_at: Time.new # 上一次发生流量的时间
279
- }
311
+ tund_info[ :dst_ids ][ src_id ] = dst_id
312
+ tund_info[ :dsts ][ dst_id ] = dst
280
313
 
281
- data = [ 0, PAIRED, src_id, local_port ].pack( 'Q>CQ>n' )
282
- # puts "debug1 add ctlmsg paired #{ data.inspect }"
283
- add_tund_ctlmsg( tund, data )
314
+ data = [ 0, PAIRED, src_id, dst_id ].pack( 'Q>CQ>n' )
315
+ # puts "debug1 send paired #{ data.inspect }"
316
+ send_data( tund, data, tund_info[ :tun_addr ] )
284
317
 
285
318
  true
286
319
  end
@@ -295,101 +328,39 @@ module Girl
295
328
 
296
329
  puts "p#{ Process.pid } #{ Time.new } proxyd bind on #{ proxyd_port }"
297
330
  @proxyd = proxyd
298
- @proxyd_ctlmsgs = [] # [ to_addr, data ]
299
331
  add_read( proxyd, :proxyd )
300
332
  end
301
333
 
302
334
  ##
303
- # add proxyd ctlmsg
304
- #
305
- def add_proxyd_ctlmsg( data, to_addr )
306
- @proxyd_ctlmsgs << [ to_addr, data ]
307
- add_write( @proxyd )
308
- end
309
-
310
- ##
311
- # add tund ctlmsg
335
+ # add read
312
336
  #
313
- def add_tund_ctlmsg( tund, data )
314
- tund_info = @tund_infos[ tund ]
315
- tund_info[ :ctlmsgs ] << data
316
- add_write( tund )
317
- end
337
+ def add_read( sock, role = nil )
338
+ if sock && !sock.closed? && !@reads.include?( sock )
339
+ @reads << sock
318
340
 
319
- ##
320
- # add tund wbuff
321
- #
322
- def add_tund_wbuff( tund, dst_local_port, pack_id, data )
323
- tund_info = @tund_infos[ tund ]
324
- tund_info[ :wbuffs ] << [ dst_local_port, pack_id, data ]
325
-
326
- if tund_info[ :wbuffs ].size >= WBUFFS_LIMIT
327
- spring = tund_info[ :chunks ].size > 0 ? ( tund_info[ :spring ] + 1 ) : 0
328
- filename = "#{ Process.pid }-#{ tund_info[ :port ] }.#{ spring }"
329
- chunk_path = File.join( @tund_chunk_dir, filename )
330
- datas = tund_info[ :wbuffs ].map{ | _dst_local_port, _pack_id, _data | [ [ _dst_local_port, _pack_id, _data.bytesize ].pack( 'nQ>n' ), _data ].join }
331
-
332
- begin
333
- IO.binwrite( chunk_path, datas.join )
334
- rescue Errno::ENOSPC => e
335
- puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close tund"
336
- set_is_closing( tund )
337
- return
341
+ if role
342
+ @roles[ sock ] = role
338
343
  end
339
-
340
- tund_info[ :chunks ] << filename
341
- tund_info[ :spring ] = spring
342
- tund_info[ :wbuffs ].clear
343
344
  end
344
-
345
- add_write( tund )
346
345
  end
347
346
 
348
347
  ##
349
- # add dst wbuff
348
+ # add write
350
349
  #
351
- def add_dst_wbuff( dst, data )
352
- dst_info = @dst_infos[ dst ]
353
- dst_info[ :wbuff ] << data
354
-
355
- if dst_info[ :wbuff ].bytesize >= CHUNK_SIZE
356
- spring = dst_info[ :chunks ].size > 0 ? ( dst_info[ :spring ] + 1 ) : 0
357
- filename = "#{ Process.pid }-#{ dst_info[ :local_port ] }.#{ spring }"
358
- chunk_path = File.join( @dst_chunk_dir, filename )
359
-
360
- begin
361
- IO.binwrite( chunk_path, dst_info[ :wbuff ] )
362
- rescue Errno::ENOSPC => e
363
- puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close dst"
364
- set_is_closing( dst )
365
- return
366
- end
367
-
368
- dst_info[ :chunks ] << filename
369
- dst_info[ :spring ] = spring
370
- dst_info[ :wbuff ].clear
350
+ def add_write( sock )
351
+ if sock && !sock.closed? && !@writes.include?( sock )
352
+ @writes << sock
371
353
  end
372
-
373
- add_write( dst )
374
354
  end
375
355
 
376
356
  ##
377
- # add read
357
+ # add pause dst
378
358
  #
379
- def add_read( sock, role )
380
- unless @reads.include?( sock )
381
- @reads << sock
382
- end
383
-
384
- @roles[ sock ] = role
385
- end
359
+ def add_pause_dst( dst )
360
+ @reads.delete( dst )
386
361
 
387
- ##
388
- # add write
389
- #
390
- def add_write( sock )
391
- if sock && !sock.closed? && !@writes.include?( sock )
392
- @writes << sock
362
+ unless @pause_dsts.include?( dst )
363
+ @pause_dsts << dst
393
364
  end
394
365
  end
395
366
 
@@ -415,6 +386,53 @@ module Girl
415
386
  end
416
387
  end
417
388
 
389
+ ##
390
+ # tunnel data
391
+ #
392
+ def tunnel_data( dst, data )
393
+ dst_info = @dst_infos[ dst ]
394
+ tund = dst_info[ :tund ]
395
+
396
+ if tund.closed?
397
+ puts "p#{ Process.pid } #{ Time.new } tund closed, close dst"
398
+ set_is_closing( dst )
399
+ return
400
+ end
401
+
402
+ tund_info = @tund_infos[ tund ]
403
+ dst_id = dst_info[ :id ]
404
+ now = Time.new
405
+ pack_id = dst_info[ :biggest_pack_id ]
406
+ idx = 0
407
+ len = data.bytesize
408
+
409
+ while idx < len
410
+ chunk = data[ idx, PACK_SIZE ]
411
+ pack_id += 1
412
+
413
+ if pack_id <= CONFUSE_UNTIL
414
+ chunk = @custom.encode( chunk )
415
+ # puts "debug1 encoded chunk #{ pack_id }"
416
+ end
417
+
418
+ data2 = [ [ pack_id, dst_id ].pack( 'Q>n' ), chunk ].join
419
+ sent = send_data( tund, data2, tund_info[ :tun_addr ] )
420
+ # puts "debug2 written pack #{ pack_id } #{ sent }"
421
+ tund_info[ :wmems ][ [ dst_id, pack_id ] ] = data2
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
428
+
429
+ # 写后超过上限,暂停读dst
430
+ if tund_info[ :wmems ].size >= WMEMS_LIMIT
431
+ puts "p#{ Process.pid } #{ Time.new } pause dst #{ dst_id } #{ dst_info[ :domain_port ] } #{ dst_info[ :biggest_pack_id ] }"
432
+ add_pause_dst( dst )
433
+ end
434
+ end
435
+
418
436
  ##
419
437
  # send data
420
438
  #
@@ -440,33 +458,28 @@ module Girl
440
458
  def close_dst( dst )
441
459
  # puts "debug1 close dst"
442
460
  close_sock( dst )
443
- dst_info = @dst_infos.delete( dst )
461
+ @pause_dsts.delete( dst )
462
+ dst_info = @dst_infos[ dst ]
463
+ tund = dst_info[ :tund ]
444
464
 
445
- dst_info[ :chunks ].each do | filename |
446
- begin
447
- File.delete( File.join( @dst_chunk_dir, filename ) )
448
- rescue Errno::ENOENT
449
- end
465
+ if tund.closed?
466
+ @dst_infos.delete( dst )
467
+ return
450
468
  end
451
469
 
452
- tund = dst_info[ :tund ]
453
- return if tund.closed?
454
-
455
470
  tund_info = @tund_infos[ tund ]
456
- local_port = dst_info[ :local_port ]
457
- dst_ext = tund_info[ :dst_exts ][ local_port ]
458
- return unless dst_ext
471
+ dst_id = dst_info[ :id ]
459
472
 
460
- if dst_ext[ :is_src_closed ]
473
+ if dst_info[ :is_src_closed ]
461
474
  # puts "debug1 4-3. after close dst -> src closed ? yes -> del dst ext -> send fin2"
462
- del_dst_ext( tund, local_port )
463
- data = [ 0, FIN2, local_port ].pack( 'Q>Cn' )
464
- add_tund_ctlmsg( tund, data )
475
+ del_dst_ext( tund_info, dst_id )
476
+ data = [ 0, FIN2, dst_id ].pack( 'Q>Cn' )
465
477
  else
466
478
  # puts "debug1 3-1. after close dst -> src closed ? no -> send fin1"
467
- data = [ 0, FIN1, local_port, dst_info[ :biggest_pack_id ], dst_ext[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
468
- add_tund_ctlmsg( tund, data )
479
+ data = [ 0, FIN1, dst_id, dst_info[ :biggest_pack_id ], dst_info[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
469
480
  end
481
+
482
+ send_data( tund, data, tund_info[ :tun_addr ] )
470
483
  end
471
484
 
472
485
  ##
@@ -475,16 +488,8 @@ module Girl
475
488
  def close_tund( tund )
476
489
  # puts "debug1 close tund"
477
490
  close_sock( tund )
478
-
479
491
  tund_info = @tund_infos.delete( tund )
480
- tund_info[ :chunks ].each do | filename |
481
- begin
482
- File.delete( File.join( @tund_chunk_dir, filename ) )
483
- rescue Errno::ENOENT
484
- end
485
- end
486
-
487
- tund_info[ :dst_exts ].each{ | _, dst_ext | set_is_closing( dst_ext[ :dst ] ) }
492
+ tund_info[ :dsts ].each{ | _, dst | set_is_closing( dst ) }
488
493
  @tunneling_tunds.delete( tund_info[ :tun_addr ] )
489
494
  @tunds.delete( tund_info[ :port ] )
490
495
  end
@@ -502,30 +507,34 @@ module Girl
502
507
  ##
503
508
  # del dst ext
504
509
  #
505
- def del_dst_ext( tund, dst_local_port )
506
- tund_info = @tund_infos[ tund ]
507
- dst_ext = tund_info[ :dst_exts ].delete( dst_local_port )
510
+ def del_dst_ext( tund_info, dst_id )
511
+ tund_info[ :wmems ].delete_if { | port_and_pack_id, _ | port_and_pack_id.first == dst_id }
512
+ dst = tund_info[ :dsts ].delete( dst_id )
508
513
 
509
- if dst_ext
510
- tund_info[ :dst_local_ports ].delete( dst_ext[ :src_id ] )
514
+ if dst
515
+ dst_info = @dst_infos.delete( dst )
516
+
517
+ if dst_info
518
+ tund_info[ :dst_ids ].delete( dst_info[ :src_id ] )
519
+ end
511
520
  end
512
521
  end
513
522
 
514
523
  ##
515
524
  # release wmems
516
525
  #
517
- def release_wmems( dst_ext, completed_pack_id )
518
- if completed_pack_id > dst_ext[ :completed_pack_id ]
526
+ def release_wmems( tund_info, dst_info, completed_pack_id )
527
+ if completed_pack_id > dst_info[ :completed_pack_id ]
519
528
  # puts "debug2 update completed pack #{ completed_pack_id }"
520
529
 
521
- pack_ids = dst_ext[ :wmems ].keys.select { | pack_id | pack_id <= completed_pack_id }
530
+ pack_ids = dst_info[ :send_ats ].keys.select { | pack_id | pack_id <= completed_pack_id }
522
531
 
523
532
  pack_ids.each do | pack_id |
524
- dst_ext[ :wmems ].delete( pack_id )
525
- dst_ext[ :send_ats ].delete( pack_id )
533
+ tund_info[ :wmems ].delete( [ dst_info[ :id ], pack_id ] )
534
+ dst_info[ :send_ats ].delete( pack_id )
526
535
  end
527
536
 
528
- dst_ext[ :completed_pack_id ] = completed_pack_id
537
+ dst_info[ :completed_pack_id ] = completed_pack_id
529
538
  end
530
539
  end
531
540
 
@@ -536,54 +545,21 @@ module Girl
536
545
  @dotw.write( '.' )
537
546
  end
538
547
 
539
- ##
540
- # write proxyd
541
- #
542
- def write_proxyd( proxyd )
543
- while @proxyd_ctlmsgs.any?
544
- to_addr, data = @proxyd_ctlmsgs.first
545
-
546
- unless send_data( proxyd, data, to_addr )
547
- return
548
- end
549
-
550
- @proxyd_ctlmsgs.shift
551
- end
552
-
553
- @writes.delete( proxyd )
554
- end
555
-
556
548
  ##
557
549
  # write dst
558
550
  #
559
551
  def write_dst( dst )
560
552
  dst_info = @dst_infos[ dst ]
561
- from, data = :cache, dst_info[ :cache ]
562
-
563
- if data.empty?
564
- if dst_info[ :chunks ].any?
565
- path = File.join( @dst_chunk_dir, dst_info[ :chunks ].shift )
566
553
 
567
- begin
568
- data = dst_info[ :cache ] = IO.binread( path )
569
- File.delete( path )
570
- rescue Errno::ENOENT => e
571
- puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
572
- close_dst( dst )
573
- return
574
- end
575
- else
576
- from, data = :wbuff, dst_info[ :wbuff ]
577
- end
554
+ if dst_info[ :is_closing ]
555
+ close_dst( dst )
556
+ return
578
557
  end
579
558
 
580
- if data.empty?
581
- if dst_info[ :is_closing ]
582
- close_dst( dst )
583
- else
584
- @writes.delete( dst )
585
- end
559
+ data = dst_info[ :wbuff ]
586
560
 
561
+ if data.empty?
562
+ @writes.delete( dst )
587
563
  return
588
564
  end
589
565
 
@@ -599,7 +575,7 @@ module Girl
599
575
 
600
576
  # puts "debug2 write dst #{ written }"
601
577
  data = data[ written..-1 ]
602
- dst_info[ from ] = data
578
+ dst_info[ :wbuff ] = data
603
579
  dst_info[ :last_continue_at ] = Time.new
604
580
  end
605
581
 
@@ -607,7 +583,6 @@ module Girl
607
583
  # write tund
608
584
  #
609
585
  def write_tund( tund )
610
- now = Time.new
611
586
  tund_info = @tund_infos[ tund ]
612
587
 
613
588
  if tund_info[ :is_closing ]
@@ -620,104 +595,7 @@ module Girl
620
595
  return
621
596
  end
622
597
 
623
- # 传ctlmsg
624
- while tund_info[ :ctlmsgs ].any?
625
- data = tund_info[ :ctlmsgs ].first
626
-
627
- unless send_data( tund, data, tund_info[ :tun_addr ] )
628
- return
629
- end
630
-
631
- tund_info[ :ctlmsgs ].shift
632
- end
633
-
634
- # 重传
635
- while tund_info[ :resendings ].any?
636
- dst_local_port, pack_id = tund_info[ :resendings ].first
637
- dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
638
-
639
- if dst_ext
640
- data = dst_ext[ :wmems ][ pack_id ]
641
-
642
- if data
643
- unless send_data( tund, data, tund_info[ :tun_addr ] )
644
- return
645
- end
646
-
647
- dst_ext[ :last_continue_at ] = now
648
- end
649
- end
650
-
651
- tund_info[ :resendings ].shift
652
- end
653
-
654
- # 若写后达到上限,暂停取写前
655
- if tund_info[ :dst_exts ].map{ | _, dst_ext | dst_ext[ :wmems ].size }.sum >= WMEMS_LIMIT
656
- unless tund_info[ :paused ]
657
- puts "p#{ Process.pid } #{ Time.new } pause tund #{ tund_info[ :port ] }"
658
- tund_info[ :paused ] = true
659
- end
660
-
661
- @writes.delete( tund )
662
- return
663
- end
664
-
665
- # 取写前
666
- if tund_info[ :caches ].any?
667
- datas = tund_info[ :caches ]
668
- elsif tund_info[ :chunks ].any?
669
- path = File.join( @tund_chunk_dir, tund_info[ :chunks ].shift )
670
-
671
- begin
672
- data = IO.binread( path )
673
- File.delete( path )
674
- rescue Errno::ENOENT => e
675
- puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
676
- close_tund( tund )
677
- return
678
- end
679
-
680
- caches = []
681
-
682
- until data.empty?
683
- _dst_local_port, _pack_id, pack_size = data[ 0, 12 ].unpack( 'nQ>n' )
684
- caches << [ _dst_local_port, _pack_id, data[ 12, pack_size ] ]
685
- data = data[ ( 12 + pack_size )..-1 ]
686
- end
687
-
688
- datas = tund_info[ :caches ] = caches
689
- elsif tund_info[ :wbuffs ].any?
690
- datas = tund_info[ :wbuffs ]
691
- else
692
- @writes.delete( tund )
693
- return
694
- end
695
-
696
- while datas.any?
697
- dst_local_port, pack_id, data = datas.first
698
- dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
699
-
700
- if dst_ext
701
- if pack_id <= CONFUSE_UNTIL
702
- data = @custom.encode( data )
703
- # puts "debug1 encoded pack #{ pack_id }"
704
- end
705
-
706
- data = [ [ pack_id, dst_local_port ].pack( 'Q>n' ), data ].join
707
-
708
- unless send_data( tund, data, tund_info[ :tun_addr ] )
709
- return
710
- end
711
-
712
- # puts "debug2 written pack #{ pack_id }"
713
- dst_ext[ :relay_pack_id ] = pack_id
714
- dst_ext[ :wmems ][ pack_id ] = data
715
- dst_ext[ :send_ats ][ pack_id ] = now
716
- dst_ext[ :last_continue_at ] = now
717
- end
718
-
719
- datas.shift
720
- end
598
+ @writes.delete( tund )
721
599
  end
722
600
 
723
601
  ##
@@ -734,7 +612,15 @@ module Girl
734
612
  data, addrinfo, rflags, *controls = proxyd.recvmsg
735
613
  from_addr = addrinfo.to_sockaddr
736
614
 
737
- return if @tunneling_tunds.include?( from_addr )
615
+ if @tunneling_tunds.include?( from_addr )
616
+ tund = @tunneling_tunds[ from_addr ]
617
+ tund_info = @tund_infos[ tund ]
618
+ port = tund_info[ :port ]
619
+ data = [ 0, TUND_PORT, port ].pack( 'Q>Cn' )
620
+ puts "p#{ Process.pid } #{ Time.new } resend tund port #{ port }"
621
+ send_data( proxyd, data, from_addr )
622
+ return
623
+ end
738
624
 
739
625
  result = @custom.check( data, addrinfo )
740
626
 
@@ -751,16 +637,11 @@ module Girl
751
637
  @tunds[ port ] = tund
752
638
  @tund_infos[ tund ] = {
753
639
  port: port, # 端口
754
- ctlmsgs: [], # data
755
- wbuffs: [], # 写前缓存 [ dst_local_port, pack_id, data ]
756
- caches: [], # 块读出缓存 [ dst_local_port, pack_id, data ]
757
- chunks: [], # 块队列 filename
758
- spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
640
+ wbuffs: [], # 写前 [ dst_id, pack_id, data ]
641
+ wmems: {}, # 写后 [ dst_id, pack_id ] => data
759
642
  tun_addr: from_addr, # tun地址
760
- dst_exts: {}, # dst额外信息 dst_local_port => {}
761
- dst_local_ports: {}, # src_id => dst_local_port
762
- paused: false, # 是否暂停写
763
- resendings: [], # 重传队列 [ dst_local_port, pack_id ]
643
+ dsts: {}, # dst额外信息 dst_id => dst
644
+ dst_ids: {}, # src_id => dst_id
764
645
  created_at: Time.new, # 创建时间
765
646
  last_recv_at: nil, # 上一次收到流量的时间,过期关闭
766
647
  is_closing: false, # 是否准备关闭
@@ -771,7 +652,7 @@ module Girl
771
652
 
772
653
  data = [ 0, TUND_PORT, port ].pack( 'Q>Cn' )
773
654
  puts "p#{ Process.pid } #{ Time.new } a new tunnel #{ addrinfo.ip_unpack.inspect } - #{ port }, #{ @tunds.size } tunds"
774
- add_proxyd_ctlmsg( data, from_addr )
655
+ send_data( proxyd, data, from_addr )
775
656
  end
776
657
 
777
658
  ##
@@ -779,7 +660,7 @@ module Girl
779
660
  #
780
661
  def read_dst( dst )
781
662
  begin
782
- data = dst.read_nonblock( PACK_SIZE )
663
+ data = dst.read_nonblock( READ_SIZE )
783
664
  rescue IO::WaitReadable, Errno::EINTR
784
665
  return
785
666
  rescue Exception => e
@@ -788,20 +669,7 @@ module Girl
788
669
  return
789
670
  end
790
671
 
791
- # puts "debug2 read dst #{ data.inspect }"
792
- dst_info = @dst_infos[ dst ]
793
- dst_info[ :last_continue_at ] = Time.new
794
- tund = dst_info[ :tund ]
795
-
796
- if tund.closed?
797
- puts "p#{ Process.pid } #{ Time.new } tund closed, close dst"
798
- set_is_closing( dst )
799
- return
800
- end
801
-
802
- pack_id = dst_info[ :biggest_pack_id ] + 1
803
- dst_info[ :biggest_pack_id ] = pack_id
804
- add_tund_wbuff( tund, dst_info[ :local_port ], pack_id, data )
672
+ tunnel_data( dst, data )
805
673
  end
806
674
 
807
675
  ##
@@ -830,112 +698,165 @@ module Girl
830
698
  case ctl_num
831
699
  when A_NEW_SOURCE
832
700
  src_id = data[ 9, 8 ].unpack( 'Q>' ).first
833
- dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
701
+ dst_id = tund_info[ :dst_ids ][ src_id ]
834
702
 
835
- if dst_local_port
836
- dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
837
- return unless dst_ext
703
+ if dst_id
704
+ dst = tund_info[ :dsts ][ dst_id ]
705
+ return unless dst
838
706
 
839
- if dst_ext[ :dst ].closed?
840
- dst_local_port = 0
707
+ if dst.closed?
708
+ dst_id = 0
841
709
  end
842
710
 
843
- # puts "debug1 readd ctlmsg paired #{ dst_local_port }"
844
- data2 = [ 0, PAIRED, src_id, dst_local_port ].pack( 'Q>CQ>n' )
845
- add_tund_ctlmsg( tund, data2 )
711
+ # puts "debug1 resend paired #{ dst_id }"
712
+ data2 = [ 0, PAIRED, src_id, dst_id ].pack( 'Q>CQ>n' )
713
+ send_data( tund, data2, tund_info[ :tun_addr ] )
846
714
  return
847
715
  end
848
716
 
849
717
  data = data[ 17..-1 ]
850
- destination_domain_port = @custom.decode( data )
851
- puts "p#{ Process.pid } #{ Time.new } a new source #{ src_id } #{ destination_domain_port }"
852
- resolve_domain( tund, src_id, destination_domain_port )
718
+ domain_port = @custom.decode( data )
719
+ puts "p#{ Process.pid } #{ Time.new } a new source #{ src_id } #{ domain_port }"
720
+ resolve_domain( tund, src_id, domain_port )
853
721
  when SOURCE_STATUS
854
722
  src_id, relay_src_pack_id, continue_dst_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
855
723
 
856
- dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
857
- return unless dst_local_port
724
+ dst_id = tund_info[ :dst_ids ][ src_id ]
725
+ return unless dst_id
726
+
727
+ dst = tund_info[ :dsts ][ dst_id ]
728
+ return unless dst
858
729
 
859
- dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
860
- return unless dst_ext
730
+ dst_info = @dst_infos[ dst ]
731
+ return unless dst_info
861
732
 
862
- # puts "debug2 got source status"
733
+ # puts "debug2 got source status #{ Time.new }"
863
734
 
864
- release_wmems( dst_ext, continue_dst_pack_id )
735
+ # 消写后
736
+ release_wmems( tund_info, dst_info, continue_dst_pack_id )
865
737
 
866
738
  # 发miss
867
- if !dst_ext[ :dst ].closed? && ( dst_ext[ :continue_src_pack_id ] < relay_src_pack_id )
739
+ if !dst.closed? && ( dst_info[ :continue_src_pack_id ] < relay_src_pack_id )
868
740
  ranges = []
869
- curr_pack_id = dst_ext[ :continue_src_pack_id ] + 1
741
+ ignored = false
742
+ curr_pack_id = dst_info[ :continue_src_pack_id ] + 1
870
743
 
871
- dst_ext[ :pieces ].keys.sort.each do | pack_id |
744
+ dst_info[ :pieces ].keys.sort.each do | pack_id |
872
745
  if pack_id > curr_pack_id
873
746
  ranges << [ curr_pack_id, pack_id - 1 ]
747
+
748
+ if ranges.size >= MISS_RANGE_LIMIT
749
+ puts "p#{ Process.pid } #{ Time.new } break add miss range at #{ pack_id }"
750
+ ignored = true
751
+ break
752
+ end
874
753
  end
875
754
 
876
755
  curr_pack_id = pack_id + 1
877
756
  end
878
757
 
879
- if curr_pack_id <= relay_src_pack_id
758
+ if !ignored && ( curr_pack_id <= relay_src_pack_id )
880
759
  ranges << [ curr_pack_id, relay_src_pack_id ]
881
760
  end
882
761
 
883
- pack_count = 0
884
- # puts "debug1 continue/relay #{ dst_ext[ :continue_src_pack_id ] }/#{ relay_src_pack_id } send MISS #{ ranges.size }"
762
+ # puts "debug1 continue/relay #{ dst_info[ :continue_src_pack_id ] }/#{ relay_src_pack_id } send MISS #{ ranges.size }"
763
+ idx = 0
764
+ ranges = ranges.map{ | pack_id_begin, pack_id_end | [ pack_id_begin, pack_id_end ].pack( 'Q>Q>' ) }
885
765
 
886
- ranges.each do | pack_id_begin, pack_id_end |
887
- if pack_count >= BREAK_SEND_MISS
888
- puts "p#{ Process.pid } #{ Time.new } break send miss at #{ pack_id_begin }"
889
- break
890
- end
766
+ while idx < ranges.size
767
+ chunk = ranges[ idx, MULTI_MISS_SIZE ].join
768
+ data2 = [ [ 0, MULTI_MISS, src_id ].pack( 'Q>CQ>' ), chunk ].join
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>*' )
775
+
776
+ dst = tund_info[ :dsts ][ dst_id ]
777
+ return unless dst
778
+
779
+ dst_info = @dst_infos[ dst ]
780
+ return unless dst_info
781
+
782
+ return if ranges.empty? || ( ranges.size % 2 != 0 )
783
+
784
+ # puts "debug1 got multi miss #{ dst_id } #{ ranges.size }"
785
+
786
+ idx = 0
891
787
 
892
- data2 = [ 0, MISS, src_id, pack_id_begin, pack_id_end ].pack( 'Q>CQ>Q>Q>' )
893
- add_tund_ctlmsg( tund, data2 )
894
- pack_count += ( pack_id_end - pack_id_begin + 1 )
788
+ while idx < ranges.size
789
+ pack_id_begin, pack_id_end = ranges[ idx ], ranges[ idx + 1 ]
790
+
791
+ ( pack_id_begin..pack_id_end ).each do | pack_id |
792
+ send_at = dst_info[ :send_ats ][ pack_id ]
793
+
794
+ if send_at
795
+ break if now - send_at < CHECK_STATUS_INTERVAL
796
+ data2 = tund_info[ :wmems ][ [ dst_id, pack_id ] ]
797
+
798
+ if data2
799
+ if send_data( tund, data2, tund_info[ :tun_addr ] )
800
+ dst_info[ :last_continue_at ] = now
801
+ end
802
+ end
803
+ end
895
804
  end
805
+
806
+ idx += 2
896
807
  end
897
808
  when MISS
898
- dst_local_port, pack_id_begin, pack_id_end = data[ 9, 18 ].unpack( 'nQ>Q>' )
809
+ dst_id, pack_id_begin, pack_id_end = data[ 9, 18 ].unpack( 'nQ>Q>' )
810
+
811
+ dst = tund_info[ :dsts ][ dst_id ]
812
+ return unless dst
899
813
 
900
- dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
901
- return unless dst_ext
814
+ dst_info = @dst_infos[ dst ]
815
+ return unless dst_info
902
816
 
903
817
  ( pack_id_begin..pack_id_end ).each do | pack_id |
904
- send_at = dst_ext[ :send_ats ][ pack_id ]
818
+ send_at = dst_info[ :send_ats ][ pack_id ]
905
819
 
906
820
  if send_at
907
- break if now - send_at < STATUS_INTERVAL
908
- tund_info[ :resendings ] << [ dst_local_port, pack_id ]
821
+ break if now - send_at < CHECK_STATUS_INTERVAL
822
+ data2 = tund_info[ :wmems ][ [ dst_id, pack_id ] ]
823
+
824
+ if data2
825
+ if send_data( tund, data2, tund_info[ :tun_addr ] )
826
+ dst_info[ :last_continue_at ] = now
827
+ end
828
+ end
909
829
  end
910
830
  end
911
-
912
- add_write( tund )
913
831
  when FIN1
914
832
  src_id, biggest_src_pack_id, continue_dst_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
915
833
 
916
- dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
917
- return unless dst_local_port
834
+ dst_id = tund_info[ :dst_ids ][ src_id ]
835
+ return unless dst_id
836
+
837
+ dst = tund_info[ :dsts ][ dst_id ]
838
+ return unless dst
918
839
 
919
- dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
920
- return unless dst_ext
840
+ dst_info = @dst_infos[ dst ]
841
+ return unless dst_info
921
842
 
922
843
  # puts "debug1 got fin1 #{ src_id } biggest src pack #{ biggest_src_pack_id } completed dst pack #{ continue_dst_pack_id }"
923
- dst_ext[ :is_src_closed ] = true
924
- dst_ext[ :biggest_src_pack_id ] = biggest_src_pack_id
925
- release_wmems( dst_ext, continue_dst_pack_id )
844
+ dst_info[ :is_src_closed ] = true
845
+ dst_info[ :biggest_src_pack_id ] = biggest_src_pack_id
846
+ release_wmems( tund_info, dst_info, continue_dst_pack_id )
926
847
 
927
- if biggest_src_pack_id == dst_ext[ :continue_src_pack_id ]
848
+ if biggest_src_pack_id == dst_info[ :continue_src_pack_id ]
928
849
  # puts "debug1 4-1. tund recv fin1 -> all traffic received ? -> close dst after write"
929
- set_is_closing( dst_ext[ :dst ] )
850
+ set_is_closing( dst )
930
851
  end
931
852
  when FIN2
932
853
  src_id = data[ 9, 8 ].unpack( 'Q>' ).first
933
854
 
934
- dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
935
- return unless dst_local_port
855
+ dst_id = tund_info[ :dst_ids ][ src_id ]
856
+ return unless dst_id
936
857
 
937
858
  # puts "debug1 3-2. tund recv fin2 -> del dst ext"
938
- del_dst_ext( tund, dst_local_port )
859
+ del_dst_ext( tund_info, dst_id )
939
860
  when TUN_FIN
940
861
  puts "p#{ Process.pid } #{ Time.new } recv tun fin"
941
862
  set_is_closing( tund )
@@ -946,12 +867,16 @@ module Girl
946
867
 
947
868
  src_id = data[ 8, 8 ].unpack( 'Q>' ).first
948
869
 
949
- dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
950
- return unless dst_local_port
870
+ dst_id = tund_info[ :dst_ids ][ src_id ]
871
+ return unless dst_id
951
872
 
952
- dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
953
- return if dst_ext.nil? || dst_ext[ :dst ].closed?
954
- return if ( pack_id <= dst_ext[ :continue_src_pack_id ] ) || dst_ext[ :pieces ].include?( pack_id )
873
+ dst = tund_info[ :dsts ][ dst_id ]
874
+ return unless dst
875
+
876
+ dst_info = @dst_infos[ dst ]
877
+ return unless dst_info
878
+
879
+ return if ( pack_id <= dst_info[ :continue_src_pack_id ] ) || dst_info[ :pieces ].include?( pack_id )
955
880
 
956
881
  data = data[ 16..-1 ]
957
882
  # puts "debug2 got pack #{ pack_id }"
@@ -963,25 +888,26 @@ module Girl
963
888
  end
964
889
 
965
890
  # 放进写前,跳号放碎片缓存
966
- if pack_id - dst_ext[ :continue_src_pack_id ] == 1
967
- while dst_ext[ :pieces ].include?( pack_id + 1 )
968
- data << dst_ext[ :pieces ].delete( pack_id + 1 )
891
+ if pack_id - dst_info[ :continue_src_pack_id ] == 1
892
+ while dst_info[ :pieces ].include?( pack_id + 1 )
893
+ data << dst_info[ :pieces ].delete( pack_id + 1 )
969
894
  pack_id += 1
970
895
  end
971
896
 
972
- dst_ext[ :continue_src_pack_id ] = pack_id
973
- dst_ext[ :last_continue_at ] = now
974
- add_dst_wbuff( dst_ext[ :dst ], data )
897
+ dst_info[ :continue_src_pack_id ] = pack_id
898
+ dst_info[ :last_continue_at ] = now
899
+ dst_info[ :wbuff ] << data
900
+ add_write( dst )
975
901
  # puts "debug2 update continue src pack #{ pack_id }"
976
902
 
977
- # 接到流量,若对面已关闭,且流量正好收全,关闭dst
978
- if dst_ext[ :is_src_closed ] && ( pack_id == dst_ext[ :biggest_src_pack_id ] )
903
+ # 若对面已关闭,且流量正好收全,关闭dst
904
+ if dst_info[ :is_src_closed ] && ( pack_id == dst_info[ :biggest_src_pack_id ] )
979
905
  # puts "debug1 4-2. tund recv traffic -> src closed and all traffic received ? -> close dst after write"
980
- set_is_closing( dst_ext[ :dst ] )
981
- return
906
+ set_is_closing( dst )
982
907
  end
983
- else
984
- dst_ext[ :pieces ][ pack_id ] = data
908
+ elsif !dst_info[ :pieces ].include?( pack_id )
909
+ dst_info[ :pieces ][ pack_id ] = data
910
+ dst_info[ :last_continue_at ] = now
985
911
  end
986
912
  end
987
913