girl 0.69.0 → 0.72.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b16f67f52bf05cd498b16e480ee9d29577217ef93fd8964c0256e3816eb837e6
4
- data.tar.gz: 38a5178d59930baa536a2ea882b8e17d86bb5e194386bcf9fc5ef7615d8e120e
3
+ metadata.gz: adb4fc20afbb57a58552ce95b6580c6d743fd85a1cd7f0a20d820c9481c8d2dd
4
+ data.tar.gz: be27ab104fd8715186d18031999f6050eeaebeb6d8bc7c4e19b3f29ebd997928
5
5
  SHA512:
6
- metadata.gz: 139f1ea8a12a8e58d236e873ef1b3cb2944768ac1f2940fc986afb3ed5095e82550235f89fa1a81981b1981d6422f5bebd7918874a8cfe2fef7ab586af1d22fa
7
- data.tar.gz: 0554a3541237a4f62d838309b3ff703b18480218646bf6f3920e218d477aed0d41e21ef1cd944e4f042539c0d0d17a73a15f0fedcd4d8356d350b7052c1071a5
6
+ metadata.gz: 7f458ccee3db7c612f29715fa66c70e70fd3d4a8bfd4773c9590ebf830079d3d6ea3bc1daeed67d26ef70b08d7857592073602f20b0937b5f384713d15ff334f
7
+ data.tar.gz: 504190992e2966453ab1783f6fcccea05ac18c0a067a3b9c0372e6b097392d5b4f64c70d1ea405aa090de15408d6d9eb86a1042b6feb27ef922ca6c213bcdb80
@@ -19,17 +19,12 @@ girl.gemspec
19
19
  lib/girl.rb
20
20
  lib/girl/custom.rb
21
21
  lib/girl/head.rb
22
- lib/girl/hex.rb
23
22
  lib/girl/proxy_custom.rb
24
23
  lib/girl/proxy_worker.rb
25
24
  lib/girl/proxy.rb
26
25
  lib/girl/proxyd_custom.rb
27
26
  lib/girl/proxyd_worker.rb
28
27
  lib/girl/proxyd.rb
29
- lib/girl/resolv.rb
30
- lib/girl/resolvd.rb
31
- lib/girl/tun.rb
32
- lib/girl/tund.rb
33
28
  lib/girl/udp.rb
34
29
  lib/girl/udpd.rb
35
30
  lib/girl/version.rb
@@ -1,18 +1,17 @@
1
1
  module Girl
2
- PACK_SIZE = 1328 # 包大小 1400(console MTU) - 8(PPPoE header) - 40(IPv6 header) - 8(UDP header) - 8(pack id) - 8(src id) = 1328
3
- CHUNK_SIZE = PACK_SIZE * 1000 # 块大小
4
- WBUFFS_LIMIT = 1000 # 写前上限,超过上限结一个块
5
- WMEMS_LIMIT = 100_000 # 写后上限,达到上限暂停写
6
- RESUME_BELOW = 50_000 # 降到多少以下恢复写
7
- EXPIRE_NEW = 10 # 创建之后多久没有流量进来,过期
8
- EXPIRE_AFTER = 300 # 多久没有新流量,过期
9
- CHECK_EXPIRE_INTERVAL = 30 # 检查过期间隔
10
- HEARTBEAT_INTERVAL = 30 # 心跳间隔
11
- STATUS_INTERVAL = 0.5 # 发送状态间隔
12
- SEND_STATUS_UNTIL = 10 # 持续的告之对面状态,直到没有流量往来,持续多少秒
13
- BREAK_SEND_MISS = 10_000 # miss包个数上限,达到上限忽略要后面的段,可控碎片缓存
14
- CONFUSE_UNTIL = 5 # 混淆前几个包
15
- RESOLV_CACHE_EXPIRE = 300 # dns查询结果缓存多久过期
2
+ PACK_SIZE = 1328 # 包大小 1400(console MTU) - 8(PPPoE header) - 40(IPv6 header) - 8(UDP header) - 8(pack id) - 8(src id) = 1328
3
+ CHUNK_SIZE = PACK_SIZE * 1000 # 块大小
4
+ WBUFFS_LIMIT = 1000 # 写前上限,超过上限结一个块
5
+ WMEMS_LIMIT = 100_000 # 写后上限,达到上限暂停写
6
+ RESUME_BELOW = 50_000 # 降到多少以下恢复写
7
+ EXPIRE_NEW = 10 # 创建之后多久没有流量进来,过期
8
+ EXPIRE_AFTER = 300 # 多久没有新流量,过期
9
+ CHECK_EXPIRE_INTERVAL = 30 # 检查过期间隔
10
+ STATUS_INTERVAL = 0.5 # 发送状态间隔
11
+ SEND_STATUS_UNTIL = 10 # 持续的告之对面状态,直到没有流量往来,持续多少秒
12
+ BREAK_SEND_MISS = 10_000 # miss包个数上限,达到上限忽略要后面的段,可控碎片缓存
13
+ CONFUSE_UNTIL = 5 # 混淆前几个包
14
+ RESOLV_CACHE_EXPIRE = 300 # dns查询结果缓存多久过期
16
15
  TUND_PORT = 1
