girl 4.1.0 → 4.6.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.

@@ -1,12 +1,12 @@
1
- require 'girl/custom'
2
-
3
- module Girl
4
- class ProxydCustom
5
- include Custom
6
-
7
- def check( data, addrinfo )
8
- :success
9
- end
10
-
11
- end
12
- end
1
+ require 'girl/custom'
2
+
3
+ module Girl
4
+ class ProxydCustom
5
+ include Custom
6
+
7
+ def check( data, addrinfo )
8
+ :success
9
+ end
10
+
11
+ end
12
+ end
@@ -221,7 +221,7 @@ module Girl
221
221
  close_sock( btun )
222
222
  btun_info = @btun_infos.delete( btun )
223
223
  dst = btun_info[ :dst ]
224
-
224
+
225
225
  if dst then
226
226
  @paused_dsts.delete( dst )
227
227
  end
@@ -306,6 +306,7 @@ module Girl
306
306
  #
307
307
  def deal_with_destination_addr( ctl_addr, src_id, destination_addr, domain_port )
308
308
  dst = Socket.new( Addrinfo.new( destination_addr ).ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
309
+ dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
309
310
 
310
311
  begin
311
312
  dst.connect_nonblock( destination_addr )
@@ -324,6 +325,7 @@ module Girl
324
325
  ctl_addr: ctl_addr, # 对应ctl
325
326
  im: ctl_info[ :im ], # 标识
326
327
  domain_port: domain_port, # 目的地和端口
328
+ connected: false, # 是否已连接
327
329
  rbuff: '', # 对应的tun没准备好,暂存读到的流量
328
330
  atun: nil, # 对应的atun
329
331
  btun: nil, # 对应的btun
@@ -336,6 +338,7 @@ module Girl
336
338
  }
337
339
 
338
340
  add_read( dst, :dst )
341
+ add_write( dst )
339
342
 
340
343
  ctl_info[ :dst_ids ][ src_id ] = dst_id
341
344
  ctl_info[ :dsts ][ dst_id ] = dst
@@ -404,11 +407,17 @@ module Girl
404
407
  end
405
408
 
406
409
  @dst_infos.each do | dst, dst_info |
407
- last_recv_at = dst_info[ :last_recv_at ] || dst_info[ :created_at ]
408
- last_sent_at = dst_info[ :last_sent_at ] || dst_info[ :created_at ]
409
- expire_after = dst_info[ :btun ] ? EXPIRE_AFTER : EXPIRE_NEW
410
+ if dst_info[ :connected ] then
411
+ last_recv_at = dst_info[ :last_recv_at ] || dst_info[ :created_at ]
412
+ last_sent_at = dst_info[ :last_sent_at ] || dst_info[ :created_at ]
413
+ expire_after = EXPIRE_AFTER
414
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
415
+ else
416
+ expire_after = EXPIRE_CONNECTING
417
+ is_expire = ( now - dst_info[ :created_at ] >= expire_after )
418
+ end
410
419
 
411
- if ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after ) then
420
+ if is_expire then
412
421
  puts "p#{ Process.pid } #{ Time.new } expire dst #{ expire_after } #{ dst_info[ :domain_port ] }"
413
422
 
414
423
  unless @closing_dsts.include?( dst ) then
@@ -436,7 +445,7 @@ module Girl
436
445
  if btun && !btun.closed? then
437
446
  btun_info = @btun_infos[ btun ]
438
447
 
439
- if btun_info[ :wbuff ].size < RESUME_BELOW then
448
+ if btun_info[ :wbuff ].bytesize < RESUME_BELOW then
440
449
  puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain_port ] }"
441
450
  add_resume_dst( dst )
442
451
  end
@@ -450,7 +459,7 @@ module Girl
450
459
  if dst && !dst.closed? then
451
460
  dst_info = @dst_infos[ dst ]
452
461
 
453
- if dst_info[ :wbuff ].size < RESUME_BELOW then
462
+ if dst_info[ :wbuff ].bytesize < RESUME_BELOW then
454
463
  puts "p#{ Process.pid } #{ Time.new } resume atun #{ atun_info[ :domain_port ] }"
455
464
  add_resume_atun( atun )
456
465
  end
