girl 3.8.0 → 4.3.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: 5199f1adef8e1a8ec53a5b72bfce597c65abc6dee357e7004c1628ebbead85bc
4
- data.tar.gz: 5541fcfa8dd95bc60723ad6deaa98cec54224d407ad4fa04b085638136bd5b5c
3
+ metadata.gz: 43a48060a5cd6624864bceaa00824b736918f484b5a9342f67a7e885b401b276
4
+ data.tar.gz: f08b961719f618da8833746996c9bb66698a35e1d43526e63dd2792df2ed53da
5
5
  SHA512:
6
- metadata.gz: ecdb7c484ff08eb6f240656ff440f4640f201145f152dd61fca9a2aa85da271e1efb2db39e8b4ff57f9418d4e8936838f968e3c5ea0553140e694af444ac0392
7
- data.tar.gz: 2f5a56d688433e4b4a6fb60e0c74ac93c8d5e3c3c8f88c1fc69e3cfa9bee269f0463d029618b95c92fdf541977997b8860b94e06fca0c3d56a38172f288c44d7
6
+ metadata.gz: aa1c6709b604a13c80b9b4c66f09ae80f5ceb7714c8d8f3f0d9ee7cd906f1179399e8f75f31e8e8763bef0eb0ea62f4ddc46b646585833d75a4fdc07fc84c0f6
7
+ data.tar.gz: 5443ef6598cc196a27dcf50ec0e0f8d39cf65cc01a268092c0f2b9db2d1add65b1ee33eba8bdce17bd1be8b3e256fcc37bf731aecd4a3bee62d35eb198074934
data/girl.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  girl.gemspec
19
19
  lib/girl.rb
20
20
  lib/girl/concurrent_hash.rb
21
- lib/girl/custom_dns_query.rb
21
+ lib/girl/custom.rb
22
22
  lib/girl/head.rb
23
23
  lib/girl/proxy_custom.rb
24
24
  lib/girl/proxy_worker.rb
@@ -19,4 +19,8 @@ class ConcurrentHash < Hash
19
19
  def each( *args )
20
20
  @mutex.synchronize { super }
21
21
  end
22
+
23
+ def clear( *args )
24
+ @mutex.synchronize { super }
25
+ end
22
26
  end
@@ -1,5 +1,5 @@
1
1
  module Girl
2
- module CustomDnsQuery
2
+ module Custom
3
3
  def encode( data )
4
4
  data.reverse
5
5
  end
data/lib/girl/head.rb CHANGED
@@ -1,14 +1,17 @@
1
1
  module Girl
2
- READ_SIZE = 1024 * 1024 # 一次读多少
2
+ READ_SIZE = 1024 * 1024 # atun, btun一次读多少
3
3
  WBUFF_LIMIT = 50 * 1024 * 1024 # 写前上限,超过上限暂停读
4
4
  RESUME_BELOW = WBUFF_LIMIT / 2 # 降到多少以下恢复读
5
5
  EXPIRE_NEW = 5 # 多久没有建立通道,过期
6
6
  EXPIRE_AFTER = 300 # 多久没有新流量,过期
7
+ EXPIRE_CTL = 86400 # 多久没有ctlmsg来,过期
7
8
  RESET_TRAFF_DAY = 1 # 流量计数重置日,0为不重置
8
9
  CHECK_TRAFF_INTERVAL = 86400 # 检查今天是否是流量计数重置日间隔
9
10
  CHECK_EXPIRE_INTERVAL = 5 # 检查过期间隔
10
11
  CHECK_RESUME_INTERVAL = 1 # 检查恢复读间隔
11
12
  RESOLV_CACHE_EXPIRE = 300 # dns查询结果缓存多久过期
13
+ RESEND_LIMIT = 5 # ctlmsg重传次数
14
+ RESEND_INTERVAL = 1 # ctlmsg重传间隔
12
15
  HELLO = 1
13
16
  TUND_PORT = 2
14
17
  A_NEW_SOURCE = 3
@@ -31,6 +34,8 @@ module Girl
31
34
  RESOLV = 20
32
35
  RESOLVED = 21
33
36
  HEARTBEAT = 22
37
+ UNKNOWN_CTL_ADDR = 23
38
+ CTL_FIN = 24
34
39
  TRAFF_INFOS = 101
35
40
  SEPARATE = "\r\n\r\n"
36
41
  HTTP_OK = "HTTP/1.1 200 OK\r\n\r\n"
@@ -49,8 +54,13 @@ EOF
49
54
  RESUME_BELOW
50
55
  EXPIRE_NEW
51
56
  EXPIRE_AFTER
57
+ EXPIRE_CTL
58
+ RESET_TRAFF_DAY
59
+ CHECK_TRAFF_INTERVAL
52
60
  CHECK_EXPIRE_INTERVAL
53
61
  CHECK_RESUME_INTERVAL
54
62
  RESOLV_CACHE_EXPIRE
63
+ RESEND_LIMIT
64
+ RESEND_INTERVAL
55
65
  ]
56
66
  end
data/lib/girl/proxy.rb CHANGED
@@ -6,7 +6,6 @@ require 'girl/proxy_worker'
6
6
  require 'girl/version'
7
7
  require 'ipaddr'
8
8
  require 'json'
9
- require 'openssl'
10
9
  require 'socket'
11
10
 
12
11
  ##
@@ -14,29 +13,32 @@ require 'socket'
14
13
  #
15
14
  #
16
15
  =begin
17
- C: 1 hello -> hello
18
- 2 tund port -> n: tund port
19
- 3 a new source -> Q>: src id -> encoded destination address
20
- 4 paired -> Q>: src id -> n: dst id
21
- 5 dest status NOT USE
22
- 6 source status NOT USE
23
- 7 miss NOT USE
24
- 8 fin1 NOT USE
25
- 9 confirm fin1 NOT USE
26
- 10 fin2 NOT USE
27
- 11 confirm fin2 NOT USE
28
- 12 tund fin
29
- 13 tun fin
30
- 14 tun ip changed NOT USE
31
- 15 single miss NOT USE
32
- 16 range miss NOT USE
33
- 17 continue NOT USE
34
- 18 is resend ready NOT USE
35
- 19 resend ready NOT USE
36
- 20 resolv -> Q>: src id -> encoded domain
37
- 21 resolved -> Q>: src id -> encoded ip
16
+ C: 1 hello -> hello
17
+ 2 tund port -> n: atund port -> n: btund port
18
+ 3 a new source -> Q>: src id -> destination
19
+ 4 paired -> Q>: src id -> n: dst id
20
+ 5 dest status NOT USE
21
+ 6 source status NOT USE
22
+ 7 miss NOT USE
23
+ 8 fin1 NOT USE
24
+ 9 confirm fin1 NOT USE
25
+ 10 fin2 NOT USE
26
+ 11 confirm fin2 NOT USE
27
+ 12 tund fin NOT USE
28
+ 13 tun fin NOT USE
29
+ 14 tun ip changed NOT USE
30
+ 15 single miss NOT USE
31
+ 16 range miss NOT USE
32
+ 17 continue NOT USE
33
+ 18 is resend ready NOT USE
34
+ 19 resend ready NOT USE
35
+ 20 resolv NOT USE
36
+ 21 resolved NOT USE
37
+ 22 heartbeat NOT USE
38
+ 23 unknown ctl addr
39
+ 24 ctl fin
38
40
  101 traff infos
39
- 101 traff infos -> [ C: im len -> im -> Q>: traff in -> Q>: traff out ]
41
+ 101 traff infos -> [ C: im len -> im -> Q>: traff in -> Q>: traff out ]
40
42
  =end
41
43
 
42
44
  module Girl
@@ -56,7 +58,6 @@ module Girl
56
58
  direct_path = conf[ :direct_path ]
57
59
  remote_path = conf[ :remote_path ]
58
60
  im = conf[ :im ]
59
- use_remote_resolv = conf[ :use_remote_resolv ]
60
61
  worker_count = conf[ :worker_count ]
61
62
 
62
63
  unless redir_port then
@@ -87,10 +88,6 @@ module Girl
87
88
  im = 'girl'
88
89
  end
89
90
 
90
- unless use_remote_resolv then
91
- use_remote_resolv = false
92
- end
93
-
94
91
  nprocessors = Etc.nprocessors
95
92
 
96
93
  if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors then
@@ -105,7 +102,7 @@ module Girl
105
102
 
106
103
  title = "girl proxy #{ Girl::VERSION }"
107
104
  puts title
108
- puts "redir port #{ redir_port } proxyd host #{ proxyd_host } proxyd port #{ proxyd_port } im #{ im } use remote resolv #{ use_remote_resolv } worker count #{ worker_count }"
105
+ puts "redir port #{ redir_port } proxyd host #{ proxyd_host } proxyd port #{ proxyd_port } im #{ im } worker count #{ worker_count }"
109
106
  puts "#{ direct_path } #{ directs.size } directs"
110
107
  puts "#{ remote_path } #{ remotes.size } remotes"
111
108
 
@@ -116,7 +113,7 @@ module Girl
116
113
  worker_count.times do | i |
117
114
  workers << fork do
118
115
  $0 = 'girl proxy worker'
119
- worker = Girl::ProxyWorker.new( redir_port, proxyd_host, proxyd_port, directs, remotes, im, use_remote_resolv )
116
+ worker = Girl::ProxyWorker.new( redir_port, proxyd_host, proxyd_port, directs, remotes, im )
120
117
 
121
118
  Signal.trap( :TERM ) do
122
119
  puts "w#{ i } exit"
@@ -140,7 +137,7 @@ module Girl
140
137
 
141
138
  Process.waitall
142
139
  else
143
- Girl::ProxyWorker.new( redir_port, proxyd_host, proxyd_port, directs, remotes, im, use_remote_resolv ).looping
140
+ Girl::ProxyWorker.new( redir_port, proxyd_host, proxyd_port, directs, remotes, im ).looping
144
141
  end
145
142
  end
146
143
 
@@ -1,13 +1,16 @@
1
- module Girl
2
- class ProxyCustom
3
-
4
- def initialize( im )
5
- @im = im
6
- end
7
-
8
- def hello
9
- @im
10
- end
11
-
12
- end
13
- end
1
+ require 'girl/custom'
2
+
3
+ module Girl
4
+ class ProxyCustom
5
+ include Custom
6
+
7
+ def initialize( im )
8
+ @im = im
9
+ end
10
+
11
+ def hello
12
+ @im
13
+ end
14
+
15
+ end
16
+ end
@@ -4,28 +4,28 @@ module Girl
4
4
  ##
