girl 0.69.0 → 0.70.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.

@@ -9,15 +9,6 @@ require 'socket'
9
9
  ##
10
10
  # Girl::Proxyd - 代理服务,远端。
11
11
  #
12
- # close logic
13
- # ===========
14
- #
15
- # 1-1. after close dst -> src closed ? no -> send fin1
16
- # 1-2. recv fin2 -> del dst ext
17
- #
18
- # 2-1. recv traffic/fin1/src status -> src closed and all traffic received ? -> close dst after write
19
- # 2-2. after close dst -> src closed ? yes -> del dst ext -> send fin2
20
- #
21
12
  module Girl
22
13
  class Proxyd
23
14
 
@@ -160,7 +160,7 @@ module Girl
160
160
 
161
161
  tund_info[ :dst_exts ].each do | dst_local_port, dst_ext |
162
162
  if now - dst_ext[ :last_continue_at ] < SEND_STATUS_UNTIL
163
- data = [ 0, DEST_STATUS, dst_local_port, dst_ext[ :biggest_pack_id ], dst_ext[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
163
+ data = [ 0, DEST_STATUS, dst_local_port, dst_ext[ :relay_pack_id ], dst_ext[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
164
164
  add_tund_ctlmsg( tund, data )
165
165
  need_trigger = true
166
166
  end
@@ -171,11 +171,6 @@ module Girl
171
171
  puts "p#{ Process.pid } #{ Time.new } resume tund"
172
172
  tund_info[ :paused ] = false
173
173
  add_write( tund )
174
-
175
- tund_info[ :dst_exts ].each do | _, dst_ext |
176
- add_write( dst_ext[ :dst ] )
177
- end
178
-
179
174
  need_trigger = true
180
175
  end
181
176
  end
@@ -253,6 +248,7 @@ module Girl
253
248
  @dst_infos[ dst ] = {
254
249
  local_port: local_port, # 本地端口
255
250
  tund: tund, # 对应tund
251
+ biggest_pack_id: 0, # 最大包号码
256
252
  wbuff: '', # 写前
257
253
  cache: '', # 块读出缓存
258
254
  chunks: [], # 块队列,写前达到块大小时结一个块 filename
@@ -270,11 +266,11 @@ module Girl
270
266
  src_id: src_id, # 近端src id
271
267
  wmems: {}, # 写后 pack_id => data
272
268
  send_ats: {}, # 上一次发出时间 pack_id => send_at
273
- biggest_pack_id: 0, # 发到几
269
+ relay_pack_id: 0, # 转发到几
274
270
  continue_src_pack_id: 0, # 收到几
275
271
  pieces: {}, # 跳号包 src_pack_id => data
276
- is_src_closed: false, # 对面是否已关闭
277
- biggest_src_pack_id: 0, # 对面发到几
272
+ is_src_closed: false, # src是否已关闭
273
+ biggest_src_pack_id: 0, # src最大包号码
278
274
  completed_pack_id: 0, # 完成到几(对面收到几)
279
275
  last_continue_at: Time.new # 创建,或者上一次收到连续流量,或者发出新包的时间
280
276
  }
@@ -320,18 +316,18 @@ module Girl
320
316
  ##
321
317
  # add tund wbuff
322
318
  #
323
- def add_tund_wbuff( tund, dst_local_port, data )
319
+ def add_tund_wbuff( tund, dst_local_port, pack_id, data )
324
320
  tund_info = @tund_infos[ tund ]
325
- tund_info[ :wbuffs ] << [ dst_local_port, data ]
321
+ tund_info[ :wbuffs ] << [ dst_local_port, pack_id, data ]
326
322
 
327
323
  if tund_info[ :wbuffs ].size >= WBUFFS_LIMIT
328
324
  spring = tund_info[ :chunks ].size > 0 ? ( tund_info[ :spring ] + 1 ) : 0
329
325
  filename = "#{ Process.pid }-#{ tund_info[ :port ] }.#{ spring }"
330
326
  chunk_path = File.join( @tund_chunk_dir, filename )
331
- wbuffs = tund_info[ :wbuffs ].map{ | _dst_local_port, _data | [ [ _dst_local_port, _data.bytesize ].pack( 'nn' ), _data ].join }
327
+ datas = tund_info[ :wbuffs ].map{ | _dst_local_port, _pack_id, _data | [ [ _dst_local_port, _pack_id, _data.bytesize ].pack( 'nQ>n' ), _data ].join }
332
328
 
333
329
  begin
334
- IO.binwrite( chunk_path, wbuffs.join )
330
+ IO.binwrite( chunk_path, datas.join )
335
331
  rescue Errno::ENOSPC => e
336
332
  puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close tund"
337
333
  set_is_closing( tund )
@@ -440,13 +436,13 @@ module Girl
440
436
  return unless dst_ext
441
437
 
442
438
  if dst_ext[ :is_src_closed ]
443
- # puts "debug1 2-2. after close dst -> src closed ? yes -> del dst ext -> send fin2"
439
+ # puts "debug1 4-3. after close dst -> src closed ? yes -> del dst ext -> send fin2"
444
440
  del_dst_ext( tund, local_port )
445
441
  data = [ 0, FIN2, local_port ].pack( 'Q>Cn' )
446
442
  add_tund_ctlmsg( tund, data )
447
443
  else
448
- # puts "debug1 1-1. after close dst -> src closed ? no -> send fin1"
449
- data = [ 0, FIN1, local_port, dst_ext[ :biggest_pack_id ], dst_ext[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
444
+ # puts "debug1 3-1. after close dst -> src closed ? no -> send fin1"
445
+ data = [ 0, FIN1, local_port, dst_info[ :biggest_pack_id ], dst_ext[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
450
446
  add_tund_ctlmsg( tund, data )
451
447
  end
452
448
  end
@@ -565,19 +561,7 @@ module Girl
565
561
 
566
562
  if data.empty?
567
563
  if dst_info[ :is_closing ]
568
- if dst_info[ :tund ].closed?
569
- close_dst( dst )
570
- else
571
- tund_info = @tund_infos[ dst_info[ :tund ] ]
572
-
573
- if tund_info[ :paused ]
574
- @writes.delete( dst )
575
- elsif !@writes.include?( dst_info[ :tund ] )
576
- # 转发光了,正式关闭
577
- # puts "debug2 close dst after tund empty"
578
- close_dst( dst )
579
- end
580
- end
564
+ close_dst( dst )
581
565
  else
582
566
  @writes.delete( dst )
583
567
  end
@@ -658,7 +642,7 @@ module Girl
658
642
 
659
643
  # 取写前
660
644
  if tund_info[ :caches ].any?
661
- dst_local_port, data = tund_info[ :caches ].first
645
+ dst_local_port, pack_id, data = tund_info[ :caches ].first
662
646
  from = :caches
663
647
  elsif tund_info[ :chunks ].any?
664
648
  path = File.join( @tund_chunk_dir, tund_info[ :chunks ].shift )
@@ -675,16 +659,16 @@ module Girl
675
659
  caches = []
676
660
 
677
661
  until data.empty?
678
- _dst_local_port, pack_size = data[ 0, 4 ].unpack( 'nn' )
679
- caches << [ _dst_local_port, data[ 4, pack_size ] ]
680
- data = data[ ( 4 + pack_size )..-1 ]
662
+ _dst_local_port, _pack_id, pack_size = data[ 0, 12 ].unpack( 'nQ>n' )
663
+ caches << [ _dst_local_port, _pack_id, data[ 12, pack_size ] ]
664
+ data = data[ ( 12 + pack_size )..-1 ]
681
665
  end
682
666
 
683
667
  tund_info[ :caches ] = caches
684
- dst_local_port, data = caches.first
668
+ dst_local_port, pack_id, data = caches.first
685
669
  from = :caches
686
670
  elsif tund_info[ :wbuffs ].any?
687
- dst_local_port, data = tund_info[ :wbuffs ].first
671
+ dst_local_port, pack_id, data = tund_info[ :wbuffs ].first
688
672
  from = :wbuffs
689
673
  else
690
674
  @writes.delete( tund )
@@ -694,8 +678,6 @@ module Girl
694
678
  dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
695
679
 
696
680
  if dst_ext
697
- pack_id = dst_ext[ :biggest_pack_id ] + 1
698
-
699
681
  if pack_id <= CONFUSE_UNTIL
700
682
  data = @custom.encode( data )
701
683
  # puts "debug1 encoded pack #{ pack_id }"
@@ -711,7 +693,7 @@ module Girl
711
693
 
712
694
  # puts "debug2 written pack #{ pack_id }"
713
695
  now = Time.new
714
- dst_ext[ :biggest_pack_id ] = pack_id
696
+ dst_ext[ :relay_pack_id ] = pack_id
715
697
  dst_ext[ :wmems ][ pack_id ] = data
716
698
  dst_ext[ :send_ats ][ pack_id ] = now
717
699
  dst_ext[ :last_continue_at ] = now
@@ -752,15 +734,15 @@ module Girl
752
734
  @tund_infos[ tund ] = {
753
735
  port: port, # 端口
754
736
  ctlmsgs: [], # data
755
- wbuffs: [], # 写前缓存 [ src_dst_addr, data ]
756
- caches: [], # 块读出缓存 [ src_dst_addr, data ]
737
+ wbuffs: [], # 写前缓存 [ dst_local_port, pack_id, data ]
738
+ caches: [], # 块读出缓存 [ dst_local_port, pack_id, data ]
757
739
  chunks: [], # 块队列 filename
758
740
  spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
759
741
  tun_addr: from_addr, # tun地址
760
- dst_exts: {}, # dst额外信息 dst_addr => {}
742
+ dst_exts: {}, # dst额外信息 dst_local_port => {}
761
743
  dst_local_ports: {}, # src_id => dst_local_port
762
744
  paused: false, # 是否暂停写
763
- resendings: [], # 重传队列 [ dst_addr, pack_id ]
745
+ resendings: [], # 重传队列 [ dst_local_port, pack_id ]
764
746
  created_at: Time.new, # 创建时间
765
747
  last_recv_at: nil, # 上一次收到流量的时间,过期关闭
766
748
  is_closing: false # 是否准备关闭
@@ -798,7 +780,9 @@ module Girl
798
780
  return
799
781
  end
800
782
 
801
- add_tund_wbuff( tund, dst_info[ :local_port ], data )
783
+ pack_id = dst_info[ :biggest_pack_id ] + 1
784
+ dst_info[ :biggest_pack_id ] = pack_id
785
+ add_tund_wbuff( tund, dst_info[ :local_port ], pack_id, data )
802
786
  end
803
787
 
804
788
  ##
@@ -851,7 +835,7 @@ module Girl
851
835
  destination_domain_port = @custom.decode( data )
852
836
  resolve_domain( tund, src_id, destination_domain_port )
853
837
  when SOURCE_STATUS
854
- src_id, biggest_src_pack_id, continue_dst_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
838
+ src_id, relay_src_pack_id, continue_dst_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
855
839
 
856
840
  dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
857
841
  return unless dst_local_port
@@ -861,22 +845,10 @@ module Girl
861
845
 
862
846
  # puts "debug2 got source status"
863
847
 
864
- # 更新对面发到几
865
- if biggest_src_pack_id > dst_ext[ :biggest_src_pack_id ]
866
- # puts "debug2 update biggest src pack #{ biggest_src_pack_id }"
867
- dst_ext[ :biggest_src_pack_id ] = biggest_src_pack_id
868
-
869
- # 接到对面状态,若对面已关闭,且最后一个包已经进写前,关闭dst
870
- if dst_ext[ :is_src_closed ] && ( biggest_src_pack_id == dst_ext[ :continue_src_pack_id ] )
871
- # puts "debug1 2-1. recv traffic/fin1/src status -> src closed and all traffic received ? -> close dst after write"
872
- set_is_closing( dst_ext[ :dst ] )
873
- end
874
- end
875
-
876
848
  release_wmems( dst_ext, continue_dst_pack_id )
877
849
 
878
850
  # 发miss
879
- if !dst_ext[ :dst ].closed? && ( dst_ext[ :continue_src_pack_id ] < dst_ext[ :biggest_src_pack_id ] )
851
+ if !dst_ext[ :dst ].closed? && ( dst_ext[ :continue_src_pack_id ] < relay_src_pack_id )
880
852
  ranges = []
881
853
  curr_pack_id = dst_ext[ :continue_src_pack_id ] + 1
882
854
 
@@ -888,12 +860,12 @@ module Girl
888
860
  curr_pack_id = pack_id + 1
889
861
  end
890
862
 
891
- if curr_pack_id <= dst_ext[ :biggest_src_pack_id ]
892
- ranges << [ curr_pack_id, dst_ext[ :biggest_src_pack_id ] ]
863
+ if curr_pack_id <= relay_src_pack_id
864
+ ranges << [ curr_pack_id, relay_src_pack_id ]
893
865
  end
894
866
 
895
867
  pack_count = 0
896
- # puts "debug1 continue/biggest #{ dst_ext[ :continue_src_pack_id ] }/#{ dst_ext[ :biggest_src_pack_id ] } send MISS #{ ranges.size }"
868
+ # puts "debug1 continue/relay #{ dst_ext[ :continue_src_pack_id ] }/#{ relay_src_pack_id } send MISS #{ ranges.size }"
897
869
 
898
870
  ranges.each do | pack_id_begin, pack_id_end |
899
871
  if pack_count >= BREAK_SEND_MISS
@@ -938,7 +910,7 @@ module Girl
938
910
 
939
911
  # 接到对面已关闭,若最后一个包已经进写前,关闭dst
940
912
  if biggest_src_pack_id == dst_ext[ :continue_src_pack_id ]
941
- # puts "debug1 2-1. recv traffic/fin1/src status -> src closed and all traffic received ? -> close dst after write"
913
+ # puts "debug1 4-1. tund recv fin1 -> all traffic received ? -> close dst after write"
942
914
  set_is_closing( dst_ext[ :dst ] )
943
915
  end
944
916
  when FIN2
@@ -947,7 +919,7 @@ module Girl
947
919
  dst_local_port = tund_info[ :dst_local_ports ][ src_id ]
948
920
  return unless dst_local_port
949
921
 
950
- # puts "debug1 1-2. recv fin2 -> del dst ext"
922
+ # puts "debug1 3-2. tund recv fin2 -> del dst ext"
951
923
  del_dst_ext( tund, dst_local_port )
952
924
  when TUN_FIN
953
925
  puts "p#{ Process.pid } #{ Time.new } recv tun fin"
@@ -989,7 +961,7 @@ module Girl
989
961
 
990
962
  # 接到流量,若对面已关闭,且流量正好收全,关闭dst
991
963
  if dst_ext[ :is_src_closed ] && ( pack_id == dst_ext[ :biggest_src_pack_id ] )
992
- # puts "debug1 2-1. recv traffic/fin1/src status -> src closed and all traffic received ? -> close dst after write"
964
+ # puts "debug1 4-2. tund recv traffic -> src closed and all traffic received ? -> close dst after write"
993
965
  set_is_closing( dst_ext[ :dst ] )
994
966
  return
995
967
  end
@@ -1,3 +1,3 @@
1
1
  module Girl
2
- VERSION = '0.69.0'.freeze
2
+ VERSION = '0.70.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: girl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.69.0
4
+ version: 0.70.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - takafan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-28 00:00:00.000000000 Z
11
+ date: 2020-06-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: while internet is evil, here's a girl.
14
14
  email:
@@ -21,17 +21,12 @@ files:
21
21
  - lib/girl.rb
22
22
  - lib/girl/custom.rb
23
23
  - lib/girl/head.rb
24
- - lib/girl/hex.rb
25
24
  - lib/girl/proxy.rb
26
25
  - lib/girl/proxy_custom.rb
27
26
  - lib/girl/proxy_worker.rb
28
27
  - lib/girl/proxyd.rb
29
28
  - lib/girl/proxyd_custom.rb
30
29
  - lib/girl/proxyd_worker.rb
31
- - lib/girl/resolv.rb
32
- - lib/girl/resolvd.rb
33
- - lib/girl/tun.rb
34
- - lib/girl/tund.rb
35
30
  - lib/girl/udp.rb
36
31
  - lib/girl/udpd.rb
37
32
  - lib/girl/version.rb
@@ -1,24 +0,0 @@
1
- module Girl
2
- class Hex
3
- def hello
4
- :hello
5
- end
6
-
7
- def check( data, addrinfo )
8
- :success
9
- end
10
-
11
- def gen_random_num
12
- rand( ( 2 ** 64 ) - 1 ) + 1
13
- end
14
-
15
- def encode( data )
16
- # overwrite me, you'll be free
17
- data
18
- end
19
-
20
- def decode( data )
21
- data
22
- end
23
- end
24
- end
@@ -1,200 +0,0 @@
1
- require 'girl/hex'
2
- require 'girl/version'
3
- require 'socket'
4
-
5
- ##
6
- # Girl::Resolv - dns查询得到正确的ip,近端。
7
- #
8
- # usage
9
- # =====
10
- #
11
- # Girl::Resolvd.new( 7070 ).looping # 远端
12
- #
13
- # Girl::Resolv.new( 1717, [ '114.114.114.114' ], 'your.server.ip', 7070, [ 'google.com' ] ).looping # 近端
14
- #
15
- # dig google.com @127.0.0.1 -p1717
16
- #
17
- module Girl
18
- class Resolv
19
-
20
- def initialize( port = 1717, nameservers = [], resolvd_host = nil, resolvd_port = nil, custom_domains = [] )
21
- @hex = Girl::Hex.new
22
- @mutex = Mutex.new
23
- @reads = []
24
- @writes = []
25
- @roles = {} # sock => :ctlr / :redir / :resolv / :pub
26
- @infos = {} # redir => {}
27
- @socks = {} # sock => sock_id
28
- @sock_ids = {} # sock_id => sock
29
-
30
- redir = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
31
- redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
32
- redir.bind( Socket.sockaddr_in( port, '0.0.0.0' ) )
33
- puts "redir bound on #{ port } #{ Time.new }"
34
-
35
- nameservers = nameservers.select{ | ns | Addrinfo.udp( ns, 53 ).ipv4? }
36
-
37
- if nameservers.empty?
38
- nameservers = %w[ 114.114.114.114 114.114.115.115 ]
39
- end
40
-
41
- redir_info = {
42
- src_addrs: {}, # src_addr => resolv_or_pub
43
- socks: {}, # resolv_or_pub => src_addr
44
- last_recv_ats: {}, # resolv_or_pub => now
45
- pubd_addrs: nameservers.map{ | ns | Socket.sockaddr_in( 53, ns ) },
46
- resolvd_addr: ( resolvd_host && resolvd_port ) ? Socket.sockaddr_in( resolvd_port, resolvd_host ) : nil,
47
- custom_qnames: custom_domains.map{ | dom | dom.split( '.' ).map{ | sub | [ sub.size ].pack( 'C' ) + sub }.join }
48
- }
49
-
50
- @redir = redir
51
- @redir_info = redir_info
52
- @roles[ redir ] = :redir
53
- @infos[ redir ] = redir_info
54
- @reads << redir
55
-
56
- ctlr, ctlw = IO.pipe
57
- @ctlw = ctlw
58
- @roles[ ctlr ] = :ctlr
59
- @reads << ctlr
60
- end
61
-
62
- def looping
63
- loop_expire
64
-
65
- loop do
66
- rs, ws = IO.select( @reads, @writes )
67
-
68
- @mutex.synchronize do
69
- rs.each do | sock |
70
- case @roles[ sock ]
71
- when :ctlr
72
- read_ctlr( sock )
73
- when :redir
74
- read_redir( sock )
75
- when :resolv, :pub
76
- read_sock( sock )
77
- end
78
- end
79
-
80
- ws.each do | sock |
81
- close_sock( sock )
82
- end
83
- end
84
- end
85
- end
86
-
87
- def quit!
88
- exit
89
- end
90
-
91
- private
92
-
93
- def read_ctlr( ctlr )
94
- sock_id = ctlr.read( 8 ).unpack( 'Q>' ).first
95
- sock = @sock_ids[ sock_id ]
96
-
97
- if sock
98
- # puts "debug expire #{ @roles[ sock ] } #{ sock_id } #{ Time.new }"
99
-
100
- unless @writes.include?( sock )
101
- @writes << sock
102
- end
103
- end
104
- end
105
-
106
- def read_redir( redir )
107
- # https://tools.ietf.org/html/rfc1035#page-26
108
- data, addrinfo, rflags, *controls = redir.recvmsg
109
- return if data.size <= 12
110
-
111
- id = data[ 0, 2 ]
112
- qname_len = data[ 12..-1 ].index( [ 0 ].pack( 'C' ) )
113
- return unless qname_len
114
-
115
- now = Time.new
116
- info = @infos[ redir ]
117
- src_addr = addrinfo.to_sockaddr
118
- sock = info[ :src_addrs ][ src_addr ]
119
-
120
- unless sock
121
- sock = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
122
- sock.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
123
- sock.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
124
-
125
- sock_id = @hex.gen_random_num
126
- @socks[ sock ] = sock_id
127
- @sock_ids[ sock_id ] = sock
128
- qname = data[ 12, qname_len ]
129
-
130
- if info[ :resolvd_addr ] && ( info[ :custom_qnames ].any? { | custom | qname.include?( custom ) } )
131
- @roles[ sock ] = :resolv
132
- else
133
- @roles[ sock ] = :pub
134
- end
135
-
136
- # puts "debug a new #{ @roles[ sock ] } bound on #{ sock.local_address.ip_unpack.last } #{ Time.new }"
137
-
138
- @reads << sock
139
- info[ :src_addrs ][ src_addr ] = sock
140
- info[ :socks ][ sock ] = src_addr
141
- info[ :last_recv_ats ][ sock ] = now
142
- end
143
-
144
- if @roles[ sock ] == :resolv
145
- data = @hex.encode( data )
146
- sock.sendmsg( data, 0, info[ :resolvd_addr ] )
147
- else
148
- info[ :pubd_addrs ].each { | pubd_addr | sock.sendmsg( data, 0, pubd_addr ) }
149
- end
150
- end
151
-
152
- def read_sock( sock )
153
- data, addrinfo, rflags, *controls = sock.recvmsg
154
- return if data.size <= 12
155
-
156
- if @roles[ sock ] == :resolv
157
- data = @hex.decode( data )
158
- end
159
-
160
- src_addr = @redir_info[ :socks ][ sock ]
161
- return unless src_addr
162
-
163
- @redir_info[ :last_recv_ats ][ sock ] = Time.new
164
- @redir.sendmsg( data, 0, src_addr )
165
- end
166
-
167
- def close_sock( sock )
168
- sock.close
169
- @reads.delete( sock )
170
- @writes.delete( sock )
171
- @roles.delete( sock )
172
- sock_id = @socks.delete( sock )
173
- @sock_ids.delete( sock_id )
174
- @redir_info[ :last_recv_ats ].delete( sock )
175
- src_addr = @redir_info[ :socks ].delete( sock )
176
- @redir_info[ :src_addrs ].delete( src_addr )
177
- end
178
-
179
- def loop_expire
180
- Thread.new do
181
- loop do
182
- sleep 60
183
-
184
- @mutex.synchronize do
185
- now = Time.new
186
- socks = @redir_info[ :socks ].keys
187
-
188
- socks.each do | sock |
189
- if now - @redir_info[ :last_recv_ats ][ sock ] > 5
190
- sock_id = @socks[ sock ]
191
- @ctlw.write( [ sock_id ].pack( 'Q>' ) )
192
- end
193
- end
194
- end
195
- end
196
- end
197
- end
198
-
199
- end
200
- end