@@ -507,6 +516,7 @@ module Girl
507
516
  #
508
517
  def new_a_tund
509
518
  tund = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
519
+ tund.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
510
520
  tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
511
521
  tund.listen( 127 )
512
522
  tund
@@ -519,6 +529,14 @@ module Girl
519
529
  @dotw.write( '.' )
520
530
  end
521
531
 
532
+ ##
533
+ # pack a chunk
534
+ #
535
+ def pack_a_chunk( data )
536
+ data = @custom.encode( data )
537
+ "#{ [ data.bytesize ].pack( 'n' ) }#{ data }"
538
+ end
539
+
522
540
  ##
523
541
  # resolve domain
524
542
  #
@@ -564,6 +582,8 @@ module Girl
564
582
  # send ctlmsg
565
583
  #
566
584
  def send_ctlmsg( data, to_addr )
585
+ data = @custom.encode( data )
586
+
567
587
  begin
568
588
  @ctld.sendmsg( data, 0, to_addr )
569
589
  rescue Exception => e
@@ -599,7 +619,7 @@ module Girl
599
619
  # read dotr
600
620
  #
601
621
  def read_dotr( dotr )
602
- dotr.read_nonblock( 65535 )
622
+ dotr.read_nonblock( READ_SIZE )
603
623
 
604
624
  if @deleting_ctl_infos.any? then
605
625
  @deleting_ctl_infos.each { | ctl_addr | del_ctl_info( ctl_addr ) }
@@ -635,6 +655,7 @@ module Girl
635
655
  #
636
656
  def read_ctld( ctld )
637
657
  data, addrinfo, rflags, *controls = ctld.recvmsg
658
+ data = @custom.decode( data )
638
659
  ctl_num = data[ 0 ].unpack( 'C' ).first
639
660
  ctl_addr = addrinfo.to_sockaddr
640
661
  ctl_info = @ctl_infos[ ctl_addr ]
@@ -644,7 +665,7 @@ module Girl
644
665
  if ctl_info then
645
666
  atund_port, btund_port = ctl_info[ :atund_port ], ctl_info[ :btund_port ]
646
667
  else
647
- return if data.size <= 1
668
+ return if data.bytesize <= 1
648
669
  im = data[ 1..-1 ]
649
670
  result = @custom.check( im, addrinfo )
650
671
 
@@ -698,7 +719,7 @@ module Girl
698
719
  return
699
720
  end
700
721
 
701
- return if data.size <= 9
722
+ return if data.bytesize <= 9
702
723
  src_id = data[ 1, 8 ].unpack( 'Q>' ).first
703
724
  dst_id = ctl_info[ :dst_ids ][ src_id ]
704
725
 
@@ -761,7 +782,7 @@ module Girl
761
782
  btun = dst_info[ :btun ]
762
783
 
763
784
  begin
764
- data = dst.read_nonblock( 65535 )
785
+ data = dst.read_nonblock( CHUNK_SIZE )
765
786
  rescue IO::WaitReadable
766
787
  print 'r'
767
788
  return
@@ -777,12 +798,10 @@ module Girl
777
798
  end
778
799
 
779
800
  @traff_ins[ dst_info[ :im ] ] += data.bytesize
780
- # puts "debug read dst #{ data.bytesize }, encode"
781
- data = @custom.encode( data )
782
- data = "#{ [ data.bytesize ].pack( 'n' ) }#{ data }"
801
+ # puts "debug read dst #{ data.bytesize }"
783
802
 
784
803
  if btun then
785
- add_btun_wbuff( btun, data )
804
+ add_btun_wbuff( btun, pack_a_chunk( data ) )
786
805
  else
787
806
  # puts "debug add dst.rbuff #{ data.bytesize }"
788
807
  add_dst_rbuff( dst, data )
@@ -816,7 +835,8 @@ module Girl
816
835
  dst: nil, # 对应dst
817
836
  domain_port: nil, # dst的目的地和端口
818
837
  rbuff: '', # 暂存当前块没收全的流量
819
- wait_bytes: 0 # 还差多少字节收全当前块
838
+ wait_bytes: 0, # 还差多少字节收全当前块
839
+ lbuff: '' # 流量截断在长度前缀处
820
840
  }
821
841
 