17
16
  HEARTBEAT = 2
18
17
  A_NEW_SOURCE = 3
@@ -26,8 +25,6 @@ module Girl
26
25
  GOT_FIN2 = 11
27
26
  TUND_FIN = 12
28
27
  TUN_FIN = 13
29
- CTL_CLOSE = 1
30
- CTL_RESUME = 2
31
28
  HTTP_OK = "HTTP/1.1 200 OK\r\n\r\n"
32
29
  # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
33
30
  RESERVED_ROUTE = <<EOF
@@ -23,29 +23,37 @@ require 'socket'
23
23
  #
24
24
  # tun-tund:
25
25
  #
26
- # Q>: 0 ctlmsg -> C: 2 heartbeat -> C: random char
27
- # 3 a new src -> Q>: src_id -> encoded destination address
28
- # 4 paired -> Q>: src_id -> n: dst_port
29
- # 5 dst status -> n: dst_port -> Q>Q>: biggest_dst_pack_id continue_src_pack_id
30
- # 6 src status -> Q>: src_id -> Q>Q>: biggest_src_pack_id continue_dst_pack_id
31
- # 7 miss -> Q>: src_id/n: dst_port -> Q>Q>: pack_id_begin pack_id_end
32
- # 8 fin1 -> Q>: src_id/n: dst_port -> Q>Q>: biggest_src_pack_id continue_dst_pack_id / biggest_dst_pack_id continue_src_pack_id
26
+ # Q>: 0 ctlmsg -> C: 2 heartbeat -> C: random char
27
+ # 3 a new source -> Q>: src id -> encoded destination address
28
+ # 4 paired -> Q>: src id -> n: dst port
29
+ # 5 dest status -> n: dst port -> Q>: biggest relayed dst pack id -> Q>: continue src pack id
30
+ # 6 source status -> Q>: src id -> Q>: biggest relayed src pack id -> Q>: continue dst pack id
31
+ # 7 miss -> Q>/n: src id / dst port -> Q>: pack id begin -> Q>: pack id end
32
+ # 8 fin1 -> Q>/n: src id / dst port -> Q>: biggest src pack id / biggest dst pack id -> Q>: continue dst pack id / continue src pack id
33
33
  # 9 not use
34
- # 10 fin2 -> Q>: src_id/n: dst_port
34
+ # 10 fin2 -> Q>/n: src id / dst port
35
35
  # 11 not use
36
36
  # 12 tund fin
37
37
  # 13 tun fin
38
38
  #
39
- # Q>: 1+ pack_id -> Q>: src_id/n: dst_port -> traffic
39
+ # Q>: 1+ pack_id -> Q>/n: src id / dst port -> traffic
40
40
  #
41
41
  # close logic
42
42
  # ===========