5
5
  # initialize
6
6
  #
7
- def initialize( redir_port, proxyd_host, proxyd_port, directs, remotes, im, use_remote_resolv )
7
+ def initialize( redir_port, proxyd_host, proxyd_port, directs, remotes, im )
8
8
  @proxyd_host = proxyd_host
9
+ @proxyd_port = proxyd_port
9
10
  @proxyd_addr = Socket.sockaddr_in( proxyd_port, proxyd_host )
10
11
  @directs = directs
11
12
  @remotes = remotes
12
13
  @custom = Girl::ProxyCustom.new( im )
13
- @use_remote_resolv = use_remote_resolv
14
14
  @reads = []
15
15
  @writes = []
16
16
  @closing_srcs = []
17
17
  @paused_srcs = []
18
18
  @paused_dsts = []
19
- @paused_tuns = []
19
+ @paused_btuns = []
20
20
  @resume_srcs = []
21
21
  @resume_dsts = []
22
- @resume_tuns = []
23
- @pending_srcs = [] # 还没配到tund,暂存的src
24
- @roles = ConcurrentHash.new # sock => :dotr / :redir / :proxy / :src / :dst / :tun / :pre_proxy / :pre_tun
22
+ @resume_btuns = []
23
+ @pending_srcs = [] # 还没得到atund和btund地址,暂存的src
24
+ @roles = ConcurrentHash.new # sock => :dotr / :redir / :ctl / :src / :dst / :atun / :btun
25
25
  @src_infos = ConcurrentHash.new # src => {}
26
26
  @dst_infos = ConcurrentHash.new # dst => {}
27
- @tun_infos = ConcurrentHash.new # tun => {}
28
- @pre_tun_infos = ConcurrentHash.new # pre_tun => {}
27
+ @atun_infos = ConcurrentHash.new # atun => {}
28
+ @btun_infos = ConcurrentHash.new # btun => {}
29
29
  @resolv_caches = ConcurrentHash.new # domain => [ ip, created_at ]
30
30
  @is_direct_caches = ConcurrentHash.new # ip => true / false
31
31
  @srcs = ConcurrentHash.new # src_id => src
@@ -54,31 +54,27 @@ module Girl
54
54
  read_dotr( sock )
55
55
  when :redir then
56
56
  read_redir( sock )
57
- when :proxy then
58
- read_proxy( sock )
57
+ when :ctl then
58
+ read_ctl( sock )
59
59
  when :src then
60
60
  read_src( sock )
61
61
  when :dst then
62
62
  read_dst( sock )
63
- when :tun then
64
- read_tun( sock )
63
+ when :btun then
64
+ read_btun( sock )
65
65
  end
66
66
  end
67
67
 
68
68
  ws.each do | sock |
69
69
  case @roles[ sock ]
70
- when :proxy then
71
- write_proxy( sock )
72
70
  when :src then
73
71
  write_src( sock )
74
72
  when :dst then
75
73
  write_dst( sock )
76
- when :tun then
77
- write_tun( sock )
78
- when :pre_proxy then
79
- write_pre_proxy( sock )
80
- when :pre_tun then
81
- write_pre_tun( sock )
74
+ when :atun then
75
+ write_atun( sock )
76
+ when :btun then
77
+ write_btun( sock )
82
78
  end
83
79
  end
84
80
  end
@@ -91,13 +87,8 @@ module Girl
91
87
  # quit!
92
88
  #
93
89
  def quit!
94
- if @proxy && !@proxy.closed? then
95
- # puts "debug1 send tun fin"
96
- data = [ TUN_FIN ].pack( 'C' )
97
- @proxy.write( data )
98
- end
99
-
100
- # puts "debug1 exit"
90
+ # puts "debug exit"
91
+ send_ctlmsg( [ CTL_FIN ].pack( 'C' ) )
101
92
  exit
102
93
  end
103
94
 
@@ -111,8 +102,24 @@ module Girl
111
102
  destination_domain = src_info[ :destination_domain ]
112
103
  destination_port = src_info[ :destination_port ]
113
104
  domain_port = [ destination_domain, destination_port ].join( ':' )
114
- data = "#{ [ A_NEW_SOURCE, src_info[ :id ] ].pack( 'CQ>' ) }#{ domain_port }"
115
- add_ctlmsg( data )
105
+ # puts "debug add a new source #{ src_info[ :id ] } #{ domain_port }"
106
+ key = [ A_NEW_SOURCE, src_info[ :id ] ].pack( 'CQ>' )
107
+ add_ctlmsg( key, domain_port )
108
+ end
109
+
110
+ ##
111
+ # add atun wbuff
112
+ #
113
+ def add_atun_wbuff( atun, data )
114
+ return if atun.closed?
115
+ atun_info = @atun_infos[ atun ]
116
+ atun_info[ :wbuff ] << data
117
+ add_write( atun )
118
+
119
+ if atun_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
120
+ puts "p#{ Process.pid } #{ Time.new } pause tunnel src #{ atun_info[ :domain ] }"
121
+ add_paused_src( atun_info[ :src ] )
122
+ end
116
123
  end
117
124
 
118
125
  ##
@@ -127,16 +134,18 @@ module Girl
127
134
  ##
128
135
  # add ctlmsg
129
136
  #
130
- def add_ctlmsg( data )
131
- return if @proxy.nil? || @proxy.closed?
132
- @proxy_info[ :ctlmsgs ] << data
133
- add_write( @proxy )
137
+ def add_ctlmsg( key, data )
138
+ ctlmsg = "#{ key }#{ data }"
139
+ send_ctlmsg( ctlmsg )
140
+ @ctl_info[ :resends ][ key ] = 0
141
+ loop_resend_ctlmsg( key, ctlmsg )
134
142
  end
135
143
 
136
144
  ##
137
145
  # add dst wbuff
138
146
  #
139
147
  def add_dst_wbuff( dst, data )
148
+ return if dst.closed?
140
149
  dst_info = @dst_infos[ dst ]
141
150
  dst_info[ :wbuff ] << data
142
151
  add_write( dst )
@@ -147,6 +156,15 @@ module Girl
147
156
  end
148
157
  end
149
158
 
159
+ ##
160
+ # add paused btun
161
+ #
162
+ def add_paused_btun( btun )
163
+ return if btun.closed? || @paused_btuns.include?( btun )
164
+ @reads.delete( btun )
165
+ @paused_btuns << btun
166
+ end
167
+
150
168
  ##
151
169
  # add paused dst
152
170
  #
@@ -165,15 +183,6 @@ module Girl
165
183
  @paused_srcs << src
166
184
  end
167
185
 
168
- ##
169
- # add paused tun
170
- #
171
- def add_paused_tun( tun )
172
- return if tun.closed? || @paused_tuns.include?( tun )
173
- @reads.delete( tun )
174
- @paused_tuns << tun
175
- end
176
-
177
186
  ##
178
187
  # add read
179
188
  #
@@ -188,6 +197,15 @@ module Girl
188
197
  next_tick
189
198
  end
190
199
 
200
+ ##
201
+ # add resume btun
202
+ #
203
+ def add_resume_btun( btun )
204
+ return if @resume_btuns.include?( btun )
205
+ @resume_btuns << btun
206
+ next_tick
207
+ end
208
+
191
209
  ##
192
210
  # add resume dst
193
211
  #
@@ -206,15 +224,6 @@ module Girl
206
224
  next_tick
207
225
  end
208
226
 
209
- ##
210
- # add resume tun
211
- #
212
- def add_resume_tun( tun )
213
- return if @resume_tuns.include?( tun )
214
- @resume_tuns << tun
215
- next_tick
216
- end
217
-
218
227
  ##
219
228
  # add socks5 conn reply
220
229
  #
@@ -226,7 +235,7 @@ module Girl
226
235
  # +----+-----+-------+------+----------+----------+
227
236
  redir_ip, redir_port = @redir_local_address.ip_unpack
228
237
  data = [ [ 5, 0, 0, 1 ].pack( 'C4' ), IPAddr.new( redir_ip ).hton, [ redir_port ].pack( 'n' ) ].join
229
- # puts "debug1 add src.wbuff socks5 conn reply #{ data.inspect }"
238
+ # puts "debug add src.wbuff socks5 conn reply #{ data.inspect }"
230
239
  add_src_wbuff( src, data )
231
240
  end
232
241
 
@@ -238,7 +247,7 @@ module Girl
238
247
  src_info[ :rbuff ] << data
239
248
 
240
249
  if src_info[ :rbuff ].bytesize >= WBUFF_LIMIT then
241
- # puts "debug1 src.rbuff full"
250
+ # puts "debug src.rbuff full"
242
251
  add_closing_src( src )
243
252
  end
244
253
  end
@@ -260,30 +269,16 @@ module Girl
260
269
  puts "p#{ Process.pid } #{ Time.new } pause dst #{ src_info[ :destination_domain ] }"
261
270
  add_paused_dst( dst )
262
271
  else
263
- tun = src_info[ :tun ]
272
+ btun = src_info[ :btun ]
264
273
 
265
- if tun then
266
- puts "p#{ Process.pid } #{ Time.new } pause tun #{ src_info[ :destination_domain ] }"
267
- add_paused_tun( tun )
274
+ if btun then
275
+ puts "p#{ Process.pid } #{ Time.new } pause btun #{ src_info[ :destination_domain ] }"
276
+ add_paused_btun( btun )
268
277
  end
269
278
  end
270
279
  end
271
280
  end
272
281
 
273
- ##
274
- # add tun wbuff
275
- #
276
- def add_tun_wbuff( tun, data )
277
- tun_info = @tun_infos[ tun ]
278
- tun_info[ :wbuff ] << data
279
- add_write( tun )
280
-
281
- if tun_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
282
- puts "p#{ Process.pid } #{ Time.new } pause tunnel src #{ tun_info[ :domain ] }"
283
- add_paused_src( tun_info[ :src ] )
284
- end
285
- end
286
-
287
282
  ##
288
283
  # add write
289
284
  #