822
842
  add_read( atun, :atun )
@@ -912,22 +932,44 @@ module Girl
912
932
  end
913
933
 
914
934
  until data.empty? do
915
- rbuff = atun_info[ :rbuff ]
916
935
  wait_bytes = atun_info[ :wait_bytes ]
917
936
 
918
937
  if wait_bytes > 0 then
919
938
  len = wait_bytes
920
939
  # puts "debug wait bytes #{ len }"
921
940
  else
922
- if data.bytesize <= 2 then
923
- # puts "debug unexpect data length #{ data.bytesize }"
924
- close_atun( atun )
925
- return
926
- end
941
+ lbuff = atun_info[ :lbuff ]
942
+
943
+ if lbuff.empty? then
944
+ # 长度缓存为空,从读到的流量里取长度
945
+ # 两个字节以下,记进长度缓存
946
+ if data.bytesize <= 2 then
947
+ # puts "debug set atun.lbuff #{ data.inspect }"
948
+ atun_info[ :lbuff ] = data
949
+ return
950
+ end
951
+
952
+ len = data[ 0, 2 ].unpack( 'n' ).first
953
+ data = data[ 2..-1 ]
954
+ elsif lbuff.bytesize == 1 then
955
+ # 长度缓存记有一个字节,补一个字节
956
+ lbuff = "#{ lbuff }#{ data[ 0 ] }"
927
957
 
928
- len = data[ 0, 2 ].unpack( 'n' ).first
929
- # puts "debug read len #{ len }"
930
- data = data[ 2..-1 ]
958
+ if data.bytesize == 1 then
959
+ # puts "debug add atun.lbuff a byte #{ data.inspect }"
960
+ atun_info[ :lbuff ] = lbuff
961
+ return
962
+ end
963
+
964
+ # 使用长度缓存
965
+ len = lbuff.unpack( 'n' ).first
966
+ atun_info[ :lbuff ].clear
967
+ data = data[ 1..-1 ]
968
+ else
969
+ # 使用长度缓存
970
+ len = lbuff.unpack( 'n' ).first
971
+ atun_info[ :lbuff ].clear
972
+ end
931
973
  end
932
974
 
933
975
  chunk = data[ 0, len ]
@@ -935,7 +977,7 @@ module Girl
935
977
 
936
978
  if chunk_size == len then
937
979
  # 取完整了
938
- chunk = @custom.decode( "#{ rbuff }#{ chunk }" )
980
+ chunk = @custom.decode( "#{ atun_info[ :rbuff ] }#{ chunk }" )
939
981
  # puts "debug decode and add dst.wbuff #{ chunk.bytesize }"
940
982
  add_dst_wbuff( dst, chunk )
941
983
  atun_info[ :rbuff ].clear
@@ -1009,8 +1051,17 @@ module Girl
1009
1051
  btun_info[ :domain_port ] = dst_info[ :domain_port ]
1010
1052
 
1011
1053
  unless dst_info[ :rbuff ].empty? then
1012
- # puts "debug move dst.rbuff to btun.wbuff"
1013
- add_btun_wbuff( btun, dst_info[ :rbuff ] )
1054
+ data2 = ''
1055
+
1056
+ until dst_info[ :rbuff ].empty? do
1057
+ _data = dst_info[ :rbuff ][ 0, CHUNK_SIZE ]
1058
+ data_size = _data.bytesize
1059
+ # puts "debug move dst.rbuff to btun.wbuff"
1060
+ data2 << pack_a_chunk( _data )
1061
+ dst_info[ :rbuff ] = dst_info[ :rbuff ][ data_size..-1 ]
1062
+ end
1063
+
1064
+ add_btun_wbuff( btun, data2 )
1014
1065
  end
1015
1066
 
1016
1067
  dst_info[ :btun ] = btun
@@ -1026,6 +1077,7 @@ module Girl
1026
1077
  end
1027
1078
 
1028
1079
  dst_info = @dst_infos[ dst ]
1080
+ dst_info[ :connected ] = true
1029
1081
  atun = dst_info[ :atun ]
1030
1082
  data = dst_info[ :wbuff ]
1031
1083
 
data/lib/girl/relay.rb CHANGED
@@ -3,8 +3,8 @@ require 'girl/concurrent_hash'
3
3
  require 'girl/head'