43
43
  #
44
44
  # 1-1. after close src -> dst closed ? no -> send fin1
45
- # 1-2. recv fin2 -> del src ext
45
+ # 1-2. tun recv fin2 -> del src ext
46
46
  #
47
- # 2-1. recv traffic/fin1/dst status -> dst closed and all traffic received ? -> close src after write
48
- # 2-2. after close src -> dst closed ? yes -> del src ext -> send fin2
47
+ # 2-1. tun recv fin1 -> all traffic received ? -> close src after write
48
+ # 2-2. tun recv traffic -> dst closed and all traffic received ? -> close src after write
49
+ # 2-3. after close src -> dst closed ? yes -> del src ext -> send fin2
50
+ #
51
+ # 3-1. after close dst -> src closed ? no -> send fin1
52
+ # 3-2. tund recv fin2 -> del dst ext
53
+ #
54
+ # 4-1. tund recv fin1 -> all traffic received ? -> close dst after write
55
+ # 4-2. tund recv traffic -> src closed and all traffic received ? -> close dst after write
56
+ # 4-3. after close dst -> src closed ? yes -> del dst ext -> send fin2
49
57
  #
50
58
  module Girl
51
59
  class Proxy
@@ -121,21 +129,19 @@ module Girl
121
129
  end
122
130
 
123
131
  src_chunk_dir = File.join( proxy_tmp_dir, 'src.chunk' )
124
- dst_chunk_dir = File.join( proxy_tmp_dir, 'dst.chunk' )
125
- tun_chunk_dir = File.join( proxy_tmp_dir, 'tun.chunk' )
126
-
127
- unless Dir.exist?( proxy_tmp_dir )
128
- Dir.mkdir( proxy_tmp_dir )
129
- end
130
132
 
131
133
  unless Dir.exist?( src_chunk_dir )
132
134
  Dir.mkdir( src_chunk_dir )
133
135
  end
134
136
 
137
+ dst_chunk_dir = File.join( proxy_tmp_dir, 'dst.chunk' )
138
+
135
139
  unless Dir.exist?( dst_chunk_dir )
136
140
  Dir.mkdir( dst_chunk_dir )
137
141
  end
138
142
 
143
+ tun_chunk_dir = File.join( proxy_tmp_dir, 'tun.chunk' )
144
+
139
145
  unless Dir.exist?( tun_chunk_dir )
140
146
  Dir.mkdir( tun_chunk_dir )
141
147
  end
@@ -18,7 +18,6 @@ module Girl
18
18
  @writes = []
19
19
  @roles = {} # sock => :dotr / :proxy / :src / :dst / :tun
20
20
  @src_infos = {} # src => {}
21
- @dsts = {} # local_port => dst
22
21
  @dst_infos = {} # dst => {}
23
22
  @resolv_caches = {} # domain => [ ip, created_at ]
24
23
 
@@ -168,8 +167,7 @@ module Girl
168
167
 
169
168
  @tun_info[ :src_exts ].each do | src_id, src_ext |
170
169
  if src_ext[ :dst_port ] && ( now - src_ext[ :last_continue_at ] < SEND_STATUS_UNTIL )