@@ -294,32 +289,36 @@ module Girl
294
289
  end
295
290
 
296
291
  ##
297
- # close pre proxy
292
+ # close atun
298
293
  #
299
- def close_pre_proxy( pre_proxy )
300
- return if pre_proxy.closed?
301
- # puts "debug1 close pre proxy"
302
- close_sock( pre_proxy )
294
+ def close_atun( atun )
295
+ return if atun.closed?
296
+ # puts "debug close atun"
297
+ close_sock( atun )
298
+ atun_info = @atun_infos.delete( atun )
299
+ src = atun_info[ :src ]
300
+
301
+ if src then
302
+ @paused_srcs.delete( src )
303
+ end
303
304
  end
304
305
 
305
306
  ##
306
- # close pre tun
307
+ # close btun
307
308
  #
308
- def close_pre_tun( pre_tun )
309
- return if pre_tun.closed?
310
- # puts "debug1 close pre tun"
311
- close_sock( pre_tun )
312
- @pre_tun_infos.delete( pre_tun )
309
+ def close_btun( btun )
310
+ return if btun.closed?
311
+ # puts "debug close btun"
312
+ close_sock( btun )
313
+ del_btun_info( btun )
313
314
  end
314
315
 
315
316
  ##
316
- # close proxy
317
+ # close ctl
317
318
  #
318
- def close_proxy( proxy )
319
- return if proxy.closed?
320
- # puts "debug1 close proxy"
321
- close_sock( proxy )
322
- close_pre_proxy( @pre_proxy )
319
+ def close_ctl( ctl )
320
+ close_sock( ctl )
321
+ @ctl_info[ :resends ].clear
323
322
  end
324
323
 
325
324
  ##
@@ -327,20 +326,15 @@ module Girl
327
326
  #
328
327
  def close_read_dst( dst )
329
328
  return if dst.closed?
330
- # puts "debug1 close read dst"
329
+ # puts "debug close read dst"
331
330
  dst.close_read
332
331
  @reads.delete( dst )
333
332
 
334
333
  if dst.closed? then
335
- # puts "debug1 delete dst info"
336
334
  @writes.delete( dst )
337
335
  @roles.delete( dst )
338
- dst_info = @dst_infos.delete( dst )
339
- else
340
- dst_info = @dst_infos[ dst ]
336
+ del_dst_info( dst )
341
337
  end
342
-
343
- dst_info
344
338
  end
345
339
 
346
340
  ##
@@ -348,39 +342,15 @@ module Girl
348
342
  #
349
343
  def close_read_src( src )
350
344
  return if src.closed?
351
- # puts "debug1 close read src"
345
+ # puts "debug close read src"
352
346
  src.close_read
353
347
  @reads.delete( src )
354
348
 
355
349
  if src.closed? then
356
- # puts "debug1 delete src info"
357
350
  @writes.delete( src )
358
351
  @roles.delete( src )
359
- src_info = del_src_info( src )
360
- else
361
- src_info = @src_infos[ src ]
352
+ del_src_info( src )
362
353
  end
363
-
364
- src_info
365
- end
366
-
367
- ##
368
- # close read tun
369
- #
370
- def close_read_tun( tun )
371
- return if tun.closed?
372
- # puts "debug1 close read tun"
373
- tun_info = @tun_infos[ tun ]
374
- tun_info[ :close_read ] = true
375
-
376
- if tun_info[ :close_write ] then
377
- # puts "debug1 close tun"
378
- close_tun( tun )
379
- else
380
- @reads.delete( tun )
381
- end
382
-
383
- tun_info
384
354
  end
385
355
 
386
356
  ##
@@ -398,59 +368,44 @@ module Girl
398
368
  #
399
369
  def close_src( src )
400
370
  return if src.closed?
401
- # puts "debug1 close src"
371
+ # puts "debug close src"
402
372
  close_sock( src )
403
373
  src_info = del_src_info( src )
404
374
  dst = src_info[ :dst ]
405
375
 
406
376
  if dst then
407
377
  close_sock( dst )
408
- @dst_infos.delete( dst )
378
+ del_dst_info( dst )
409
379
  else
410
- tun = src_info[ :tun ]
380
+ atun = src_info[ :atun ]
381
+ btun = src_info[ :btun ]
411
382
 
412
- if tun then
413
- close_tun( tun )
414
- else
415
- pre_tun = src_info[ :pre_tun ]
383
+ if atun then
384
+ close_sock( atun )
385
+ @atun_infos.delete( atun )
386
+ end
416
387
 
417
- if pre_tun then
418
- close_pre_tun( pre_tun )
419
- end
388
+ if btun then
389
+ close_sock( btun )
390
+ del_btun_info( btun )
420
391
  end
421
392
  end
422
393
  end
423
394
 
424
- ##
425
- # close tun
426
- #
427
- def close_tun( tun )
428
- return if tun.closed?
429
- # puts "debug1 close tun"
430
- close_sock( tun )
431
- tun_info = @tun_infos.delete( tun )
432
- close_pre_tun( tun_info[ :pre_tun ] )
433
- end
434
-
435
395
  ##
436
396
  # close write dst
437
397
  #
438
398
  def close_write_dst( dst )
439
399
  return if dst.closed?
440
- # puts "debug1 close write dst"
400
+ # puts "debug close write dst"
441
401
  dst.close_write
442
402
  @writes.delete( dst )
443
403
 
444
404
  if dst.closed? then
445
- # puts "debug1 delete dst info"
446
405
  @reads.delete( dst )
447
406
  @roles.delete( dst )
448
- dst_info = @dst_infos.delete( dst )
449
- else
450
- dst_info = @dst_infos[ dst ]
407
+ del_dst_info( dst )
451
408
  end
452
-
453
- dst_info
454
409
  end
455
410
 
456
411
  ##
@@ -458,39 +413,15 @@ module Girl
458
413
  #
459
414
  def close_write_src( src )
460
415
  return if src.closed?
461
- # puts "debug1 close write src"
416
+ # puts "debug close write src"
462
417
  src.close_write
463
418
  @writes.delete( src )
464
419
 
465
420
  if src.closed? then
466
- # puts "debug1 delete src info"
467
421
  @reads.delete( src )
468
422
  @roles.delete( src )
469
- src_info = del_src_info( src )
470
- else
471
- src_info = @src_infos[ src ]
423
+ del_src_info( src )
472
424
  end
473
-
474
- src_info
475
- end
476
-
477
- ##
478
- # close write tun
479
- #
480
- def close_write_tun( tun )
481
- return if tun.closed?
482
- # puts "debug1 close write tun"
483
- tun_info = @tun_infos[ tun ]
484
- tun_info[ :close_write ] = true
485
-
486
- if tun_info[ :close_read ] then
487
- # puts "debug1 close tun"
488
- close_tun( tun )
489
- else
490
- @writes.delete( tun )
491
- end
492
-
493
- tun_info
494
425
  end
495
426
 
496
427
  ##
@@ -500,9 +431,8 @@ module Girl
500
431
  return if src.closed?
501
432
  src_info = @src_infos[ src ]
502
433
 
503
- if ip_info.ipv4_loopback? \
504
- || ip_info.ipv6_loopback? \
505
- || ( ( @ip_address_list.any? { | addrinfo | addrinfo.ip_address == ip_info.ip_address } ) && ( src_info[ :destination_port ] == @redir_port ) ) then
434
+ if ( ( @ip_address_list.any? { | addrinfo | addrinfo.ip_address == ip_info.ip_address } ) && ( src_info[ :destination_port ] == @redir_port ) ) \
435
+ || ( ( ip_info.ip_address == @proxyd_host ) && ( src_info[ :destination_port ] == @proxyd_port ) ) then
506
436
  puts "p#{ Process.pid } #{ Time.new } ignore #{ ip_info.ip_address }:#{ src_info[ :destination_port ] }"
507
437
  add_closing_src( src )
508
438
  return
@@ -519,29 +449,49 @@ module Girl
519
449
  is_direct = @is_direct_caches[ ip_info.ip_address ]
520
450
  else
521
451
  is_direct = @directs.any? { | direct | direct.include?( ip_info.ip_address ) }
522
- # 判断直连耗时较长(树莓派 0.27秒),这里可能切去主线程,回来src可能已关闭
523
452
  puts "p#{ Process.pid } #{ Time.new } cache is direct #{ ip_info.ip_address } #{ is_direct }"
524
453
  @is_direct_caches[ ip_info.ip_address ] = is_direct
525
454
  end
526
455
 
527
456
  if is_direct then
528
- # puts "debug1 #{ ip_info.inspect } hit directs"
457
+ # puts "debug #{ ip_info.inspect } hit directs"
529
458
  new_a_dst( src, ip_info )
530
459
  else
531
- # 走远端
532
- # puts "debug1 #{ ip_info.inspect } go tunnel"
460
+ # puts "debug #{ ip_info.inspect } go tunnel"
533
461
  set_proxy_type_tunnel( src )
534
462
  end
535
463
  end
536
464
 
465
+ ##
466
+ # del btun info
467
+ #
468
+ def del_btun_info( btun )
469
+ @btun_infos.delete( btun )
470
+ @paused_btuns.delete( btun )
471
+ @resume_btuns.delete( btun )
472
+ end
473
+
474
+ ##
475
+ # del dst info
476
+ #
477
+ def del_dst_info( dst )
478
+ # puts "debug delete dst info"
479
+ dst_info = @dst_infos.delete( dst )
480
+ @paused_dsts.delete( dst )
481
+ @resume_dsts.delete( dst )
482
+ dst_info
483
+ end
484
+
537
485
  ##
538
486
  # del src info
539
487
  #
540
488
  def del_src_info( src )
489
+ # puts "debug delete src info"
541
490
  src_info = @src_infos.delete( src )
542
491
  @srcs.delete( src_info[ :id ] )
543
492
  @pending_srcs.delete( src )
544
-
493
+ @paused_srcs.delete( src )
494
+ @resume_srcs.delete( src )
545
495
  src_info
546
496
  end
547
497
 
@@ -554,37 +504,23 @@ module Girl
554
504
  sleep CHECK_EXPIRE_INTERVAL
555
505
  now = Time.new
556
506
 