4
4
  require 'girl/proxy_custom'
5
5
  require 'girl/relay_worker'
6
- require 'girl/resolv_custom'
7
6
  require 'girl/version'
7
+ require 'ipaddr'
8
8
  require 'json'
9
9
  require 'socket'
10
10
 
@@ -13,7 +13,6 @@ module Girl
13
13
  @directs = directs
14
14
  @remotes = remotes
15
15
  @custom = Girl::ProxyCustom.new( im )
16
- @resolv_custom = Girl::ResolvCustom.new
17
16
  @reads = []
18
17
  @writes = []
19
18
  @closing_rsvs = []
@@ -24,7 +23,7 @@ module Girl
24
23
  @resume_srcs = []
25
24
  @resume_dsts = []
26
25
  @resume_btuns = []
27
- @pending_srcs = [] # 还没配到tund,暂存的src
26
+ @pending_srcs = [] # 还没得到atund和btund地址,暂存的src
28
27
  @roles = ConcurrentHash.new # sock => :dotr / :resolv / :rsv / :redir / :proxy / :src / :dst / :atun / :btun
29
28
  @rsv_infos = ConcurrentHash.new # rsv => {}
30
29
  @src_infos = ConcurrentHash.new # src => {}
@@ -445,9 +444,8 @@ module Girl
445
444
  return if src.closed?
446
445
  src_info = @src_infos[ src ]
447
446
 
448
- if ip_info.ipv4_loopback? \
449
- || ip_info.ipv6_loopback? \
450
- || ( ( @ip_address_list.any? { | addrinfo | addrinfo.ip_address == ip_info.ip_address } ) && ( src_info[ :destination_port ] == @redir_port ) ) then
447
+ if ( ( @ip_address_list.any? { | addrinfo | addrinfo.ip_address == ip_info.ip_address } ) && ( src_info[ :destination_port ] == @redir_port ) ) \
448
+ || ( ( ip_info.ip_address == @proxyd_host ) && ( src_info[ :destination_port ] == @proxyd_port ) ) then
451
449
  puts "p#{ Process.pid } #{ Time.new } ignore #{ ip_info.ip_address }:#{ src_info[ :destination_port ] }"
452
450
  add_closing_src( src )
453
451
  return
@@ -464,7 +462,6 @@ module Girl
464
462
  is_direct = @is_direct_caches[ ip_info.ip_address ]
465
463
  else
466
464
  is_direct = @directs.any? { | direct | direct.include?( ip_info.ip_address ) }
467
- # 判断直连耗时较长(树莓派 0.27秒),这里可能切去主线程,回来src可能已关闭
468
465
  puts "p#{ Process.pid } #{ Time.new } cache is direct #{ ip_info.ip_address } #{ is_direct }"
469
466
  @is_direct_caches[ ip_info.ip_address ] = is_direct
470
467
  end
@@ -473,7 +470,6 @@ module Girl
473
470
  # puts "debug #{ ip_info.inspect } hit directs"
474
471
  new_a_dst( src, ip_info )
475
472
  else
476
- # 走远端
477
473
  # puts "debug #{ ip_info.inspect } go tunnel"
478
474
  set_proxy_type_tunnel( src )
479
475
  end
@@ -524,8 +520,8 @@ module Girl
524
520
  if @ctl && !@ctl.closed? then
525
521
  last_recv_at = @ctl_info[ :last_recv_at ] || @ctl_info[ :created_at ]
526
522
 
527
- if now - last_recv_at >= EXPIRE_AFTER then
528
- puts "p#{ Process.pid } #{ Time.new } expire ctl"
523
+ if now - last_recv_at >= EXPIRE_CTL then
524
+ puts "p#{ Process.pid } #{ Time.new } expire ctl #{ EXPIRE_CTL }"
529
525
  @ctl_info[ :closing ] = true
530
526
  next_tick
531
527
  end
@@ -541,9 +537,24 @@ module Girl
541
537
  @src_infos.each do | src, src_info |
542
538
  last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
543
539
  last_sent_at = src_info[ :last_sent_at ] || src_info[ :created_at ]