171
- # puts "debug2 ctl send status biggest #{ src_ext[ :biggest_pack_id ] } continue dst #{ src_ext[ :continue_dst_pack_id ] }"
172
- data = [ 0, SOURCE_STATUS, src_id, src_ext[ :biggest_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
170
+ data = [ 0, SOURCE_STATUS, src_id, src_ext[ :relay_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
173
171
  add_tun_ctlmsg( data )
174
172
  need_trigger = true
175
173
  end
@@ -180,11 +178,6 @@ module Girl
180
178
  puts "p#{ Process.pid } #{ Time.new } resume tun"
181
179
  @tun_info[ :paused ] = false
182
180
  add_write( @tun )
183
-
184
- @tun_info[ :src_exts ].each do | _, src_ext |
185
- add_write( src_ext[ :src ] )
186
- end
187
-
188
181
  need_trigger = true
189
182
  end
190
183
 
@@ -322,8 +315,8 @@ module Girl
322
315
  port: port, # 端口
323
316
  ctlmsg_rbuffs: [], # 还没配上tund,暂存的ctlmsg
324
317
  ctlmsgs: [], # [ to_addr, data ]
325
- wbuffs: [], # 写前缓存 [ src_id, data ]
326
- caches: [], # 块读出缓存 [ src_id, data ]
318
+ wbuffs: [], # 写前缓存 [ src_id, pack_id, data ]
319
+ caches: [], # 块读出缓存 [ src_id, pack_id, data ]
327
320
  chunks: [], # 块队列 filename
328
321
  spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
329
322
  tund_addr: nil, # tund地址
@@ -370,7 +363,6 @@ module Girl
370
363
 
371
364
  # puts "debug1 a new dst #{ dst.local_address.inspect }"
372
365
  local_port = dst.local_address.ip_port
373
- @dsts[ local_port ] = dst
374
366
  @dst_infos[ dst ] = {
375
367
  local_port: local_port, # 本地端口
376
368
  src: src, # 对应src
@@ -388,17 +380,13 @@ module Girl
388
380
  src_info[ :dst ] = dst
389
381
 
390
382
  if src_info[ :proxy_proto ] == :http
391
- datas = src_info[ :rbuffs ]
392
-
393
- if datas.empty?
394
- # CONNECT
383
+ if src_info[ :is_connect ]
395
384
  # puts "debug1 add src wbuff http ok"
396
385
  add_src_wbuff( src, HTTP_OK )
397
386
  else
398
- # not CONNECT
399
387
  # puts "debug1 add src rbuffs to dst wbuff"
400
388
 
401
- datas.each do | data |
389
+ src_info[ :rbuffs ].each do | _, data |
402
390
  add_dst_wbuff( dst, data )
403
391
  end
404
392
  end
@@ -420,11 +408,11 @@ module Girl
420
408
  dst_port: nil, # 远端dst端口
421
409
  wmems: {}, # 写后 pack_id => data
422
410
  send_ats: {}, # 上一次发出时间 pack_id => send_at
423
- biggest_pack_id: 0, # 发到几
411
+ relay_pack_id: 0, # 转发到几
424
412
  continue_dst_pack_id: 0, # 收到几
425
413
  pieces: {}, # 跳号包 dst_pack_id => data
426
- is_dst_closed: false, # 对面是否已关闭
427
- biggest_dst_pack_id: 0, # 对面发到几
414
+ is_dst_closed: false, # dst是否已关闭
415
+ biggest_dst_pack_id: 0, # dst最大包号码
428
416
  completed_pack_id: 0, # 完成到几(对面收到几)
429
417
  last_continue_at: Time.new # 创建,或者上一次收到连续流量,或者发出新包的时间
430
418
  }
@@ -496,17 +484,17 @@ module Girl
496
484
  ##
497
485
  # add tun wbuff
498
486
  #
499
- def add_tun_wbuff( src_id, data )
500
- @tun_info[ :wbuffs ] << [ src_id, data ]
487
+ def add_tun_wbuff( src_id, pack_id, data )
488
+ @tun_info[ :wbuffs ] << [ src_id, pack_id, data ]
501
489
 
502
490
  if @tun_info[ :wbuffs ].size >= WBUFFS_LIMIT
503
491
  spring = @tun_info[ :chunks ].size > 0 ? ( @tun_info[ :spring ] + 1 ) : 0
504
492
  filename = "#{ Process.pid }-#{ @tun_info[ :port ] }.#{ spring }"
505
493
  chunk_path = File.join( @tun_chunk_dir, filename )
506
- wbuffs = @tun_info[ :wbuffs ].map{ | _src_id, _data | [ [ _src_id, _data.bytesize ].pack( 'Q>n' ), _data ].join }
494
+ datas = @tun_info[ :wbuffs ].map{ | _src_id, _pack_id, _data | [ [ _src_id, _pack_id, _data.bytesize ].pack( 'Q>Q>n' ), _data ].join }
507
495
 
508
496
  begin
509
- IO.binwrite( chunk_path, wbuffs.join )
497
+ IO.binwrite( chunk_path, datas.join )
510
498
  rescue Errno::ENOSPC => e
511
499
  puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close tun"
512
500
  set_is_closing( @tun )
@@ -645,13 +633,13 @@ module Girl
645
633
  return if src_ext.nil? || src_ext[ :dst_port ].nil?
646
634
 
647
635
  if src_ext[ :is_dst_closed ]
648
- # puts "debug1 2-2. after close src -> dst closed ? yes -> del src ext -> send fin2"
636
+ # puts "debug1 2-3. after close src -> dst closed ? yes -> del src ext -> send fin2"
649
637
  del_src_ext( src_id )
650
638
  data = [ 0, FIN2, src_id ].pack( 'Q>CQ>' )
651
639
  add_tun_ctlmsg( data )
652
640
  else
653
641
  # puts "debug1 1-1. after close src -> dst closed ? no -> send fin1"
654
- data = [ 0, FIN1, src_id, src_ext[ :biggest_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
642
+ data = [ 0, FIN1, src_id, src_info[ :biggest_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
655
643
  add_tun_ctlmsg( data )
656
644
  end
657
645
  elsif src_info[ :proxy_type ] == :direct
@@ -674,7 +662,6 @@ module Girl
674
662
  end
675
663
  end
676
664
 
677
- @dsts.delete( dst_info[ :local_port ] )
678
665
  set_is_closing( dst_info[ :src ] )
679
666
  end
680
667
 
@@ -768,19 +755,7 @@ module Girl
768
755
 
769
756
  if data.empty?
770
757
  if src_info[ :is_closing ]
771
- if @tun
772
- if @tun.closed?
773
- close_src( src )
774
- elsif @tun_info[ :paused ]
775
- @writes.delete( src )
776
- elsif !@writes.include?( @tun )
777
- # 转发光了,正式关闭
778
- # puts "debug2 close src after tun empty"
779
- close_src( src )
780
- end
781
- else
782
- close_src( src )
783
- end
758
+ close_src( src )
784
759
  else
785
760
  @writes.delete( src )
786
761
  end
@@ -872,6 +847,10 @@ module Girl
872
847
  tun.sendmsg( data, 0, to_addr )
873
848
  rescue IO::WaitWritable, Errno::EINTR
874
849
  return
850
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH => e
851
+ puts "#{ Time.new } #{ e.class }, close tun"
852
+ close_tun( tun )
853
+ return
875
854
  end
876
855
 
877
856
  @tun_info[ :ctlmsgs ].shift
@@ -890,6 +869,10 @@ module Girl
890
869
  tun.sendmsg( data, 0, @tun_info[ :tund_addr ] )
891
870
  rescue IO::WaitWritable, Errno::EINTR
892
871
  return
872
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH => e
873
+ puts "#{ Time.new } #{ e.class }, close tun"
874
+ close_tun( tun )
875
+ return
893
876
  end
894
877
  end
895
878
  end
@@ -911,7 +894,7 @@ module Girl
911
894
 
912
895
  # 取写前
913
896
  if @tun_info[ :caches ].any?
914
- src_id, data = @tun_info[ :caches ].first
897
+ src_id, pack_id, data = @tun_info[ :caches ].first
915
898
  from = :caches
916
899
  elsif @tun_info[ :chunks ].any?
917
900
  path = File.join( @tun_chunk_dir, @tun_info[ :chunks ].shift )
@@ -928,16 +911,16 @@ module Girl
928
911
  caches = []
929
912
 
930
913
  until data.empty?
931
- _src_id, pack_size = data[ 0, 10 ].unpack( 'Q>n' )
932
- caches << [ _src_id, data[ 10, pack_size ] ]
933
- data = data[ ( 10 + pack_size )..-1 ]
914
+ _src_id, _pack_id, pack_size = data[ 0, 18 ].unpack( 'Q>Q>n' )
915
+ caches << [ _src_id, _pack_id, data[ 18, pack_size ] ]
916
+ data = data[ ( 18 + pack_size )..-1 ]
934
917
  end
935
918
 
936
919
  @tun_info[ :caches ] = caches
937
- src_id, data = caches.first
920
+ src_id, pack_id, data = caches.first
938
921
  from = :caches
939
922
  elsif @tun_info[ :wbuffs ].any?
940
- src_id, data = @tun_info[ :wbuffs ].first
923
+ src_id, pack_id, data = @tun_info[ :wbuffs ].first
941
924
  from = :wbuffs
942
925
  else
943
926
  @writes.delete( tun )
@@ -947,8 +930,6 @@ module Girl
947
930
  src_ext = @tun_info[ :src_exts ][ src_id ]
948
931
 
949
932
  if src_ext
950
- pack_id = src_ext[ :biggest_pack_id ] + 1
951
-
952
933
  if pack_id <= CONFUSE_UNTIL
953
934
  data = @custom.encode( data )
954
935
  # puts "debug1 encoded pack #{ pack_id }"
@@ -960,10 +941,14 @@ module Girl
960
941
  tun.sendmsg( data, 0, @tun_info[ :tund_addr ] )
961
942
  rescue IO::WaitWritable, Errno::EINTR
962
943
  return
944
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH => e
945
+ puts "#{ Time.new } #{ e.class }, close tun"
946
+ close_tun( tun )
947
+ return
963
948
  end
964
949
 
965
950
  # puts "debug2 written pack #{ pack_id }"
966
- src_ext[ :biggest_pack_id ] = pack_id
951
+ src_ext[ :relay_pack_id ] = pack_id
967
952
  src_ext[ :wmems ][ pack_id ] = data
968
953
  src_ext[ :send_ats ][ pack_id ] = now
969
954
  src_ext[ :last_continue_at ] = now
@@ -999,7 +984,9 @@ module Girl
999
984
  dst: nil, # :direct的场合,对应的dst
1000
985
  destination_domain: nil, # 目的地域名
1001
986
  destination_port: nil, # 目的地端口
1002
- rbuffs: [], # 非CONNECT,dst或者远端dst未准备好,暂存流量
987
+ biggest_pack_id: 0, # 最大包号码
988
+ is_connect: true, # 代理协议是http的场合,是否是CONNECT
989
+ rbuffs: [], # 非CONNECT,dst或者远端dst未准备好,暂存流量 [ pack_id, data ]
1003
990
  wbuff: '', # 写前
1004
991
  cache: '', # 块读出缓存
1005
992
  chunks: [], # 块队列,写前达到块大小时结一个块 filename
@@ -1096,7 +1083,10 @@ module Girl
1096
1083
  end
1097
1084
  end
1098
1085
 
1099
- src_info[ :rbuffs ] << data
1086
+ src_info[ :is_connect ] = false
1087
+ pack_id = src_info[ :biggest_pack_id ] + 1
1088
+ src_info[ :biggest_pack_id ] = pack_id
1089
+ src_info[ :rbuffs ] << [ pack_id, data ]
1100
1090
  end
1101
1091
 
1102
1092
  domain, port = domain_and_port.split( ':' )
@@ -1109,7 +1099,9 @@ module Girl
1109
1099
  resolve_domain( src, domain )
1110
1100
  when :checking
1111
1101
  # puts "debug1 add src rbuff while checking #{ data.inspect }"
1112
- src_info[ :rbuffs ] << data
1102
+ pack_id = src_info[ :biggest_pack_id ] + 1
1103
+ src_info[ :biggest_pack_id ] = pack_id
1104
+ src_info[ :rbuffs ] << [ pack_id, data ]
1113
1105
  when :negotiation
1114
1106
  # +----+-----+-------+------+----------+----------+
1115
1107
  # |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
@@ -1156,6 +1148,9 @@ module Girl
1156
1148
  return
1157
1149
  end
1158
1150
 
1151
+ pack_id = src_info[ :biggest_pack_id ] + 1
1152
+ src_info[ :biggest_pack_id ] = pack_id
1153
+
1159
1154
  if src_ext[ :dst_port ]
1160
1155
  if @tun.closed?
1161
1156
  # puts "debug1 tun closed, close src"
@@ -1163,14 +1158,14 @@ module Girl
1163
1158
  return
1164
1159
  end
1165
1160
 
1166
- if src_info[ :rbuffs ].any?
1161
+ unless src_info[ :is_connect ]
1167
1162
  data, _ = sub_http_request( data )
1168
1163
  end
1169
1164
 
1170
- add_tun_wbuff( src_id, data )
1165
+ add_tun_wbuff( src_id, pack_id, data )
1171
1166
  else
1172
1167
  # puts "debug1 remote dst not ready, save data to src rbuff"
1173
- src_info[ :rbuffs ] << data
1168
+ src_info[ :rbuffs ] << [ pack_id, data ]
1174
1169
  end
1175
1170
  when :direct
1176
1171
  dst = src_info[ :dst ]
@@ -1182,14 +1177,14 @@ module Girl
1182
1177
  return
1183
1178
  end
1184
1179
 
1185
- if src_info[ :rbuffs ].any?
1180
+ unless src_info[ :is_connect ]
1186
1181
  data, _ = sub_http_request( data )
1187
1182
  end
1188
1183
 
1189
1184
  add_dst_wbuff( dst, data )
1190
1185
  else
1191
1186
  # puts "debug1 dst not ready, save data to src rbuff"
1192
- src_info[ :rbuffs ] << data
1187
+ src_info[ :rbuffs ] << [ nil, data ]
1193
1188
  end
1194
1189
  end
1195
1190
  end
@@ -1275,18 +1270,14 @@ module Girl
1275
1270
  src_info = @src_infos[ src ]
1276
1271
 
1277
1272
  if src_info[ :proxy_proto ] == :http
1278
- datas = src_info[ :rbuffs ]
1279
-
1280
- if datas.empty?
1281
- # CONNECT
1273
+ if src_info[ :is_connect ]
1282
1274
  # puts "debug1 add src wbuff http ok"
1283
1275
  add_src_wbuff( src, HTTP_OK )
1284
1276
  else
1285
- # not CONNECT
1286
1277
  # puts "debug1 add src rbuffs to tun wbuffs"
1287
1278
 
1288
- datas.each do | _data |
1289
- add_tun_wbuff( src_id, _data )
1279
+ src_info[ :rbuffs ].each do | pack_id, _data |
1280
+ add_tun_wbuff( src_id, pack_id, _data )
1290
1281
  end
1291
1282
  end
1292
1283
  elsif src_info[ :proxy_proto ] == :socks5
@@ -1295,7 +1286,7 @@ module Girl
1295
1286
  when DEST_STATUS
1296
1287
  return if from_addr != @tun_info[ :tund_addr ]
1297
1288
 
1298
- dst_port, biggest_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
1289
+ dst_port, relay_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
1299
1290
 
1300
1291
  src_id = @tun_info[ :src_ids ][ dst_port ]
1301
1292
  return unless src_id
@@ -1305,22 +1296,10 @@ module Girl
1305
1296
 
1306
1297
  # puts "debug2 got dest status"
1307
1298
 
1308
- # 更新对面发到几
1309
- if biggest_dst_pack_id > src_ext[ :biggest_dst_pack_id ]
1310
- # puts "debug2 update biggest dst pack #{ biggest_dst_pack_id }"
1311
- src_ext[ :biggest_dst_pack_id ] = biggest_dst_pack_id
1312
-
1313
- # 接到对面状态,若对面已关闭,且最后一个包已经进写前,关闭src
1314
- if src_ext[ :is_dst_closed ] && ( biggest_dst_pack_id == src_ext[ :continue_dst_pack_id ] )
1315
- # puts "debug1 2-1. recv traffic/fin1/dst status -> dst closed and all traffic received ? -> close src after write"
1316
- set_is_closing( src_ext[ :src ] )
1317
- end
1318
- end
1319
-
1320
1299
  release_wmems( src_ext, continue_src_pack_id )
1321
1300
 
1322
1301
  # 发miss
1323
- if !src_ext[ :src ].closed? && ( src_ext[ :continue_dst_pack_id ] < src_ext[ :biggest_dst_pack_id ] )
1302
+ if !src_ext[ :src ].closed? && ( src_ext[ :continue_dst_pack_id ] < relay_dst_pack_id )
1324
1303
  ranges = []
1325
1304
  curr_pack_id = src_ext[ :continue_dst_pack_id ] + 1
1326
1305
 
@@ -1332,12 +1311,12 @@ module Girl
1332
1311
  curr_pack_id = pack_id + 1
1333
1312
  end
1334
1313
 
1335
- if curr_pack_id <= src_ext[ :biggest_dst_pack_id ]
1336
- ranges << [ curr_pack_id, src_ext[ :biggest_dst_pack_id ] ]
1314
+ if curr_pack_id <= relay_dst_pack_id
1315
+ ranges << [ curr_pack_id, relay_dst_pack_id ]
1337
1316
  end
1338
1317
 
1339
1318
  pack_count = 0
1340
- # puts "debug1 continue/biggest #{ src_ext[ :continue_dst_pack_id ] }/#{ src_ext[ :biggest_dst_pack_id ] } send MISS #{ ranges.size }"
1319
+ # puts "debug1 continue/relay #{ src_ext[ :continue_dst_pack_id ] }/#{ relay_dst_pack_id } send MISS #{ ranges.size }"
1341
1320
 
1342
1321
  ranges.each do | pack_id_begin, pack_id_end |
1343
1322
  if pack_count >= BREAK_SEND_MISS
@@ -1384,9 +1363,8 @@ module Girl
1384
1363
  src_ext[ :biggest_dst_pack_id ] = biggest_dst_pack_id
1385
1364
  release_wmems( src_ext, continue_src_pack_id )
1386
1365
 
1387
- # 接到对面已关闭,若最后一个包已经进写前,关闭src
1388
1366
  if ( biggest_dst_pack_id == src_ext[ :continue_dst_pack_id ] )
1389
- # puts "debug1 2-1. recv fin1 -> set dst closed -> all traffic received ? -> close src after write"
1367
+ # puts "debug1 2-1. tun recv fin1 -> all traffic received ? -> close src after write"
1390
1368
  set_is_closing( src_ext[ :src ] )
1391
1369
  end
1392
1370
  when FIN2
@@ -1397,7 +1375,7 @@ module Girl
1397
1375
  src_id = @tun_info[ :src_ids ][ dst_port ]
1398
1376
  return unless src_id
1399
1377
 
1400
- # puts "debug1 1-2. recv fin2 -> del src ext"
1378
+ # puts "debug1 1-2. tun recv fin2 -> del src ext"
1401
1379
  del_src_ext( src_id )
1402
1380
  when TUND_FIN
1403
1381
  return if from_addr != @tun_info[ :tund_addr ]
@@ -1443,7 +1421,7 @@ module Girl
1443
1421
 
1444
1422
  # 接到流量,若对面已关闭,且流量正好收全,关闭src
1445
1423
  if src_ext[ :is_dst_closed ] && ( pack_id == src_ext[ :biggest_dst_pack_id ] )
1446
- # puts "debug1 2-1. recv traffic/fin1/dst status -> dst closed and all traffic received ? -> close src after write"
1424
+ # puts "debug1 2-2. tun recv traffic -> dst closed and all traffic received ? -> close src after write"
1447
1425
  set_is_closing( src_ext[ :src ] )
1448
1426
  end
1449
1427
  else