557
- if @proxy && !@proxy.closed? then
558
- if @proxy_info[ :last_recv_at ] then
559
- last_recv_at = @proxy_info[ :last_recv_at ]
560
- expire_after = EXPIRE_AFTER
561
- else
562
- last_recv_at = @proxy_info[ :created_at ]
563
- expire_after = EXPIRE_NEW
564
- end
507
+ if @ctl && !@ctl.closed? then
508
+ last_recv_at = @ctl_info[ :last_recv_at ] || @ctl_info[ :created_at ]
565
509
 
566
- if now - last_recv_at >= expire_after then
567
- puts "p#{ Process.pid } #{ Time.new } expire proxy"
568
- @proxy_info[ :closing ] = true
569
- next_tick
570
- else
571
- # puts "debug1 #{ Time.new } send heartbeat"
572
- data = [ HEARTBEAT ].pack( 'C' )
573
- add_ctlmsg( data )
510
+ if now - last_recv_at >= EXPIRE_AFTER then
511
+ puts "p#{ Process.pid } #{ Time.new } expire ctl"
512
+ @ctl_info[ :closing ] = true
513
+ next_tick
574
514
  end
575
- elsif @pre_proxy && !@pre_proxy.closed? && ( now - @pre_proxy_info[ :created_at ] > EXPIRE_NEW ) then
576
- puts "p#{ Process.pid } #{ Time.new } expire pre proxy"
577
- @pre_proxy_info[ :closing ] = true
578
- next_tick
579
515
  end
580
516
 
581
517
  @src_infos.each do | src, src_info |
582
518
  last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
583
519
  last_sent_at = src_info[ :last_sent_at ] || src_info[ :created_at ]
584
- expire_after = ( src_info[ :dst ] || src_info[ :tun ] ) ? EXPIRE_AFTER : EXPIRE_NEW
520
+ expire_after = ( src_info[ :dst ] || src_info[ :atun ] ) ? EXPIRE_AFTER : EXPIRE_NEW
585
521
 
586
522
  if ( now - last_recv_at >= expire_after ) && ( now - last_sent_at >= expire_after ) then
587
- puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :destination_domain ] }"
523
+ puts "p#{ Process.pid } #{ Time.new } expire src #{ expire_after } #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
588
524
  add_closing_src( src )
589
525
 
590
526
  unless src_info[ :rbuff ].empty? then
@@ -605,24 +541,25 @@ module Girl
605
541
  sleep CHECK_RESUME_INTERVAL
606
542
 
607
543
  @paused_srcs.each do | src |
608
- if src.closed? then
609
- add_resume_src( src )
610
- else
611
- src_info = @src_infos[ src ]
612
- dst = src_info[ :dst ]
544
+ src_info = @src_infos[ src ]
545
+ dst = src_info[ :dst ]
613
546
 
614
- if dst then
547
+ if dst then
548
+ if !dst.closed? then
615
549
  dst_info = @dst_infos[ dst ]
616
550
 
617
551
  if dst_info[ :wbuff ].size < RESUME_BELOW then
618
552
  puts "p#{ Process.pid } #{ Time.new } resume direct src #{ src_info[ :destination_domain ] }"
619
553
  add_resume_src( src )
620
554
  end
621
- else
622
- tun = src_info[ :tun ]
623
- tun_info = @tun_infos[ tun ]
555
+ end
556
+ else
557
+ atun = src_info[ :atun ]
558
+
559
+ if atun && !atun.closed? then
560
+ atun_info = @atun_infos[ atun ]
624
561
 
625
- if tun_info[ :wbuff ].size < RESUME_BELOW then
562
+ if atun_info[ :wbuff ].size < RESUME_BELOW then
626
563
  puts "p#{ Process.pid } #{ Time.new } resume tunnel src #{ src_info[ :destination_domain ] }"
627
564
  add_resume_src( src )
628
565
  end
@@ -631,11 +568,10 @@ module Girl
631
568
  end
632
569
 
633
570
  @paused_dsts.each do | dst |
634
- if dst.closed? then
635
- add_resume_dst( dst )
636
- else
637
- dst_info = @dst_infos[ dst ]
638
- src = dst_info[ :src ]
571
+ dst_info = @dst_infos[ dst ]
572
+ src = dst_info[ :src ]
573
+
574
+ if src && !src.closed? then
639
575
  src_info = @src_infos[ src ]
640
576
 
641
577
  if src_info[ :wbuff ].size < RESUME_BELOW then
@@ -645,17 +581,16 @@ module Girl
645
581
  end
646
582
  end
647
583
 
648
- @paused_tuns.each do | tun |
649
- if tun.closed? then
650
- add_resume_tun( tun )
651
- else
652
- tun_info = @tun_infos[ tun ]
653
- src = tun_info[ :src ]
584
+ @paused_btuns.each do | btun |
585
+ btun_info = @btun_infos[ btun ]
586
+ src = btun_info[ :src ]
587
+
588
+ if src && !src.closed? then
654
589
  src_info = @src_infos[ src ]
655
590
 
656
591
  if src_info[ :wbuff ].size < RESUME_BELOW then
657
- puts "p#{ Process.pid } #{ Time.new } resume tun #{ tun_info[ :domain ] }"
658
- add_resume_tun( tun )
592
+ puts "p#{ Process.pid } #{ Time.new } resume btun #{ btun_info[ :domain ] }"
593
+ add_resume_btun( btun )
659
594
  end
660
595
  end
661
596
  end
@@ -663,6 +598,31 @@ module Girl
663
598
  end
664
599
  end
665
600
 
601
+ ##
602
+ # loop resend ctlmsg
603
+ #
604
+ def loop_resend_ctlmsg( key, ctlmsg )
605
+ Thread.new do
606
+ loop do
607
+ sleep RESEND_INTERVAL
608
+
609
+ resend = @ctl_info[ :resends ][ key ]
610
+ break unless resend
611
+
612
+ puts "p#{ Process.pid } #{ Time.new } resend #{ ctlmsg.inspect }"
613
+ send_ctlmsg( ctlmsg )
614
+ resend += 1
615
+
616
+ if resend >= RESEND_LIMIT then
617
+ @ctl_info[ :resends ].delete( key )
618
+ break
619
+ end
620
+
621
+ @ctl_info[ :resends ][ key ] = resend
622
+ end
623
+ end
624
+ end
625
+
666
626
  ##
667
627
  # new a dst
668
628
  #
@@ -672,7 +632,6 @@ module Girl
672
632
  domain = src_info[ :destination_domain ]
673
633
  destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
674
634
  dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
675
- dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 ) if RUBY_PLATFORM.include?( 'linux' )
676
635
 
677
636
  begin
678
637
  dst.connect_nonblock( destination_addr )
@@ -685,7 +644,7 @@ module Girl
685
644
  return
686
645
  end
687
646
 