544
- expire_after = ( src_info[ :dst ] || src_info[ :tun ] ) ? EXPIRE_AFTER : EXPIRE_NEW
545
540
 
546
- if ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after ) then
541
+ if src_info[ :dst ] then
542
+ if src_info[ :dst_connected ] then
543
+ expire_after = EXPIRE_AFTER
544
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
545
+ else
546
+ expire_after = EXPIRE_CONNECTING
547
+ is_expire = ( now - src_info[ :dst_created_at ] >= expire_after )
548
+ end
549
+ elsif src_info[ :atun ] then
550
+ expire_after = EXPIRE_AFTER
551
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
552
+ else
553
+ expire_after = EXPIRE_NEW
554
+ is_expire = ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after )
555
+ end
556
+
557
+ if is_expire then
547
558
  puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
548
559
  add_closing_src( src )
549
560
 
@@ -572,7 +583,7 @@ module Girl
572
583
  if !dst.closed? then
573
584
  dst_info = @dst_infos[ dst ]
574
585
 
575
- if dst_info[ :wbuff ].size < RESUME_BELOW then
586
+ if dst_info[ :wbuff ].bytesize < RESUME_BELOW then
576
587
  puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
577
588
  add_resume_src( src )
578
589
  end
@@ -583,7 +594,7 @@ module Girl
583
594
  if atun && !atun.closed? then
584
595
  atun_info = @atun_infos[ atun ]
585
596
 
586
- if atun_info[ :wbuff ].size < RESUME_BELOW then
597
+ if atun_info[ :wbuff ].bytesize < RESUME_BELOW then
587
598
  puts "p#{ Process.pid } #{ Time.new } resume tunnel src #{ src_info[ :destination_domain ] }"
588
599
  add_resume_src( src )
589
600
  end
@@ -598,7 +609,7 @@ module Girl
598
609
  if src && !src.closed? then
599
610
  src_info = @src_infos[ src ]
600
611
 
601
- if src_info[ :wbuff ].size < RESUME_BELOW then
612
+ if src_info[ :wbuff ].bytesize < RESUME_BELOW then
602
613
  puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain ] }"
603
614
  add_resume_dst( dst )
604
615
  end
@@ -612,7 +623,7 @@ module Girl
612
623
  if src && !src.closed? then
613
624
  src_info = @src_infos[ src ]
614
625
 
615
- if src_info[ :wbuff ].size < RESUME_BELOW then
626
+ if src_info[ :wbuff ].bytesize < RESUME_BELOW then
616
627
  puts "p#{ Process.pid } #{ Time.new } resume btun #{ btun_info[ :domain ] }"
617
628
  add_resume_btun( btun )
618
629
  end
@@ -656,14 +667,14 @@ module Girl
656
667
  domain = src_info[ :destination_domain ]
657
668
  destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
658
669
  dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
659
- dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
670
+ dst.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
660
671
 
661
672
  begin
662
673
  dst.connect_nonblock( destination_addr )
663
674
  rescue IO::WaitWritable
664
675
  # connect nonblock 必抛 wait writable
665
676
  rescue Exception => e
666
- puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }, close src"
677
+ puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ domain } #{ src_info[ :destination_port ] } #{ ip_info.ip_address } #{ e.class }"
667
678
  dst.close
668
679
  add_closing_src( src )
669
680
  return
@@ -678,15 +689,17 @@ module Girl
678
689
  }
679
690
 
680
691
  @dst_infos[ dst ] = dst_info
681
- add_read( dst, :dst )
682
692
  src_info[ :proxy_type ] = :direct
683
693
  src_info[ :dst ] = dst
694
+ src_info[ :dst_created_at ] = Time.new
684
695
 
685
696
  if src_info[ :rbuff ] then
686
697
  # puts "debug move src.rbuff to dst.wbuff"
687
698
  dst_info[ :wbuff ] << src_info[ :rbuff ]
688
- add_write( dst )
689
699
  end
700
+
701
+ add_read( dst, :dst )
702
+ add_write( dst )
690
703
  end
691
704
 
692
705
  ##
@@ -722,6 +735,7 @@ module Girl
722
735
  #
723
736
  def new_a_redir( redir_port )
724
737
  redir = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
738
+ redir.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
725
739
  redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
726
740
  redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
727
741
  redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
@@ -754,13 +768,13 @@ module Girl
754
768
  rsv.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
755
769
 
756
770
  if @qnames.any? { | qname | data.include?( qname ) } then
757
- data = @resolv_custom.encode( data )
771
+ data = @custom.encode( data )
758
772
  to_addr = @resolvd_addr
759
773
  else
760
774
  to_addr = @nameserver_addr
761
775
  end
762
776
 
763
- puts "p#{ Process.pid } #{ Time.new } new a rsv to #{ Addrinfo.new( to_addr ).inspect }"
777
+ # puts "debug new a rsv to #{ Addrinfo.new( to_addr ).inspect }"
764
778
 
765
779
  @rsv_infos[ rsv ] = {
766
780
  src_addr: src_addr,
@@ -774,6 +788,7 @@ module Girl
774
788
  # new tuns
775
789
  #
776
790
  def new_tuns( src_id, dst_id )
791
+ return if @ctl_info[ :atund_addr ].nil? || @ctl_info[ :btund_addr ].nil?
777
792
  src = @srcs[ src_id ]
778
793
  return if src.nil? || src.closed?
779
794
  src_info = @src_infos[ src ]
@@ -781,23 +796,25 @@ module Girl
781
796
 
782
797
  # puts "debug new atun and btun"
783
798
  atun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
799
+ atun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
784
800
 
785
801
  begin
786
802
  atun.connect_nonblock( @ctl_info[ :atund_addr ] )
787
803
  rescue IO::WaitWritable
788
804
  rescue Exception => e
789
- puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }, close atun"
805
+ puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }"
790
806
  atun.close
791
807
  return
792
808
  end
793
809
 
794
810
  btun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
811
+ btun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
795
812
 
796
813
  begin
797
814
  btun.connect_nonblock( @ctl_info[ :btund_addr ] )
798
815
  rescue IO::WaitWritable
799
816
  rescue Exception => e
800
- puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }, close btun"
817
+ puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }"
801
818
  btun.close
802
819
  return
803
820
  end
@@ -806,7 +823,7 @@ module Girl
806
823
  atun_wbuff = [ dst_id ].pack( 'n' )
807
824
 
808
825
  until src_info[ :rbuff ].empty? do
809
- data = src_info[ :rbuff ][ 0, 65535 ]
826
+ data = src_info[ :rbuff ][ 0, CHUNK_SIZE ]
810
827
  data_size = data.bytesize
811
828
  # puts "debug move src.rbuff #{ data_size } to atun.wbuff"
812
829
  atun_wbuff << pack_a_chunk( data )
@@ -827,7 +844,8 @@ module Girl
827
844
  domain: domain, # 目的地
828
845
  wbuff: btun_wbuff, # 写前
829
846
  rbuff: '', # 暂存当前块没收全的流量
830
- wait_bytes: 0 # 还差多少字节收全当前块
847
+ wait_bytes: 0, # 还差多少字节收全当前块
848
+ lbuff: '' # 流量截断在长度前缀处
831
849
  }
832
850
 
833
851
  src_info[ :dst_id ] = dst_id
@@ -860,6 +878,7 @@ module Girl
860
878
  #
861
879
  def send_ctlmsg( data )
862
880
  return if @ctl.nil? || @ctl.closed?
881
+ data = @custom.encode( data )
863
882
 
864
883
  begin
865
884
  @ctl.sendmsg( data, 0, @proxyd_addr )
@@ -888,9 +907,7 @@ module Girl
888
907
  def send_data( sock, to_addr, data )
889
908
  begin
890
909
  sock.sendmsg( data, 0, to_addr )
891
- rescue IO::WaitWritable, Errno::EINTR
892
- print 'w'
893
- rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
910
+ rescue Exception => e
894
911
  puts "p#{ Process.pid } #{ Time.new } sendmsg to #{ to_addr.ip_unpack.inspect } #{ e.class }"
895
912
  end
896
913
  end
@@ -933,30 +950,11 @@ module Girl
933
950
  add_write( src )
934
951
  end
935
952
 