688
- # puts "debug1 a new dst #{ dst.local_address.inspect }"
647
+ # puts "debug a new dst #{ dst.local_address.inspect }"
689
648
  dst_info = {
690
649
  src: src, # 对应src
691
650
  domain: domain, # 目的地
@@ -700,10 +659,10 @@ module Girl
700
659
 
701
660
  if src_info[ :proxy_proto ] == :http then
702
661
  if src_info[ :is_connect ] then
703
- # puts "debug1 add src.wbuff http ok"
662
+ # puts "debug add src.wbuff http ok"
704
663
  add_src_wbuff( src, HTTP_OK )
705
664
  elsif src_info[ :rbuff ] then
706
- # puts "debug1 move src.rbuff to dst.wbuff"
665
+ # puts "debug move src.rbuff to dst.wbuff"
707
666
  dst_info[ :wbuff ] << src_info[ :rbuff ]
708
667
  add_write( dst )
709
668
  end
@@ -713,65 +672,31 @@ module Girl
713
672
  end
714
673
 
715
674
  ##
716
- # new a pre proxy
675
+ # new a ctl
717
676
  #
718
- def new_a_pre_proxy
719
- pre_proxy = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
720
- pre_proxy.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
677
+ def new_a_ctl
678
+ ctl = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
721
679
 
722
680
  if RUBY_PLATFORM.include?( 'linux' ) then
723
- pre_proxy.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
724
- pre_proxy.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
681
+ ctl.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
725
682
  end
726
683
 
727
- begin
728
- pre_proxy.connect_nonblock( @proxyd_addr )
729
- rescue IO::WaitWritable
730
- rescue Exception => e
731
- puts "p#{ Process.pid } #{ Time.new } connect proxyd #{ e.class }, close pre proxy"
732
- pre_proxy.close
733
- return
734
- end
684
+ @ctl = ctl
685
+ add_read( ctl, :ctl )
735
686
 
736
- @pre_proxy = pre_proxy
737
- @roles[ pre_proxy ] = :pre_proxy
738
- @pre_proxy_info = {
739
- closing: false,
740
- created_at: Time.new
687
+ @ctl_info = {
688
+ resends: ConcurrentHash.new, # key => count
689
+ atund_addr: nil, # atund地址,src->dst
690
+ btund_addr: nil, # btund地址,dst->src
691
+ closing: false, # 准备关闭
692
+ created_at: Time.new, # 创建时间
693
+ last_recv_at: nil # 最近一次收到数据时间
741
694
  }
742
- add_write( pre_proxy )
743
- end
744
-
745
- ##
746
- # new a pre tun
747
- #
748
- def new_a_pre_tun( src_id, dst_id )
749
- src = @srcs[ src_id ]
750
- return if src.nil? || src.closed?
751
- src_info = @src_infos[ src ]
752
- return if src_info[ :dst_id ]
753
695
 
754
- pre_tun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
755
- pre_tun.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 ) if RUBY_PLATFORM.include?( 'linux' )
756
-
757
- begin
758
- pre_tun.connect_nonblock( @proxy_info[ :tund_addr ] )
759
- rescue IO::WaitWritable
760
- rescue Exception => e
761
- puts "p#{ Process.pid } #{ Time.new } connect tund #{ e.class }, close pre tun"
762
- pre_tun.close
763
- return
764
- end
765
-
766
- src_info[ :pre_tun ] = pre_tun
767
- src_info[ :dst_id ] = dst_id
768
- @pre_tun_infos[ pre_tun ] = {
769
- src: src,
770
- destination_domain: src_info[ :destination_domain ],
771
- created_at: Time.new
772
- }
773
- @roles[ pre_tun ] = :pre_tun
774
- add_write( pre_tun )
696
+ hello = @custom.hello
697
+ puts "p#{ Process.pid } #{ Time.new } hello i'm #{ hello.inspect }"
698
+ key = [ HELLO ].pack( 'C' )
699
+ add_ctlmsg( key, hello )
775
700
  end
776
701
 
777
702
  ##
@@ -783,7 +708,6 @@ module Girl
783
708
 
784
709
  if RUBY_PLATFORM.include?( 'linux' ) then
785
710
  redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
786
- redir.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
787
711
  end
788
712
 
789
713
  redir.bind( Socket.sockaddr_in( redir_port, '0.0.0.0' ) )
@@ -794,6 +718,86 @@ module Girl
794
718
  @redir_local_address = redir.local_address
795
719
  end
796
720
 
721
+ ##
722
+ # new tuns
723
+ #
724
+ def new_tuns( src_id, dst_id )
725
+ return if @ctl_info[ :atund_addr ].nil? || @ctl_info[ :btund_addr ].nil?
726
+ src = @srcs[ src_id ]
727
+ return if src.nil? || src.closed?
728
+ src_info = @src_infos[ src ]
729
+ return if src_info[ :dst_id ]
730
+
731
+ # puts "debug new atun and btun"
732
+ atun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
733
+
734
+ begin
735
+ atun.connect_nonblock( @ctl_info[ :atund_addr ] )
736
+ rescue IO::WaitWritable
737
+ rescue Exception => e
738
+ puts "p#{ Process.pid } #{ Time.new } connect atund #{ e.class }, close atun"
739
+ atun.close
740
+ return
741
+ end
742
+
743
+ btun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
744
+
745
+ begin
746
+ btun.connect_nonblock( @ctl_info[ :btund_addr ] )
747
+ rescue IO::WaitWritable
748
+ rescue Exception => e
749
+ puts "p#{ Process.pid } #{ Time.new } connect btund #{ e.class }, close btun"
750
+ btun.close
751
+ return
752
+ end
753
+
754
+ domain = src_info[ :destination_domain ]
755
+ atun_wbuff = [ dst_id ].pack( 'n' )
756
+
757
+ until src_info[ :rbuff ].empty? do
758
+ data = src_info[ :rbuff ][ 0, 65535 ]
759
+ data_size = data.bytesize
760
+ # puts "debug move src.rbuff #{ data_size } to atun.wbuff"
761
+ atun_wbuff << pack_a_chunk( data )
762
+ src_info[ :rbuff ] = src_info[ :rbuff ][ data_size..-1 ]
763
+ end
764
+
765
+ @atun_infos[ atun ] = {
766
+ src: src, # 对应src
767
+ domain: domain, # 目的地
768
+ wbuff: atun_wbuff, # 写前
769
+ closing: false # 准备关闭
770
+ }
771
+
772
+ btun_wbuff = [ dst_id ].pack( 'n' )
773
+
774
+ @btun_infos[ btun ] = {
775
+ src: src, # 对应src
776
+ domain: domain, # 目的地
777
+ wbuff: btun_wbuff, # 写前
778
+ rbuff: '', # 暂存当前块没收全的流量
779
+ wait_bytes: 0, # 还差多少字节收全当前块
780
+ lbuff: '' # 流量截断在长度前缀处
781
+ }
782
+
783
+ src_info[ :dst_id ] = dst_id
784
+ src_info[ :atun ] = atun
785
+ src_info[ :btun ] = btun
786
+ add_read( atun, :atun )
787
+ add_read( btun, :btun )
788
+ add_write( atun )
789
+ add_write( btun )
790
+
791
+ if src_info[ :proxy_proto ] == :http then
792
+ if src_info[ :is_connect ] then
793
+ # puts "debug add src.wbuff http ok"
794
+ add_src_wbuff( src, HTTP_OK )
795
+ end
796
+ elsif src_info[ :proxy_proto ] == :socks5 then
797
+ add_socks5_conn_reply( src )
798
+ end
799
+ end
800
+
797
801
  ##
798
802
  # next tick
799
803
  #
@@ -801,6 +805,14 @@ module Girl
801
805
  @dotw.write( '.' )
802
806
  end
803
807
 
808
+ ##
809
+ # pack a chunk
810
+ #
811
+ def pack_a_chunk( data )
812
+ data = @custom.encode( data )
813
+ "#{ [ data.bytesize ].pack( 'n' ) }#{ data }"
814
+ end
815
+
804
816
  ##
805
817
  # resolve domain
806
818
  #
@@ -817,24 +829,18 @@ module Girl
817
829
  ip_info, created_at = resolv_cache
818
830
 
819
831
  if Time.new - created_at < RESOLV_CACHE_EXPIRE then
820
- # puts "debug1 #{ domain } hit resolv cache #{ ip_info.inspect }"
832
+ # puts "debug #{ domain } hit resolv cache #{ ip_info.inspect }"
821
833
  deal_with_destination_ip( src, ip_info )
822
834
  return
823
835
  end
824
836
 
825
- # puts "debug1 expire #{ domain } resolv cache"
837
+ # puts "debug expire #{ domain } resolv cache"
826
838
  @resolv_caches.delete( domain )
827
839
  end
828
840
 
829
841
  src_info = @src_infos[ src ]
830
842
  src_info[ :proxy_type ] = :checking
831
843
 
832
- if @use_remote_resolv then
833
- data = "#{ [ RESOLV, src_info[ :id ] ].pack( 'CQ>' ) }#{ domain }"
834
- add_ctlmsg( data )
835
- return
836
- end
837
-
838
844
  Thread.new do
839
845
  begin
840
846
  ip_info = Addrinfo.ip( domain )
@@ -852,6 +858,34 @@ module Girl
852
858
  end
853
859
  end
854
860
 
861
+ ##
862
+ # send ctlmsg
863
+ #
864
+ def send_ctlmsg( data )
865
+ return if @ctl.nil? || @ctl.closed?
866
+ data = @custom.encode( data )
867
+
868
+ begin
869
+ @ctl.sendmsg( data, 0, @proxyd_addr )
870
+ @ctl_info[ :last_sent_at ] = Time.new
871
+ rescue Exception => e
872
+ puts "p#{ Process.pid } #{ Time.new } sendmsg #{ e.class }"
873
+ close_ctl( @ctl )
874
+ end
875
+ end
876
+
877
+ ##
878
+ # set atun closing
879
+ #
880
+ def set_atun_closing( atun )
881
+ return if atun.closed?
882
+ atun_info = @atun_infos[ atun ]
883
+ return if atun_info[ :closing ]
884
+ # puts "debug set atun closing"
885
+ atun_info[ :closing ] = true
886
+ add_write( atun )
887
+ end
888
+
855
889
  ##
856
890
  # set dst closing write
857
891
  #
@@ -859,6 +893,7 @@ module Girl
859
893
  return if dst.closed?
860
894
  dst_info = @dst_infos[ dst ]
861
895
  return if dst_info[ :closing_write ]
896
+ # puts "debug set dst closing write"
862
897
  dst_info[ :closing_write ] = true
863
898
  add_write( dst )
864
899
  end
@@ -872,7 +907,7 @@ module Girl
872
907
  src_info[ :proxy_type ] = :tunnel
873
908
  src_id = src_info[ :id ]
874
909
 
875
- if @proxy && !@proxy.closed? && @proxy_info[ :tund_addr ] then
910
+ if @ctl && !@ctl.closed? && @ctl_info[ :atund_addr ] then
876
911
  add_a_new_source( src )
877
912
  else
878
913
  @pending_srcs << src
@@ -890,48 +925,15 @@ module Girl
890
925
  add_write( src )
891
926
  end
892
927
 
893
- ##
894
- # set tun closing write
895
- #
896
- def set_tun_closing_write( tun )
897
- return if tun.closed?
898
- tun_info = @tun_infos[ tun ]
899
- return if tun_info[ :closing_write ]
900
- tun_info[ :closing_write ] = true
901
- add_write( tun )
902
- end
903
-
904
- ##
905
- # sub http request
906
- #
907
- def sub_http_request( data )
908
- lines = data.split( "\r\n" )
909
-
910
- return [ data, nil ] if lines.empty?
911
-
912
- method, url, proto = lines.first.split( ' ' )
913
-
914
- if proto && url && proto[ 0, 4 ] == 'HTTP' && url[ 0, 7 ] == 'http://' then
915
- domain_port = url.split( '/' )[ 2 ]
916
- data = data.sub( "http://#{ domain_port }", '' )
917
- # puts "debug1 subed #{ data.inspect } #{ domain_port }"
918
- end
919
-
920
- [ data, domain_port ]
921
- end
922
-
923
928
  ##
924
929
  # read dotr
925
930
  #
926
931
  def read_dotr( dotr )
927
- dotr.read_nonblock( READ_SIZE )
932
+ dotr.read_nonblock( 65535 )
928
933
 
929
- if @proxy && !@proxy.closed? then
930
- if @proxy_info[ :closing ] then
931
- close_proxy( @proxy )
932
- end
933
- elsif @pre_proxy && !@pre_proxy.closed? && @pre_proxy_info[ :closing ] then
934
- close_pre_proxy( @pre_proxy )
934
+ if @ctl_info && @ctl_info[ :closing ] then
935
+ send_ctlmsg( [ CTL_FIN ].pack( 'C' ) )
936
+ close_ctl( @ctl )
935
937
  end
936
938
 
937
939
  if @closing_srcs.any? then
@@ -957,13 +959,13 @@ module Girl
957
959
  @resume_dsts.clear
958
960
  end
959
961
 
960
- if @resume_tuns.any? then
961
- @resume_tuns.each do | tun |
962
- add_read( tun )
963
- @paused_tuns.delete( tun )
962
+ if @resume_btuns.any? then
963
+ @resume_btuns.each do | btun |
964
+ add_read( btun )
965
+ @paused_btuns.delete( btun )
964
966
  end
965
967
 
966
- @resume_tuns.clear
968
+ @resume_btuns.clear
967
969
  end
968
970
  end
969
971
 
@@ -979,7 +981,7 @@ module Girl
979
981
  end
980
982
 
981
983
  src_id = rand( ( 2 ** 64 ) - 2 ) + 1
982
- # puts "debug1 accept a src #{ addrinfo.ip_unpack.inspect } #{ src_id }"
984
+ # puts "debug accept a src #{ src_id } #{ addrinfo.ip_unpack.inspect }"
983
985
 
984
986
  @srcs[ src_id ] = src
985
987
  @src_infos[ src ] = {
@@ -991,10 +993,11 @@ module Girl
991
993
  is_connect: true, # 代理协议是http的场合,是否是CONNECT
992
994
  rbuff: '', # 读到的流量
993
995
  dst: nil, # :direct的场合,对应的dst
994
- pre_tun: nil, # :tunnel的场合,对应的pre tun
995
- tun: nil, # :tunnel的场合,对应的tun
996
+ ctl: nil, # :tunnel的场合,对应的ctl
997
+ atun: nil, # :tunnel的场合,对应的atun
998
+ btun: nil, # :tunnel的场合,对应的btun
996
999
  dst_id: nil, # 远端dst id
997
- wbuff: '', # 从dst/tun读到的流量
1000
+ wbuff: '', # 从dst/btun读到的流量
998
1001
  created_at: Time.new, # 创建时间
999
1002
  last_recv_at: nil, # 上一次收到新流量(由dst收到,或者由tun收到)的时间
1000
1003
  last_sent_at: nil, # 上一次发出流量(由dst发出,或者由tun发出)的时间
@@ -1003,75 +1006,51 @@ module Girl
1003
1006
 
1004
1007
  add_read( src, :src )
1005
1008
 
1006
- # 避免多线程重复建proxy,在accept到src时就建。
1007
- if @pre_proxy.nil? || @pre_proxy.closed? then
1008
- new_a_pre_proxy
1009
+ if @ctl.nil? || @ctl.closed? then
1010
+ new_a_ctl
1009
1011
  end
1010
1012
  end
1011
1013
 
1012
1014
  ##
1013
- # read proxy
1015
+ # read ctl
1014
1016
  #
1015
- def read_proxy( proxy )
1016
- if proxy.closed? then
1017
- puts "p#{ Process.pid } #{ Time.new } read proxy but proxy closed?"
1018
- return
1019
- end
1020
-
1017
+ def read_ctl( ctl )
1021
1018
  begin
1022
- data = proxy.read_nonblock( READ_SIZE )
1023
- rescue IO::WaitReadable
1024
- return
1025
- rescue Errno::EINTR
1026
- puts e.class
1027
- return
1019
+ data, addrinfo, rflags, *controls = ctl.recvmsg
1028
1020
  rescue Exception => e
1029
- # puts "debug1 read proxy #{ e.class }"
1030
- close_proxy( proxy )
1021
+ puts "p#{ Process.pid } #{ Time.new } recvmsg #{ e.class }"
1022
+ close_ctl( ctl )
1031
1023
  return
1032
1024
  end
1033
1025
 
1034
- @proxy_info[ :last_recv_at ] = Time.new
1035
-
1036
- data.split( SEPARATE ).each do | ctlmsg |
1037
- next unless ctlmsg[ 0 ]
1026
+ data = @custom.decode( data )
1027
+ ctl_num = data[ 0 ].unpack( 'C' ).first
1038
1028
 
1039
- ctl_num = ctlmsg[ 0 ].unpack( 'C' ).first
1029
+ case ctl_num
1030
+ when TUND_PORT then
1031
+ return if @ctl_info[ :atund_addr ] || data.size != 5
1032
+ atund_port, btund_port = data[ 1, 4 ].unpack( 'nn' )
1033
+ puts "p#{ Process.pid } #{ Time.new } got tund port #{ atund_port } #{ btund_port }"
1034
+ @ctl_info[ :resends ].delete( [ HELLO ].pack( 'C' ) )
1035
+ @ctl_info[ :atund_addr ] = Socket.sockaddr_in( atund_port, @proxyd_host )
1036
+ @ctl_info[ :btund_addr ] = Socket.sockaddr_in( btund_port, @proxyd_host )
1037
+ @ctl_info[ :last_recv_at ] = Time.new
1040
1038
 
1041
- case ctl_num
1042
- when TUND_PORT then
1043
- next if @proxy_info[ :tund_addr ] || ( ctlmsg.size != 3 )
1044
- tund_port = ctlmsg[ 1, 2 ].unpack( 'n' ).first
1045
- puts "p#{ Process.pid } #{ Time.new } got tund port #{ tund_port }"
1046
- @proxy_info[ :tund_addr ] = Socket.sockaddr_in( tund_port, @proxyd_host )
1047
-
1048
- if @pending_srcs.any? then
1049
- puts "p#{ Process.pid } #{ Time.new } send pending sources"
1050
- @pending_srcs.each { | src | add_a_new_source( src ) }
1051
- @pending_srcs.clear
1052
- end
1053
- when PAIRED then
1054
- next if ctlmsg.size != 11
1055
- src_id, dst_id = ctlmsg[ 1, 10 ].unpack( 'Q>n' )
1056
- # puts "debug1 got paired #{ src_id } #{ dst_id }"
1057
- new_a_pre_tun( src_id, dst_id )
1058
- when RESOLVED then
1059
- next if ctlmsg.size <= 9
1060
- src_id = ctlmsg[ 1, 8 ].unpack( 'Q>' ).first
1061
- src = @srcs[ src_id ]
1062
- next if src.nil? || src.closed?
1063
- src_info = @src_infos[ src ]
1064
- ip = ctlmsg[ 9..-1 ]
1065
- puts "p#{ Process.pid } #{ Time.new } remote resolved #{ src_info[ :destination_domain ] } #{ ip }"
1066
- ip_info = Addrinfo.ip( ip )
1067
- deal_with_destination_ip( src, ip_info )
1068
- when TUND_FIN then
1069
- puts "p#{ Process.pid } #{ Time.new } got tund fin"
1070
- close_proxy( proxy )
1071
- return
1072
- when HEARTBEAT
1073
- # puts "debug1 #{ Time.new } got heartbeat"
1039
+ if @pending_srcs.any? then
1040
+ puts "p#{ Process.pid } #{ Time.new } send pending sources"
1041
+ @pending_srcs.each { | src | add_a_new_source( src ) }
1042
+ @pending_srcs.clear
1074
1043
  end
1044
+ when PAIRED then
1045
+ return if data.size != 11
1046
+ src_id, dst_id = data[ 1, 10 ].unpack( 'Q>n' )
1047
+ # puts "debug got paired #{ src_id } #{ dst_id }"
1048
+ @ctl_info[ :resends ].delete( [ A_NEW_SOURCE, src_id ].pack( 'CQ>' ) )
1049
+ @ctl_info[ :last_recv_at ] = Time.new
1050
+ new_tuns( src_id, dst_id )
1051
+ when UNKNOWN_CTL_ADDR then
1052
+ puts "p#{ Process.pid } #{ Time.new } got unknown ctl addr, close ctl"
1053
+ close_ctl( ctl )
1075
1054
  end
1076
1055
  end
1077
1056
 
@@ -1084,33 +1063,38 @@ module Girl
1084
1063
  return
1085
1064
  end
1086
1065
 
1066
+ src_info = @src_infos[ src ]
1067
+
1087
1068
  begin
1088
- data = src.read_nonblock( READ_SIZE )
1089
- rescue IO::WaitReadable, Errno::EINTR
1069
+ data = src.read_nonblock( 65535 )
1070
+ rescue IO::WaitReadable
1090
1071
  print 'r'
1091
1072
  return
1092
1073
  rescue Exception => e
1093
- # puts "debug1 read src #{ e.class }"
1094
- src_info = close_read_src( src )
1074
+ # puts "debug read src #{ e.class }"
1075
+ close_read_src( src )
1095
1076
  dst = src_info[ :dst ]
1096
1077
 
1097
1078
  if dst then
1098
1079
  set_dst_closing_write( dst )
1099
1080
  else
1100
- tun = src_info[ :tun ]
1101
- set_tun_closing_write( tun ) if tun
1081
+ atun = src_info[ :atun ]
1082
+
1083
+ if atun then
1084
+ set_atun_closing( atun )
1085
+ end
1102
1086
  end
1103
1087
 
1104
1088
  return
1105
1089
  end
1106
1090
 
1107
- src_info = @src_infos[ src ]
1091
+ # puts "debug read src #{ data.bytesize }"
1108
1092
  proxy_type = src_info[ :proxy_type ]
1109
1093
 
1110
1094
  case proxy_type
1111
1095
  when :uncheck then
1112
1096
  if data[ 0, 7 ] == 'CONNECT' then
1113
- # puts "debug1 CONNECT"
1097
+ # puts "debug CONNECT"
1114
1098
  domain_port = data.split( "\r\n" )[ 0 ].split( ' ' )[ 1 ]
1115
1099
 
1116
1100
  unless domain_port then
@@ -1119,7 +1103,7 @@ module Girl
1119
1103
  return
1120
1104
  end
1121
1105
  elsif data[ 0 ].unpack( 'C' ).first == 5 then
1122
- # puts "debug1 socks5 #{ data.inspect }"
1106
+ # puts "debug socks5 #{ data.inspect }"
1123
1107
 
1124
1108
  # https://tools.ietf.org/html/rfc1928
1125
1109
  #
@@ -1148,19 +1132,28 @@ module Girl
1148
1132
  src_info[ :proxy_type ] = :negotiation
1149
1133
  return
1150
1134
  else
1151
- # puts "debug1 not CONNECT #{ data.inspect }"
1135
+ # puts "debug not CONNECT #{ data.inspect }"
1152
1136
  host_line = data.split( "\r\n" ).find { | _line | _line[ 0, 6 ] == 'Host: ' }
1153
1137
 
1154
1138
  unless host_line then
1155
- # puts "debug1 not found host line"
1139
+ # puts "debug not found host line"
1156
1140
  add_closing_src( src )
1157
1141
  return
1158
1142
  end
1159
1143
 
1160
- data, domain_port = sub_http_request( data )
1144
+ lines = data.split( "\r\n" )
1145
+
1146
+ unless lines.empty? then
1147
+ method, url, proto = lines.first.split( ' ' )
1148
+
1149
+ if proto && url && proto[ 0, 4 ] == 'HTTP' && url[ 0, 7 ] == 'http://' then
1150
+ domain_port = url.split( '/' )[ 2 ]
1151
+ # puts "debug domain port #{ domain_port }"
1152
+ end
1153
+ end
1161
1154
 
1162
1155
  unless domain_port then
1163
- # puts "debug1 not HTTP"
1156
+ # puts "debug not HTTP"
1164
1157
  domain_port = host_line.split( ' ' )[ 1 ]
1165
1158
 
1166
1159
  unless domain_port then
@@ -1183,7 +1176,7 @@ module Girl
1183
1176
 
1184
1177
  resolve_domain( src, domain )
1185
1178
  when :checking then
1186
- # puts "debug1 add src rbuff before resolved #{ data.inspect }"
1179
+ # puts "debug add src rbuff before resolved #{ data.inspect }"
1187
1180
  src_info[ :rbuff ] << data
1188
1181
  when :negotiation then
1189
1182
  # +----+-----+-------+------+----------+----------+
@@ -1191,11 +1184,11 @@ module Girl
1191
1184
  # +----+-----+-------+------+----------+----------+
1192
1185
  # | 1 | 1 | X'00' | 1 | Variable | 2 |
1193
1186
  # +----+-----+-------+------+----------+----------+
1194
- # puts "debug1 negotiation #{ data.inspect }"
1187
+ # puts "debug negotiation #{ data.inspect }"
1195
1188
  ver, cmd, rsv, atyp = data[ 0, 4 ].unpack( 'C4' )
1196
1189
 
1197
1190
  if cmd == 1 then
1198
- # puts "debug1 socks5 CONNECT"
1191
+ # puts "debug socks5 CONNECT"
1199
1192
 
1200
1193
  if atyp == 1 then
1201
1194
  destination_host, destination_port = data[ 4, 6 ].unpack( 'Nn' )
@@ -1204,7 +1197,7 @@ module Girl
1204
1197
  destination_ip = destination_addrinfo.ip_address
1205
1198
  src_info[ :destination_domain ] = destination_ip
1206
1199
  src_info[ :destination_port ] = destination_port
1207
- # puts "debug1 IP V4 address #{ destination_addrinfo.ip_unpack.inspect }"
1200
+ # puts "debug IP V4 address #{ destination_addrinfo.ip_unpack.inspect }"
1208
1201
  deal_with_destination_ip( src, destination_addrinfo )
1209
1202
  elsif atyp == 3 then
1210
1203
  domain_len = data[ 4 ].unpack( 'C' ).first
@@ -1214,7 +1207,7 @@ module Girl
1214
1207
  port = data[ ( 5 + domain_len ), 2 ].unpack( 'n' ).first
1215
1208
  src_info[ :destination_domain ] = domain
1216
1209
  src_info[ :destination_port ] = port
1217
- # puts "debug1 DOMAINNAME #{ domain } #{ port }"
1210
+ # puts "debug DOMAINNAME #{ domain } #{ port }"
1218
1211
  resolve_domain( src, domain )
1219
1212
  end
1220
1213
  end
@@ -1222,35 +1215,21 @@ module Girl
1222
1215
  puts "p#{ Process.pid } #{ Time.new } socks5 cmd #{ cmd } not implement"
1223
1216
  end
1224
1217
  when :tunnel then
1225
- tun = src_info[ :tun ]
1226
-
1227
- if tun then
1228
- unless tun.closed? then
1229
- unless src_info[ :is_connect ] then
1230
- data, _ = sub_http_request( data )
1231
- end
1218
+ atun = src_info[ :atun ]
1232
1219
 
1233
- # puts "debug2 add tun.wbuff #{ data.bytesize }"
1234
- add_tun_wbuff( tun, data )
1235
- end
1220
+ if atun then
1221
+ add_atun_wbuff( atun, pack_a_chunk( data ) )
1236
1222
  else
1237
- # puts "debug1 tun not ready, save data to src.rbuff"
1223
+ # puts "debug add src.rbuff #{ data.bytesize }"
1238
1224
  add_src_rbuff( src, data )
1239
1225
  end
1240
1226
  when :direct then
1241
1227
  dst = src_info[ :dst ]
1242
1228
 
1243
1229
  if dst then
1244
- unless dst.closed? then
1245
- unless src_info[ :is_connect ] then
1246
- data, _ = sub_http_request( data )
1247
- end
1248
-
1249
- # puts "debug2 add dst.wbuff #{ data.bytesize }"
1250
- add_dst_wbuff( dst, data )
1251
- end
1230
+ add_dst_wbuff( dst, data )
1252
1231
  else
1253
- # puts "debug1 dst not ready, save data to src.rbuff"
1232
+ # puts "debug add src.rbuff #{ data.bytesize }"
1254
1233
  add_src_rbuff( src, data )
1255
1234
  end
1256
1235
  end
@@ -1265,82 +1244,110 @@ module Girl
1265
1244
  return
1266
1245
  end
1267
1246
 
1247
+ dst_info = @dst_infos[ dst ]
1248
+ src = dst_info[ :src ]
1249
+
1268
1250
  begin
1269
- data = dst.read_nonblock( READ_SIZE )
1270
- rescue IO::WaitReadable, Errno::EINTR
1251
+ data = dst.read_nonblock( 65535 )
1252
+ rescue IO::WaitReadable
1271
1253
  print 'r'
1272
1254
  return
1273
1255
  rescue Exception => e
1274
- # puts "debug1 read dst #{ e.class }"
1275
- dst_info = close_read_dst( dst )
1276
- src = dst_info[ :src ]
1256
+ # puts "debug read dst #{ e.class }"
1257
+ close_read_dst( dst )
1277
1258
  set_src_closing_write( src )
1278
1259
  return
1279
1260
  end
1280
1261
 
1281
- dst_info = @dst_infos[ dst ]
1282
- src = dst_info[ :src ]
1262
+ # puts "debug read dst #{ data.bytesize }"
1283
1263
  add_src_wbuff( src, data )
1284
1264
  end
1285
1265
 
1286
1266
  ##
1287
- # read tun
1267
+ # read btun
1288
1268
  #
1289
- def read_tun( tun )
1290
- if tun.closed? then
1291
- puts "p#{ Process.pid } #{ Time.new } read tun but tun closed?"
1269
+ def read_btun( btun )
1270
+ if btun.closed? then
1271
+ puts "p#{ Process.pid } #{ Time.new } read btun but btun closed?"
1292
1272
  return
1293
1273
  end
1294
1274
 
1275
+ btun_info = @btun_infos[ btun ]
1276
+ src = btun_info[ :src ]
1277
+
1295
1278
  begin
1296
- data = tun.read_nonblock( READ_SIZE )
1297
- rescue IO::WaitReadable
1298
- return
1299
- rescue Errno::EINTR
1300
- puts e.class
1301
- return
1279
+ data = btun.read_nonblock( READ_SIZE )
1302
1280
  rescue Exception => e
1303
- # puts "debug1 read tun #{ e.class }"
1304
- tun_info = close_read_tun( tun )
1305
- src = tun_info[ :src ]
1306
- set_src_closing_write( src )
1307
- return
1308
- end
1281
+ # puts "debug read btun #{ btun_info[ :im ] } #{ e.class }"
1282
+ close_btun( btun )
1309
1283
 
1310
- tun_info = @tun_infos[ tun ]
1311
- src = tun_info[ :src ]
1312
- # puts "debug2 add src.wbuff #{ data.bytesize }"
1313
- add_src_wbuff( src, data )
1314
- end
1284
+ if src then
1285
+ set_src_closing_write( src )
1286
+ end
1315
1287
 
1316
- ##
1317
- # write proxy
1318
- #
1319
- def write_proxy( proxy )
1320
- if proxy.closed? then
1321
- puts "p#{ Process.pid } #{ Time.new } write proxy but proxy closed?"
1322
1288
  return
1323
1289
  end
1324
1290
 
1325
- if @proxy_info[ :ctlmsgs ].any? then
1326
- data = @proxy_info[ :ctlmsgs ].map{ | ctlmsg | "#{ ctlmsg }#{ SEPARATE }" }.join
1291
+ until data.empty? do
1292
+ wait_bytes = btun_info[ :wait_bytes ]
1327
1293
 
1328
- # 写入
1329
- begin
1330
- written = proxy.write( data )
1331
- rescue IO::WaitWritable, Errno::EINTR
1332
- print 'w'
1333
- return
1334
- rescue Exception => e
1335
- # puts "debug1 write proxy #{ e.class }"
1336
- close_proxy( proxy )
1337
- return
1294
+ if wait_bytes > 0 then
1295
+ len = wait_bytes
1296
+ # puts "debug wait bytes #{ len }"
1297
+ else
1298
+ lbuff = btun_info[ :lbuff ]
1299
+
1300
+ if lbuff.empty? then
1301
+ # 长度缓存为空,从读到的流量里取长度
1302
+ # 两个字节以下,记进长度缓存
1303
+ if data.bytesize <= 2 then
1304
+ # puts "debug set btun.lbuff #{ data.inspect }"
1305
+ btun_info[ :lbuff ] = data
1306
+ return
1307
+ end
1308
+
1309
+ len = data[ 0, 2 ].unpack( 'n' ).first
1310
+ data = data[ 2..-1 ]
1311
+ elsif lbuff.bytesize == 1 then
1312
+ # 长度缓存记有一个字节,补一个字节
1313
+ lbuff = "#{ lbuff }#{ data[ 0 ] }"
1314
+
1315
+ if data.bytesize == 1 then
1316
+ # puts "debug add btun.lbuff a byte #{ data.inspect }"
1317
+ btun_info[ :lbuff ] = lbuff
1318
+ return
1319
+ end
1320
+
1321
+ # 使用长度缓存
1322
+ len = lbuff.unpack( 'n' ).first
1323
+ btun_info[ :lbuff ].clear
1324
+ data = data[ 1..-1 ]
1325
+ else
1326
+ # 使用长度缓存
1327
+ len = lbuff.unpack( 'n' ).first
1328
+ btun_info[ :lbuff ].clear
1329
+ end
1338
1330
  end
1339
1331
 
1340
- @proxy_info[ :ctlmsgs ].clear
1341
- end
1332
+ chunk = data[ 0, len ]
1333
+ chunk_size = chunk.bytesize
1342
1334
 
1343
- @writes.delete( proxy )
1335
+ if chunk_size == len then
1336
+ # 取完整了
1337
+ chunk = @custom.decode( "#{ btun_info[ :rbuff ] }#{ chunk }" )
1338
+ # puts "debug decode and add src.wbuff #{ chunk.bytesize }"
1339
+ add_src_wbuff( src, chunk )
1340
+ btun_info[ :rbuff ].clear
1341
+ btun_info[ :wait_bytes ] = 0
1342
+ else
1343
+ # 暂存
1344
+ # puts "debug add btun.rbuff #{ chunk_size } wait bytes #{ len - chunk_size }"
1345
+ btun_info[ :rbuff ] << chunk
1346
+ btun_info[ :wait_bytes ] = len - chunk_size
1347
+ end
1348
+
1349
+ data = data[ chunk_size..-1 ]
1350
+ end
1344
1351
  end
1345
1352
 
1346
1353
  ##
@@ -1370,24 +1377,27 @@ module Girl
1370
1377
  # 写入
1371
1378
  begin
1372
1379
  written = src.write_nonblock( data )
1373
- rescue IO::WaitWritable, Errno::EINTR
1380
+ rescue IO::WaitWritable
1374
1381
  print 'w'
1375
1382
  return
1376
1383
  rescue Exception => e
1377
- # puts "debug1 write src #{ e.class }"
1384
+ # puts "debug write src #{ e.class }"
1378
1385
  close_write_src( src )
1379
1386
 
1380
1387
  if dst then
1381
1388
  close_read_dst( dst )
1382
1389
  else
1383
- tun = src_info[ :tun ]
1384
- close_read_tun( tun ) if tun
1390
+ btun = src_info[ :btun ]
1391
+
1392
+ if btun then
1393
+ close_btun( btun )
1394
+ end
1385
1395
  end
1386
1396
 
1387
1397
  return
1388
1398
  end
1389
1399
 
1390
- # puts "debug2 written src #{ written }"
1400
+ # puts "debug write src #{ written }"
1391
1401
  data = data[ written..-1 ]
1392
1402
  src_info[ :wbuff ] = data
1393
1403
  end
@@ -1419,11 +1429,11 @@ module Girl
1419
1429
  # 写入
1420
1430
  begin
1421
1431
  written = dst.write_nonblock( data )
1422
- rescue IO::WaitWritable, Errno::EINTR
1432
+ rescue IO::WaitWritable
1423
1433
  print 'w'
1424
1434
  return
1425
1435
  rescue Exception => e
1426
- # puts "debug1 write dst #{ e.class }"
1436
+ # puts "debug write dst #{ e.class }"
1427
1437
  close_write_dst( dst )
1428
1438
  close_read_src( src )
1429
1439
  return
@@ -1439,24 +1449,24 @@ module Girl
1439
1449
  end
1440
1450
 
1441
1451
  ##
1442
- # write tun
1452
+ # write atun
1443
1453
  #
1444
- def write_tun( tun )
1445
- if tun.closed? then
1446
- puts "p#{ Process.pid } #{ Time.new } write tun but tun closed?"
1454
+ def write_atun( atun )
1455
+ if atun.closed? then
1456
+ puts "p#{ Process.pid } #{ Time.new } write atun but atun closed?"
1447
1457
  return
1448
1458
  end
1449
1459
 
1450
- tun_info = @tun_infos[ tun ]
1451
- src = tun_info[ :src ]
1452
- data = tun_info[ :wbuff ]
1460
+ atun_info = @atun_infos[ atun ]
1461
+ src = atun_info[ :src ]
1462
+ data = atun_info[ :wbuff ]
1453
1463
 
1454
1464
  # 写前为空,处理关闭写
1455
1465
  if data.empty? then
1456
- if tun_info[ :closing_write ] then
1457
- close_write_tun( tun )
1466
+ if atun_info[ :closing ] then
1467
+ close_atun( atun )
1458
1468
  else
1459
- @writes.delete( tun )
1469
+ @writes.delete( atun )
1460
1470
  end
1461
1471
 
1462
1472
  return
@@ -1464,23 +1474,20 @@ module Girl
1464
1474
 
1465
1475
  # 写入
1466
1476
  begin
1467
- written = tun.write_nonblock( data )
1468
- rescue IO::WaitReadable
1469
- # OpenSSL::SSL::SSLErrorWaitReadable
1470
- return
1471
- rescue IO::WaitWritable, Errno::EINTR
1477
+ written = atun.write_nonblock( data )
1478
+ rescue IO::WaitWritable
1472
1479
  print 'w'
1473
1480
  return
1474
1481
  rescue Exception => e
1475
- # puts "debug1 write tun #{ e.class }"
1476
- close_write_tun( tun )
1482
+ # puts "debug write atun #{ e.class }"
1483
+ close_atun( atun )
1477
1484
  close_read_src( src )
1478
1485
  return
1479
1486
  end
1480
1487
 
1481
- # puts "debug2 written tun #{ written }"
1488
+ # puts "debug write atun #{ written }"
1482
1489
  data = data[ written..-1 ]
1483
- tun_info[ :wbuff ] = data
1490
+ atun_info[ :wbuff ] = data
1484
1491
 
1485
1492
  unless src.closed? then
1486
1493
  src_info = @src_infos[ src ]
@@ -1489,112 +1496,30 @@ module Girl
1489
1496
  end
1490
1497
 
1491
1498
  ##
1492
- # write pre proxy
1499
+ # write btun
1493
1500
  #
1494
- def write_pre_proxy( pre_proxy )
1495
- if pre_proxy.closed? then
1496
- puts "p#{ Process.pid } #{ Time.new } write pre proxy but pre proxy closed?"
1501
+ def write_btun( btun )
1502
+ if btun.closed? then
1503
+ puts "p#{ Process.pid } #{ Time.new } write btun but btun closed?"
1497
1504
  return
1498
1505
  end
1499
1506
 
1500
- proxy = OpenSSL::SSL::SSLSocket.new pre_proxy
1507
+ btun_info = @btun_infos[ btun ]
1508
+ data = btun_info[ :wbuff ]
1501
1509
 
1510
+ # 写入dst id
1502
1511
  begin
1503
- proxy.connect_nonblock
1504
- rescue IO::WaitReadable
1505
- rescue IO::WaitWritable
1512
+ written = btun.write( data )
1506
1513
  rescue Exception => e
1507
- puts "p#{ Process.pid } #{ Time.new } proxy connect #{ e.class }, close proxy"
1508
- proxy.close
1509
- close_pre_proxy( pre_proxy )
1510
- return
1511
- end
1512
-
1513
- @proxy = proxy
1514
- @proxy_info = {
1515
- ctlmsgs: [], # ctlmsg
1516
- tund_addr: nil, # tund地址
1517
- created_at: Time.new, # 创建时间
1518
- last_recv_at: nil, # 上一次收到流量的时间
1519
- closing: false # 是否准备关闭
1520
- }
1521
- add_read( proxy, :proxy )
1522
- hello = @custom.hello
1523
- puts "p#{ Process.pid } #{ Time.new } tunnel #{ hello.inspect }"
1524
- data = "#{ [ HELLO ].pack( 'C' ) }#{ hello }"
1525
- add_ctlmsg( data )
1526
-
1527
- @roles.delete( pre_proxy )
1528
- @writes.delete( pre_proxy )
1529
- end
1530
-
1531
- ##
1532
- # write pre tun
1533
- #
1534
- def write_pre_tun( pre_tun )
1535
- if pre_tun.closed? then
1536
- puts "p#{ Process.pid } #{ Time.new } write pre tun but pre tun closed?"
1537
- return
1538
- end
1539
-
1540
- pre_tun_info = @pre_tun_infos[ pre_tun ]
1541
- src = pre_tun_info[ :src ]
1542
-
1543
- if src.closed? then
1544
- puts "p#{ Process.pid } #{ Time.new } new a tun but src closed?"
1545
- return
1546
- end
1547
-
1548
- tun = OpenSSL::SSL::SSLSocket.new pre_tun
1549
-
1550
- begin
1551
- tun.connect_nonblock
1552
- rescue IO::WaitReadable
1553
- rescue IO::WaitWritable
1554
- rescue Exception => e
1555
- puts "p#{ Process.pid } #{ Time.new } tun connect #{ e.class }, close tun"
1556
- tun.close
1557
- close_pre_tun( pre_tun )
1514
+ # puts "debug write btun #{ e.class }"
1515
+ src = btun_info[ :src ]
1516
+ close_btun( btun )
1517
+ add_closing_src( src )
1558
1518
  return
1559
1519
  end
1560
1520
 
1561
- src_info = @src_infos[ src ]
1562
- dst_id = src_info[ :dst_id ]
1563
- # puts "debug1 set tun.wbuff #{ dst_id }"
1564
- data = [ dst_id ].pack( 'n' )
1565
-
1566
- unless src_info[ :rbuff ].empty? then
1567
- # puts "debug1 move src.rbuff to tun.wbuff"
1568
- data << src_info[ :rbuff ]
1569
- end
1570
-
1571
- domain = src_info[ :destination_domain ]
1572
- @tun_infos[ tun ] = {
1573
- pre_tun: pre_tun, # 对应pre tun
1574
- src: src, # 对应src
1575
- domain: domain, # 目的地
1576
- wbuff: data, # 写前
1577
- closing_write: false, # 准备关闭写
1578
- close_read: false, # 已经关闭读
1579
- close_write: false # 已经关闭写
1580
- }
1581
-
1582
- src_info[ :tun ] = tun
1583
- add_read( tun, :tun )
1584
- add_write( tun )
1585
-
1586
- if src_info[ :proxy_proto ] == :http then
1587
- if src_info[ :is_connect ] then
1588
- # puts "debug1 add src.wbuff http ok"
1589
- add_src_wbuff( src, HTTP_OK )
1590
- end
1591
- elsif src_info[ :proxy_proto ] == :socks5 then
1592
- add_socks5_conn_reply( src )
1593
- end
1594
-
1595
- @pre_tun_infos.delete( pre_tun )
1596
- @roles.delete( pre_tun )
1597
- @writes.delete( pre_tun )
1521
+ # puts "debug write btun #{ written }"
1522
+ @writes.delete( btun )
1598
1523
  end
1599
1524
 
1600
1525
  end