936
- ##
937
- # sub http request
938
- #
939
- def sub_http_request( data )
940
- lines = data.split( "\r\n" )
941
-
942
- return [ data, nil ] if lines.empty?
943
-
944
- method, url, proto = lines.first.split( ' ' )
945
-
946
- if proto && url && proto[ 0, 4 ] == 'HTTP' && url[ 0, 7 ] == 'http://' then
947
- domain_port = url.split( '/' )[ 2 ]
948
- data = data.sub( "http://#{ domain_port }", '' )
949
- # puts "debug subed #{ data.inspect } #{ domain_port }"
950
- end
951
-
952
- [ data, domain_port ]
953
- end
954
-
955
953
  ##
956
954
  # read dotr
957
955
  #
958
956
  def read_dotr( dotr )
959
- dotr.read_nonblock( 65535 )
957
+ dotr.read_nonblock( READ_SIZE )
960
958
 
961
959
  if @ctl_info && @ctl_info[ :closing ] then
962
960
  send_ctlmsg( [ CTL_FIN ].pack( 'C' ) )
@@ -1018,7 +1016,7 @@ module Girl
1018
1016
  # puts "debug rsv recvmsg #{ addrinfo.ip_unpack.inspect } #{ data.inspect }"
1019
1017
 
1020
1018
  if addrinfo.to_sockaddr == @resolvd_addr then
1021
- data = @resolv_custom.decode( data )
1019
+ data = @custom.decode( data )
1022
1020
  end
1023
1021
 
1024
1022
  rsv_info = @rsv_infos[ rsv ]
@@ -1061,6 +1059,8 @@ module Girl
1061
1059
  destination_port: dest_port, # 目的地端口
1062
1060
  rbuff: '', # 读到的流量
1063
1061
  dst: nil, # :direct的场合,对应的dst
1062
+ dst_created_at: nil, # :direct的场合,对应的dst的创建时间
1063
+ dst_connected: false, # :direct的场合,对应的dst是否已连接
1064
1064
  ctl: nil, # :tunnel的场合,对应的ctl
1065
1065
  atun: nil, # :tunnel的场合,对应的atun
1066
1066
  btun: nil, # :tunnel的场合,对应的btun
@@ -1093,11 +1093,12 @@ module Girl
1093
1093
  return
1094
1094
  end
1095
1095
 
1096
+ data = @custom.decode( data )
1096
1097
  ctl_num = data[ 0 ].unpack( 'C' ).first
1097
1098
 
1098
1099
  case ctl_num
1099
1100
  when TUND_PORT then
1100
- return if @ctl_info[ :atund_addr ] || data.size != 5
1101
+ return if @ctl_info[ :atund_addr ] || data.bytesize != 5
1101
1102
  atund_port, btund_port = data[ 1, 4 ].unpack( 'nn' )
1102
1103
  puts "p#{ Process.pid } #{ Time.new } got tund port #{ atund_port } #{ btund_port }"
1103
1104
  @ctl_info[ :resends ].delete( [ HELLO ].pack( 'C' ) )
@@ -1111,14 +1112,14 @@ module Girl
1111
1112
  @pending_srcs.clear
1112
1113
  end
1113
1114
  when PAIRED then
1114
- return if @ctl_info[ :atund_addr ].nil? || @ctl_info[ :btund_addr ].nil? || data.size != 11
1115
+ return if data.bytesize != 11
1115
1116
  src_id, dst_id = data[ 1, 10 ].unpack( 'Q>n' )
1116
1117
  # puts "debug got paired #{ src_id } #{ dst_id }"
1117
1118
  @ctl_info[ :resends ].delete( [ A_NEW_SOURCE, src_id ].pack( 'CQ>' ) )
1118
1119
  @ctl_info[ :last_recv_at ] = Time.new
1119
1120
  new_tuns( src_id, dst_id )
1120
1121
  when UNKNOWN_CTL_ADDR then
1121
- puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr, close ctl"
1122
+ puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr"
1122
1123
  close_ctl( ctl )
1123
1124
  end
1124
1125
  end
@@ -1135,7 +1136,7 @@ module Girl
1135
1136
  src_info = @src_infos[ src ]
1136
1137
 
1137
1138
  begin
1138
- data = src.read_nonblock( 65535 )
1139
+ data = src.read_nonblock( CHUNK_SIZE )
1139
1140
  rescue IO::WaitReadable
1140
1141
  print 'r'
1141
1142
  return
@@ -1197,7 +1198,7 @@ module Girl
1197
1198
  src = dst_info[ :src ]
1198
1199
 
1199
1200
  begin
1200
- data = dst.read_nonblock( 65535 )
1201
+ data = dst.read_nonblock( CHUNK_SIZE )
1201
1202
  rescue IO::WaitReadable
1202
1203
  print 'r'
1203
1204
  return
@@ -1238,22 +1239,44 @@ module Girl
1238
1239
  end
1239
1240
 
1240
1241
  until data.empty? do
1241
- rbuff = btun_info[ :rbuff ]
1242
1242
  wait_bytes = btun_info[ :wait_bytes ]
1243
1243
 
1244
1244
  if wait_bytes > 0 then
1245
1245
  len = wait_bytes
1246
1246
  # puts "debug wait bytes #{ len }"
1247
1247
  else
1248
- if data.bytesize <= 2 then
1249
- # puts "debug unexpect data length #{ data.bytesize }"
1250
- close_btun( btun )
1251
- return
1252
- end
1248
+ lbuff = btun_info[ :lbuff ]
1249
+
1250
+ if lbuff.empty? then
1251
+ # 长度缓存为空,从读到的流量里取长度
1252
+ # 两个字节以下,记进长度缓存
1253
+ if data.bytesize <= 2 then
1254
+ # puts "debug set btun.lbuff #{ data.inspect }"
1255
+ btun_info[ :lbuff ] = data
1256
+ return
1257
+ end
1253
1258
 
1254
- len = data[ 0, 2 ].unpack( 'n' ).first
1255
- # puts "debug read len #{ len }"
1256
- data = data[ 2..-1 ]
1259
+ len = data[ 0, 2 ].unpack( 'n' ).first
1260
+ data = data[ 2..-1 ]
1261
+ elsif lbuff.bytesize == 1 then
1262
+ # 长度缓存记有一个字节,补一个字节
1263
+ lbuff = "#{ lbuff }#{ data[ 0 ] }"
1264
+
1265
+ if data.bytesize == 1 then
1266
+ # puts "debug add btun.lbuff a byte #{ data.inspect }"
1267
+ btun_info[ :lbuff ] = lbuff
1268
+ return
1269
+ end
1270
+
1271
+ # 使用长度缓存
1272
+ len = lbuff.unpack( 'n' ).first
1273
+ btun_info[ :lbuff ].clear
1274
+ data = data[ 1..-1 ]
1275
+ else
1276
+ # 使用长度缓存
1277
+ len = lbuff.unpack( 'n' ).first
1278
+ btun_info[ :lbuff ].clear
1279
+ end
1257
1280
  end
1258
1281
 
1259
1282
  chunk = data[ 0, len ]
@@ -1261,7 +1284,7 @@ module Girl
1261
1284
 
1262
1285
  if chunk_size == len then
1263
1286
  # 取完整了
1264
- chunk = @custom.decode( "#{ rbuff }#{ chunk }" )
1287
+ chunk = @custom.decode( "#{ btun_info[ :rbuff ] }#{ chunk }" )
1265
1288
  # puts "debug read btun decoded #{ chunk.bytesize }"
1266
1289
  add_src_wbuff( src, chunk )
1267
1290
  btun_info[ :rbuff ] = ''
@@ -1340,6 +1363,12 @@ module Girl
1340
1363
 
1341
1364
  dst_info = @dst_infos[ dst ]
1342
1365
  src = dst_info[ :src ]
1366
+ src_info = @src_infos[ src ]
1367
+
1368
+ unless src.closed? then
1369
+ src_info[ :dst_connected ] = true
1370
+ end
1371
+
1343
1372
  data = dst_info[ :wbuff ]
1344
1373
 
1345
1374
  # 写前为空,处理关闭写
@@ -1370,7 +1399,6 @@ module Girl
1370
1399
  dst_info[ :wbuff ] = data
1371
1400
 
1372
1401
  unless src.closed? then
1373
- src_info = @src_infos[ src ]
1374
1402
  src_info[ :last_sent_at ] = Time.new
1375
1403
  end
1376
1404
  end