girl 0.86.0 → 0.87.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of girl might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48f438a56f35bb4fd0fbb76e57f08b5ea1a6e8890b8a2b7542881b1f69e89461
4
- data.tar.gz: 8ad2943b900e91f8a6e29306fe29249d467374f738261daadaaa429961370206
3
+ metadata.gz: 590ceead2e46e0803325aff199ec4fa4610a554f873ad58e91f83e8cba7bd4a9
4
+ data.tar.gz: 3034b02ee1ddf592a67446d82a3f974f2439aef9f380f20b39c96aa943a4a7ab
5
5
  SHA512:
6
- metadata.gz: 98512a3678ebde91bff827995447765c57c558f885313d05ecd8c831e85354a9ea81beb5ff038c18787b1bd0c15fe88317b85a3b6e84458a5709bcf59b027fff
7
- data.tar.gz: 263aff6f7b79025d5404f6b6e4a68b01dfa899df0af4556b0085f72e9bb3227d6423be77e3c1cd12445fb1c9727c426be9750a9f7cea72d112b72c59702917a7
6
+ metadata.gz: 27d1dd5ef6d6f4d29c1916af5c10c8eb694e7cbf11f2f8518a6d4a3ebd0d368aa92518a9c5c0f91079f9291c67b1050be16db3f0154d7fb710f55d818ca75576
7
+ data.tar.gz: ae5ab8293caf167146784342a93e059ef03a201dbd1a1a3df6bbe206321f95b13526e78713ca77903e3be44873ce02474c4d3260187fcd85c993206401fef586
@@ -1,33 +1,33 @@
1
1
  module Girl
2
- PACK_SIZE = 1328 # 包大小 1400(console MTU) - 8(PPPoE header) - 40(IPv6 header) - 8(UDP header) - 8(pack id) - 8(src id) = 1328
3
- CHUNK_SIZE = PACK_SIZE * 1000 # 块大小
4
- WBUFFS_LIMIT = 1000 # 写前上限,超过上限结一个块
5
- WMEMS_LIMIT = 100_000 # 写后上限,达到上限暂停写
6
- RESUME_BELOW = 50_000 # 降到多少以下恢复写
7
- EXPIRE_NEW = 10 # 创建之后多久没有流量进来,过期
8
- EXPIRE_AFTER = 300 # 多久没有新流量,过期
9
- CHECK_EXPIRE_INTERVAL = 30 # 检查过期间隔
10
- CHECK_STATUS_INTERVAL = 0.5 # 发送状态间隔
11
- SEND_STATUS_UNTIL = 10 # 持续的告之对面状态,直到没有流量往来,持续多少秒
12
- MISS_RANGE_LIMIT = 500 # miss段上限,达到上限忽略要后面的段
13
- RESENDING_LIMIT = 5000 # 重传队列上限
14
- CONFUSE_UNTIL = 5 # 混淆前几个包
15
- RESOLV_CACHE_EXPIRE = 300 # dns查询结果缓存多久过期
16
- TUND_PORT = 1
17
- HEARTBEAT = 2
18
- A_NEW_SOURCE = 3
19
- PAIRED = 4
20
- DEST_STATUS = 5
21
- SOURCE_STATUS = 6
22
- MISS = 7
23
- FIN1 = 8
24
- GOT_FIN1 = 9
25
- FIN2 = 10
26
- GOT_FIN2 = 11
27
- TUND_FIN = 12
28
- TUN_FIN = 13
29
- IP_CHANGED = 14
30
- HTTP_OK = "HTTP/1.1 200 OK\r\n\r\n"
2
+ PACK_SIZE = 1328 # 包大小 1400(console MTU) - 8(PPPoE header) - 40(IPv6 header) - 8(UDP header) - 8(pack id) - 8(src id) = 1328
3
+ READ_SIZE = PACK_SIZE * 100 # 一次读多少
4
+ WMEMS_LIMIT = 100_000 # 写后上限,超过上限暂停读src/dst
5
+ RESUME_BELOW = 50_000 # 降到多少以下恢复读
6
+ EXPIRE_NEW = 10 # 创建之后多久没有流量进来,过期
7
+ EXPIRE_AFTER = 300 # 多久没有新流量,过期
8
+ CHECK_EXPIRE_INTERVAL = 30 # 检查过期间隔
9
+ CHECK_STATUS_INTERVAL = 0.5 # 发送状态间隔
10
+ SEND_STATUS_UNTIL = 10 # 持续的告之对面状态,直到没有流量往来,持续多少秒
11
+ MULTI_MISS_SIZE = 80 # 几个miss段打一个包
12
+ MISS_RANGE_LIMIT = MULTI_MISS_SIZE * 10 # miss段上限,达到上限忽略要后面的段
13
+ CONFUSE_UNTIL = 5 # 混淆前几个包
14
+ RESOLV_CACHE_EXPIRE = 300 # dns查询结果缓存多久过期
15
+ TUND_PORT = 1
16
+ HEARTBEAT = 2
17
+ A_NEW_SOURCE = 3
18
+ PAIRED = 4
19
+ DEST_STATUS = 5
20
+ SOURCE_STATUS = 6
21
+ MISS = 7
22
+ FIN1 = 8
23
+ GOT_FIN1 = 9
24
+ FIN2 = 10
25
+ GOT_FIN2 = 11
26
+ TUND_FIN = 12
27
+ TUN_FIN = 13
28
+ IP_CHANGED = 14
29
+ MULTI_MISS = 15
30
+ HTTP_OK = "HTTP/1.1 200 OK\r\n\r\n"
31
31
  # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
32
32
  RESERVED_ROUTE = <<EOF
33
33
  0.0.0.0/8
@@ -36,6 +36,7 @@ require 'socket'
36
36
  # 12 tund fin
37
37
  # 13 tun fin
38
38
  # 14 tun ip changed
39
+ # 15 multi miss -> Q>/n: src id / dst port -> Q>: pack id begin -> Q>: pack id end -> Q>*
39
40
  #
40
41
  # Q>: 1+ pack_id -> Q>/n: src id / dst port -> traffic
41
42
  #
@@ -74,8 +75,6 @@ module Girl
74
75
  # "proxyd_port": 6060, // 代理服务,远端端口
75
76
  # "direct_path": "girl.direct.txt", // 直连ip段
76
77
  # "remote_path": "girl.remote.txt", // 交给远端解析的域名列表
77
- # "proxy_tmp_dir": "/tmp/girl.proxy", // 近端缓存根路径
78
- # "proxyd_tmp_dir": "/tmp/girl.proxyd", // 远端缓存根路径
79
78
  # "im": "girl", // 标识,用来识别近端
80
79
  # "worker_count": 4 // 子进程数,默认取cpu个数
81
80
  # }
@@ -85,7 +84,6 @@ module Girl
85
84
  proxyd_port = conf[ :proxyd_port ]
86
85
  direct_path = conf[ :direct_path ]
87
86
  remote_path = conf[ :remote_path ]
88
- proxy_tmp_dir = conf[ :proxy_tmp_dir ]
89
87
  im = conf[ :im ]
90
88
  worker_count = conf[ :worker_count ]
91
89
 
@@ -121,32 +119,6 @@ module Girl
121
119
  remotes = IO.binread( remote_path ).split( "\n" ).map { | line | line.strip }
122
120
  end
123
121
 
124
- unless proxy_tmp_dir
125
- proxy_tmp_dir = '/tmp/girl.proxy'
126
- end
127
-
128
- unless File.exist?( proxy_tmp_dir )
129
- Dir.mkdir( proxy_tmp_dir )
130
- end
131
-
132
- src_chunk_dir = File.join( proxy_tmp_dir, 'src.chunk' )
133
-
134
- unless Dir.exist?( src_chunk_dir )
135
- Dir.mkdir( src_chunk_dir )
136
- end
137
-
138
- dst_chunk_dir = File.join( proxy_tmp_dir, 'dst.chunk' )
139
-
140
- unless Dir.exist?( dst_chunk_dir )
141
- Dir.mkdir( dst_chunk_dir )
142
- end
143
-
144
- tun_chunk_dir = File.join( proxy_tmp_dir, 'tun.chunk' )
145
-
146
- unless Dir.exist?( tun_chunk_dir )
147
- Dir.mkdir( tun_chunk_dir )
148
- end
149
-
150
122
  unless im
151
123
  im = 'girl'
152
124
  end
@@ -164,16 +136,12 @@ module Girl
164
136
  puts "proxyd port #{ proxyd_port }"
165
137
  puts "#{ direct_path } #{ directs.size } directs"
166
138
  puts "#{ remote_path } #{ remotes.size } remotes"
167
- puts "src chunk dir #{ src_chunk_dir }"
168
- puts "dst chunk dir #{ dst_chunk_dir }"
169
- puts "tun chunk dir #{ tun_chunk_dir }"
170
139
  puts "im #{ im }"
171
140
  puts "worker count #{ worker_count }"
172
141
 
173
142
  names = %w[
174
143
  PACK_SIZE
175
- CHUNK_SIZE
176
- WBUFFS_LIMIT
144
+ READ_SIZE
177
145
  WMEMS_LIMIT
178
146
  RESUME_BELOW
179
147
  EXPIRE_NEW
@@ -181,8 +149,8 @@ module Girl
181
149
  CHECK_EXPIRE_INTERVAL
182
150
  CHECK_STATUS_INTERVAL
183
151
  SEND_STATUS_UNTIL
152
+ MULTI_MISS_SIZE
184
153
  MISS_RANGE_LIMIT
185
- RESENDING_LIMIT
186
154
  CONFUSE_UNTIL
187
155
  RESOLV_CACHE_EXPIRE
188
156
  ]
@@ -200,7 +168,7 @@ module Girl
200
168
  worker_count.times do | i |
201
169
  workers << fork do
202
170
  $0 = 'girl proxy worker'
203
- worker = Girl::ProxyWorker.new( proxy_port, proxyd_host, proxyd_port, directs, remotes, src_chunk_dir, dst_chunk_dir, tun_chunk_dir, im )
171
+ worker = Girl::ProxyWorker.new( proxy_port, proxyd_host, proxyd_port, directs, remotes, im )
204
172
 
205
173
  Signal.trap( :TERM ) do
206
174
  puts "w#{ i } exit"
@@ -224,7 +192,7 @@ module Girl
224
192
 
225
193
  Process.waitall
226
194
  else
227
- Girl::ProxyWorker.new( proxy_port, proxyd_host, proxyd_port, directs, remotes, src_chunk_dir, dst_chunk_dir, tun_chunk_dir, im ).looping
195
+ Girl::ProxyWorker.new( proxy_port, proxyd_host, proxyd_port, directs, remotes, im ).looping
228
196
  end
229
197
  end
230
198
 
@@ -4,18 +4,16 @@ module Girl
4
4
  ##
5
5
  # initialize
6
6
  #
7
- def initialize( proxy_port, proxyd_host, proxyd_port, directs, remotes, src_chunk_dir, dst_chunk_dir, tun_chunk_dir, im )
7
+ def initialize( proxy_port, proxyd_host, proxyd_port, directs, remotes, im )
8
8
  @proxyd_host = proxyd_host
9
9
  @proxyd_addr = Socket.sockaddr_in( proxyd_port, proxyd_host )
10
10
  @directs = directs
11
11
  @remotes = remotes
12
- @src_chunk_dir = src_chunk_dir
13
- @dst_chunk_dir = dst_chunk_dir
14
- @tun_chunk_dir = tun_chunk_dir
15
12
  @custom = Girl::ProxyCustom.new( im )
16
13
  @mutex = Mutex.new
17
14
  @reads = []
18
15
  @writes = []
16
+ @pause_srcs = []
19
17
  @roles = {} # sock => :dotr / :proxy / :src / :dst / :tun
20
18
  @src_infos = {} # src => {}
21
19
  @dst_infos = {} # dst => {}
@@ -106,20 +104,31 @@ module Girl
106
104
  if is_expired
107
105
  puts "p#{ Process.pid } #{ Time.new } expire tun"
108
106
  set_is_closing( @tun )
107
+ need_trigger = true
109
108
  else
110
109
  data = [ 0, HEARTBEAT, rand( 128 ) ].pack( 'Q>CC' )
111
110
  # puts "debug1 #{ Time.new } heartbeat"
112
- add_tun_ctlmsg( data )
113
-
114
- @tun_info[ :src_exts ].each do | src_id, src_ext |
115
- if src_ext[ :src ].closed? && ( now - src_ext[ :last_continue_at ] > EXPIRE_AFTER )
116
- puts "p#{ Process.pid } #{ Time.new } expire src ext #{ src_ext[ :destination_domain ] }"
117
- del_src_ext( src_id )
111
+ send_data( @tun, data, @tun_info[ :tund_addr ] )
112
+ del_src_ids = []
113
+
114
+ @tun_info[ :srcs ].each do | src_id, src |
115
+ if src.closed?
116
+ src_info = @src_infos[ src ]
117
+
118
+ if src_info && ( now - src_info[ :last_continue_at ] > EXPIRE_AFTER )
119
+ puts "p#{ Process.pid } #{ Time.new } expire src ext #{ src_info[ :destination_domain ] }"
120
+ @tun_info[ :wmems ].delete_if { | src_id_and_pack_id, _ | src_id_and_pack_id.first == src_id }
121
+ @tun_info[ :src_ids ].delete( src_info[ :dst_id ] )
122
+ @src_infos.delete( src )
123
+ del_src_ids << src_id
124
+ end
118
125
  end
119
126
  end
120
- end
121
127
 
122
- need_trigger = true
128
+ if del_src_ids.any?
129
+ @tun_info[ :srcs ].delete_if { | src_id, _ | del_src_ids.include?( src_id ) }
130
+ end
131
+ end
123
132
  end
124
133
 
125
134
  @src_infos.each do | src, src_info |
@@ -156,28 +165,30 @@ module Girl
156
165
 
157
166
  @mutex.synchronize do
158
167
  if @tun && !@tun.closed? && @tun_info[ :tund_addr ]
159
- need_trigger = false
160
-
161
- if @tun_info[ :src_exts ].any?
168
+ if @tun_info[ :srcs ].any?
162
169
  now = Time.new
163
170
 
164
- @tun_info[ :src_exts ].each do | src_id, src_ext |
165
- if src_ext[ :dst_port ] && ( now - src_ext[ :last_continue_at ] < SEND_STATUS_UNTIL )
166
- data = [ 0, SOURCE_STATUS, src_id, src_ext[ :relay_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
167
- add_tun_ctlmsg( data )
168
- need_trigger = true
171
+ @tun_info[ :srcs ].each do | src_id, src |
172
+ src_info = @src_infos[ src ]
173
+
174
+ if src_info && src_info[ :dst_id ] && ( now - src_info[ :last_continue_at ] < SEND_STATUS_UNTIL )
175
+ data = [ 0, SOURCE_STATUS, src_id, src_info[ :biggest_pack_id ], src_info[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
176
+ send_data( @tun, data, @tun_info[ :tund_addr ] )
169
177
  end
170
178
  end
171
179
  end
172
180
 
173
- if @tun_info[ :paused ] && ( @tun_info[ :src_exts ].map{ | _, src_ext | src_ext[ :wmems ].size }.sum < RESUME_BELOW )
174
- puts "p#{ Process.pid } #{ Time.new } resume tun"
175
- @tun_info[ :paused ] = false
176
- add_write( @tun )
177
- need_trigger = true
178
- end
181
+ if @pause_srcs.any? && ( @tun_info[ :wmems ].size < RESUME_BELOW )
182
+ @pause_srcs.each do | src |
183
+ src_info = @src_infos[ src ]
184
+
185
+ if src_info
186
+ puts "p#{ Process.pid } #{ Time.new } resume src #{ src_info[ :destination_domain ] }"
187
+ add_read( src )
188
+ end
189
+ end
179
190
 
180
- if need_trigger
191
+ @pause_srcs.clear
181
192
  next_tick
182
193
  end
183
194
  end
@@ -186,24 +197,58 @@ module Girl
186
197
  end
187
198
  end
188
199
 
189
- ##
190
- # loop send a new source
191
- #
192
- def loop_send_a_new_source( src_ext, data )
200
+ def loop_send_hello
201
+ data = @custom.hello
202
+
193
203
  Thread.new do
194
- EXPIRE_NEW.times do
195
- if src_ext[ :src ].closed? || src_ext[ :dst_port ]
196
- # puts "debug1 break loop send a new source #{ src_ext[ :dst_port ] }"
204
+ EXPIRE_NEW.times do | i |
205
+ if @tun.closed? || @tun_info[ :tund_addr ]
206
+ # puts "debug1 break loop send hello"
197
207
  break
198
208
  end
199
209
 
200
210
  @mutex.synchronize do
201
- # puts "debug1 send a new source #{ data.inspect }"
202
- add_tun_ctlmsg( data )
203
- next_tick
211
+ msg = i >= 1 ? "resend hello #{ i }" : "hello i'm tun"
212
+ puts "p#{ Process.pid } #{ Time.new } #{ msg }"
213
+ # puts "debug1 #{ data.inspect }"
214
+
215
+ send_data( @tun, data, @proxyd_addr )
204
216
  end
205
217
 
206
- sleep 1
218
+ sleep CHECK_STATUS_INTERVAL
219
+ end
220
+ end
221
+ end
222
+
223
+ ##
224
+ # loop send a new source
225
+ #
226
+ def loop_send_a_new_source( src )
227
+ src_info = @src_infos[ src ]
228
+
229
+ if src_info && @tun_info[ :tund_addr ]
230
+ destination_domain = src_info[ :destination_domain ]
231
+ destination_port = src_info[ :destination_port ]
232
+ domain_port = [ destination_domain, destination_port ].join( ':' )
233
+ data = [ [ 0, A_NEW_SOURCE, src_info[ :id ] ].pack( 'Q>CQ>' ), @custom.encode( domain_port ) ].join
234
+
235
+ Thread.new do
236
+ EXPIRE_NEW.times do | i |
237
+ if src.closed? || src_info[ :dst_id ]
238
+ # puts "debug1 break loop send a new source #{ src_info[ :dst_port ] }"
239
+ break
240
+ end
241
+
242
+ @mutex.synchronize do
243
+ if i >= 1
244
+ puts "p#{ Process.pid } #{ Time.new } resend a new source #{ domain_port } #{ i }"
245
+ end
246
+
247
+ send_data( @tun, data, @tun_info[ :tund_addr ] )
248
+ end
249
+
250
+ sleep CHECK_STATUS_INTERVAL
251
+ end
207
252
  end
208
253
  end
209
254
  end
@@ -304,15 +349,12 @@ module Girl
304
349
  port = tun.local_address.ip_port
305
350
  tun_info = {
306
351
  port: port, # 端口
307
- ctlmsg_rbuffs: [], # 还没配上tund,暂存的ctlmsg
308
- ctlmsgs: [], # [ to_addr, data ]
309
- wbuffs: [], # 写前缓存 [ src_id, pack_id, data ]
310
- caches: [], # 块读出缓存 [ src_id, pack_id, data ]
311
- chunks: [], # 块队列 filename
312
- spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
352
+ pending_sources: [], # 还没配上tund,暂存的src
353
+ wbuffs: [], # 写前 [ src_id, pack_id, data ]
354
+ wmems: {}, # 写后 [ src_id, pack_id ] => data
313
355
  tund_addr: nil, # tund地址
314
- src_exts: {}, # src额外信息 src_id => {}
315
- src_ids: {}, # dst_port => src_id
356
+ srcs: {}, # src_id => src
357
+ src_ids: {}, # dst_id => src_id
316
358
  paused: false, # 是否暂停写
317
359
  resendings: [], # 重传队列 [ src_id, pack_id ]
318
360
  created_at: Time.new, # 创建时间
@@ -324,10 +366,7 @@ module Girl
324
366
  @tun_info = tun_info
325
367
 
326
368
  add_read( tun, :tun )
327
- data = @custom.hello
328
- puts "p#{ Process.pid } #{ Time.new } hello i'm tun"
329
- # puts "debug1 #{ data.inspect }"
330
- add_tun_ctlmsg( data, @proxyd_addr )
369
+ loop_send_hello
331
370
  end
332
371
 
333
372
  ##
@@ -360,9 +399,6 @@ module Girl
360
399
  src: src, # 对应src
361
400
  domain: domain, # 域名
362
401
  wbuff: '', # 写前
363
- cache: '', # 块读出缓存
364
- chunks: [], # 块队列,写前达到块大小时结一个块 filename
365
- spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
366
402
  last_continue_at: Time.new, # 上一次发生流量的时间
367
403
  is_closing: false # 是否准备关闭
368
404
  }
@@ -376,11 +412,8 @@ module Girl
376
412
  # puts "debug1 add src wbuff http ok"
377
413
  add_src_wbuff( src, HTTP_OK )
378
414
  else
379
- # puts "debug1 add src rbuffs to dst wbuff"
380
-
381
- src_info[ :rbuffs ].each do | _, data |
382
- add_dst_wbuff( dst, data )
383
- end
415
+ # puts "debug1 add src rbuff to dst wbuff"
416
+ add_dst_wbuff( dst, src_info[ :rbuff ] )
384
417
  end
385
418
  elsif src_info[ :proxy_proto ] == :socks5
386
419
  add_src_wbuff_socks5_conn_reply( src )
@@ -396,31 +429,15 @@ module Girl
396
429
  end
397
430
 
398
431
  src_info = @src_infos[ src ]
399
- src_id = src_info[ :id ]
400
- destination_port = src_info[ :destination_port ]
401
- destination_domain = src_info[ :destination_domain ]
402
-
403
- src_ext = {
404
- src: src, # src
405
- dst_port: nil, # 远端dst端口
406
- destination_domain: destination_domain, # 目的地域名
407
- wmems: {}, # 写后 pack_id => data
408
- send_ats: {}, # 上一次发出时间 pack_id => send_at
409
- relay_pack_id: 0, # 转发到几
410
- continue_dst_pack_id: 0, # 收到几
411
- pieces: {}, # 跳号包 dst_pack_id => data
412
- is_dst_closed: false, # dst是否已关闭
413
- biggest_dst_pack_id: 0, # dst最大包号码
414
- completed_pack_id: 0, # 完成到几(对面收到几)
415
- last_continue_at: Time.new # 上一次发生流量的时间
416
- }
417
-
418
- @tun_info[ :src_exts ][ src_id ] = src_ext
419
432
  src_info[ :proxy_type ] = :tunnel
433
+ src_id = src_info[ :id ]
434
+ @tun_info[ :srcs ][ src_id ] = src
420
435
 
421
- destination_domain_port = [ destination_domain, destination_port ].join( ':' )
422
- data = [ [ 0, A_NEW_SOURCE, src_id ].pack( 'Q>CQ>' ), @custom.encode( destination_domain_port ) ].join
423
- loop_send_a_new_source( src_ext, data )
436
+ if @tun_info[ :tund_addr ]
437
+ loop_send_a_new_source( src )
438
+ else
439
+ @tun_info[ :pending_sources ] << src
440
+ end
424
441
  end
425
442
 
426
443
  ##
@@ -459,75 +476,12 @@ module Girl
459
476
  [ data, domain_and_port ]
460
477
  end
461
478
 
462
- ##
463
- # add tun ctlmsg
464
- #
465
- def add_tun_ctlmsg( data, to_addr = nil )
466
- unless to_addr
467
- to_addr = @tun_info[ :tund_addr ]
468
- end
469
-
470
- if to_addr
471
- @tun_info[ :ctlmsgs ] << [ to_addr, data ]
472
- add_write( @tun )
473
- else
474
- @tun_info[ :ctlmsg_rbuffs ] << data
475
- end
476
- end
477
-
478
- ##
479
- # add tun wbuff
480
- #
481
- def add_tun_wbuff( src_id, pack_id, data )
482
- @tun_info[ :wbuffs ] << [ src_id, pack_id, data ]
483
-
484
- if @tun_info[ :wbuffs ].size >= WBUFFS_LIMIT
485
- spring = @tun_info[ :chunks ].size > 0 ? ( @tun_info[ :spring ] + 1 ) : 0
486
- filename = "#{ Process.pid }-#{ @tun_info[ :port ] }.#{ spring }"
487
- chunk_path = File.join( @tun_chunk_dir, filename )
488
- datas = @tun_info[ :wbuffs ].map{ | _src_id, _pack_id, _data | [ [ _src_id, _pack_id, _data.bytesize ].pack( 'Q>Q>n' ), _data ].join }
489
-
490
- begin
491
- IO.binwrite( chunk_path, datas.join )
492
- rescue Errno::ENOSPC => e
493
- puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close tun"
494
- set_is_closing( @tun )
495
- return
496
- end
497
-
498
- @tun_info[ :chunks ] << filename
499
- @tun_info[ :spring ] = spring
500
- @tun_info[ :wbuffs ].clear
501
- end
502
-
503
- add_write( @tun )
504
- end
505
-
506
479
  ##
507
480
  # add src wbuff
508
481
  #
509
482
  def add_src_wbuff( src, data )
510
483
  src_info = @src_infos[ src ]
511
484
  src_info[ :wbuff ] << data
512
-
513
- if src_info[ :wbuff ].bytesize >= CHUNK_SIZE
514
- spring = src_info[ :chunks ].size > 0 ? ( src_info[ :spring ] + 1 ) : 0
515
- filename = "#{ Process.pid }-#{ src_info[ :id ] }.#{ spring }"
516
- chunk_path = File.join( @src_chunk_dir, filename )
517
-
518
- begin
519
- IO.binwrite( chunk_path, src_info[ :wbuff ] )
520
- rescue Errno::ENOSPC => e
521
- puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close src"
522
- set_is_closing( src )
523
- return
524
- end
525
-
526
- src_info[ :chunks ] << filename
527
- src_info[ :spring ] = spring
528
- src_info[ :wbuff ].clear
529
- end
530
-
531
485
  add_write( src )
532
486
  end
533
487
 
@@ -537,37 +491,20 @@ module Girl
537
491
  def add_dst_wbuff( dst, data )
538
492
  dst_info = @dst_infos[ dst ]
539
493
  dst_info[ :wbuff ] << data
540
-
541
- if dst_info[ :wbuff ].bytesize >= CHUNK_SIZE
542
- spring = dst_info[ :chunks ].size > 0 ? ( dst_info[ :spring ] + 1 ) : 0
543
- filename = "#{ Process.pid }-#{ dst_info[ :local_port ] }.#{ spring }"
544
- chunk_path = File.join( @dst_chunk_dir, filename )
545
-
546
- begin
547
- IO.binwrite( chunk_path, dst_info[ :wbuff ] )
548
- rescue Errno::ENOSPC => e
549
- puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close dst"
550
- set_is_closing( dst )
551
- return
552
- end
553
-
554
- dst_info[ :chunks ] << filename
555
- dst_info[ :spring ] = spring
556
- dst_info[ :wbuff ].clear
557
- end
558
-
559
494
  add_write( dst )
560
495
  end
561
496
 
562
497
  ##
563
498
  # add read
564
499
  #
565
- def add_read( sock, role )
566
- unless @reads.include?( sock )
500
+ def add_read( sock, role = nil )
501
+ if sock && !sock.closed? && !@reads.include?( sock )
567
502
  @reads << sock
568
- end
569
503
 
570
- @roles[ sock ] = role
504
+ if role
505
+ @roles[ sock ] = role
506
+ end
507
+ end
571
508
  end
572
509
 
573
510
  ##
@@ -579,6 +516,17 @@ module Girl
579
516
  end
580
517
  end
581
518
 
519
+ ##
520
+ # add pause src
521
+ #
522
+ def add_pause_src( src )
523
+ @reads.delete( src )
524
+
525
+ unless @pause_srcs.include?( src )
526
+ @pause_srcs << src
527
+ end
528
+ end
529
+
582
530
  ##
583
531
  # set is closing
584
532
  #
@@ -603,10 +551,52 @@ module Girl
603
551
  end
604
552
  end
605
553
 
554
+ ##
555
+ # tunnel data
556
+ #
557
+ def tunnel_data( src, data )
558
+ src_info = @src_infos[ src ]
559
+ src_id = src_info[ :id ]
560
+ now = Time.new
561
+ pack_id = src_info[ :biggest_pack_id ]
562
+ idx = 0
563
+ len = data.bytesize
564
+
565
+ while idx < len
566
+ chunk = data[ idx, PACK_SIZE ]
567
+ pack_id += 1
568
+
569
+ if pack_id <= CONFUSE_UNTIL
570
+ chunk = @custom.encode( chunk )
571
+ # puts "debug1 encoded chunk #{ pack_id }"
572
+ end
573
+
574
+ data2 = [ [ pack_id, src_id ].pack( 'Q>Q>' ), chunk ].join
575
+ sent = send_data( @tun, data2, @tun_info[ :tund_addr ] )
576
+ # puts "debug2 written pack #{ pack_id } #{ sent }"
577
+ @tun_info[ :wmems ][ [ src_id, pack_id ] ] = data2
578
+ src_info[ :send_ats ][ pack_id ] = now
579
+ idx += PACK_SIZE
580
+ end
581
+
582
+ src_info[ :biggest_pack_id ] = pack_id
583
+ src_info[ :last_continue_at ] = now
584
+
585
+ # 写后超过上限,暂停读src
586
+ if @tun_info[ :wmems ].size >= WMEMS_LIMIT
587
+ puts "p#{ Process.pid } #{ Time.new } pause src #{ src_id } #{ src_info[ :destination_domain ] } #{ src_info[ :biggest_pack_id ] }"
588
+ add_pause_src( src )
589
+ end
590
+ end
591
+
606
592
  ##
607
593
  # send data
608
594
  #
609
595
  def send_data( tun, data, to_addr )
596
+ unless to_addr
597
+ return false
598
+ end
599
+
610
600
  begin
611
601
  tun.sendmsg( data, 0, to_addr )
612
602
  rescue IO::WaitWritable, Errno::EINTR
@@ -626,36 +616,36 @@ module Girl
626
616
  def close_src( src )
627
617
  # puts "debug1 close src"
628
618
  close_sock( src )
629
- src_info = @src_infos.delete( src )
619
+ @pause_srcs.delete( src )
620
+ src_info = @src_infos[ src ]
630
621
 
631
- src_info[ :chunks ].each do | filename |
632
- begin
633
- File.delete( File.join( @src_chunk_dir, filename ) )
634
- rescue Errno::ENOENT
622
+ if src_info[ :proxy_type ] == :direct
623
+ @src_infos.delete( src )
624
+
625
+ if src_info[ :dst ]
626
+ set_is_closing( src_info[ :dst ] )
635
627
  end
636
- end
637
628
 
638
- src_id = src_info[ :id ]
629
+ return
630
+ end
639
631
 
640
- if src_info[ :proxy_type ] == :tunnel
641
- return if @tun.closed?
632
+ if @tun.closed? || src_info[ :dst_id ].nil?
633
+ @src_infos.delete( src )
634
+ return
635
+ end
642
636
 
643
- src_ext = @tun_info[ :src_exts ][ src_id ]
644
- return if src_ext.nil? || src_ext[ :dst_port ].nil?
637
+ src_id = src_info[ :id ]
645
638
 
646
- if src_ext[ :is_dst_closed ]
647
- # puts "debug1 2-3. after close src -> dst closed ? yes -> del src ext -> send fin2"
648
- del_src_ext( src_id )
649
- data = [ 0, FIN2, src_id ].pack( 'Q>CQ>' )
650
- add_tun_ctlmsg( data )
651
- else
652
- # puts "debug1 1-1. after close src -> dst closed ? no -> send fin1"
653
- data = [ 0, FIN1, src_id, src_info[ :biggest_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
654
- add_tun_ctlmsg( data )
655
- end
656
- elsif src_info[ :proxy_type ] == :direct
657
- set_is_closing( src_info[ :dst ] )
639
+ if src_info[ :is_dst_closed ]
640
+ # puts "debug1 2-3. after close src -> dst closed ? yes -> del src ext -> send fin2"
641
+ del_src_ext( src_id )
642
+ data = [ 0, FIN2, src_id ].pack( 'Q>CQ>' )
643
+ else
644
+ # puts "debug1 1-1. after close src -> dst closed ? no -> send fin1"
645
+ data = [ 0, FIN1, src_id, src_info[ :biggest_pack_id ], src_info[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
658
646
  end
647
+
648
+ send_data( @tun, data, @tun_info[ :tund_addr ] )
659
649
  end
660
650
 
661
651
  ##
@@ -665,14 +655,6 @@ module Girl
665
655
  # puts "debug1 close dst"
666
656
  close_sock( dst )
667
657
  dst_info = @dst_infos.delete( dst )
668
-
669
- dst_info[ :chunks ].each do | filename |
670
- begin
671
- File.delete( File.join( @dst_chunk_dir, filename ) )
672
- rescue Errno::ENOENT
673
- end
674
- end
675
-
676
658
  set_is_closing( dst_info[ :src ] )
677
659
  end
678
660
 
@@ -682,15 +664,7 @@ module Girl
682
664
  def close_tun( tun )
683
665
  # puts "debug1 close tun"
684
666
  close_sock( tun )
685
-
686
- @tun_info[ :chunks ].each do | filename |
687
- begin
688
- File.delete( File.join( @tun_chunk_dir, filename ) )
689
- rescue Errno::ENOENT
690
- end
691
- end
692
-
693
- @tun_info[ :src_exts ].each{ | _, src_ext | set_is_closing( src_ext[ :src ] ) }
667
+ @tun_info[ :srcs ].each{ | _, src | set_is_closing( src ) }
694
668
  end
695
669
 
696
670
  ##
@@ -707,27 +681,32 @@ module Girl
707
681
  # del src ext
708
682
  #
709
683
  def del_src_ext( src_id )
710
- src_ext = @tun_info[ :src_exts ].delete( src_id )
684
+ @tun_info[ :wmems ].delete_if { | src_id_and_pack_id, _ | src_id_and_pack_id.first == src_id }
685
+ src = @tun_info[ :srcs ].delete( src_id )
711
686
 
712
- if src_ext
713
- @tun_info[ :src_ids ].delete( src_ext[ :dst_port ] )
687
+ if src
688
+ src_info = @src_infos.delete( src )
689
+
690
+ if src_info
691
+ @tun_info[ :src_ids ].delete( src_info[ :dst_id ] )
692
+ end
714
693
  end
715
694
  end
716
695
 
717
696
  ##
718
697
  # release wmems
719
698
  #
720
- def release_wmems( src_ext, completed_pack_id )
721
- if completed_pack_id > src_ext[ :completed_pack_id ]
699
+ def release_wmems( src_info, completed_pack_id )
700
+ if completed_pack_id > src_info[ :completed_pack_id ]
722
701
  # puts "debug2 update completed pack #{ completed_pack_id }"
723
- pack_ids = src_ext[ :wmems ].keys.select { | pack_id | pack_id <= completed_pack_id }
702
+ pack_ids = src_info[ :send_ats ].keys.select { | pack_id | pack_id <= completed_pack_id }
724
703
 
725
704
  pack_ids.each do | pack_id |
726
- src_ext[ :wmems ].delete( pack_id )
727
- src_ext[ :send_ats ].delete( pack_id )
705
+ @tun_info[ :wmems ].delete( [ src_info[ :id ], pack_id ] )
706
+ src_info[ :send_ats ].delete( pack_id )
728
707
  end
729
708
 
730
- src_ext[ :completed_pack_id ] = completed_pack_id
709
+ src_info[ :completed_pack_id ] = completed_pack_id
731
710
  end
732
711
  end
733
712
 
@@ -743,32 +722,16 @@ module Girl
743
722
  #
744
723
  def write_src( src )
745
724
  src_info = @src_infos[ src ]
746
- from, data = :cache, src_info[ :cache ]
747
725
 
748
- if data.empty?
749
- if src_info[ :chunks ].any?
750
- path = File.join( @src_chunk_dir, src_info[ :chunks ].shift )
751
-
752
- begin
753
- data = src_info[ :cache ] = IO.binread( path )
754
- File.delete( path )
755
- rescue Errno::ENOENT => e
756
- puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
757
- close_src( src )
758
- return
759
- end
760
- else
761
- from, data = :wbuff, src_info[ :wbuff ]
762
- end
726
+ if src_info[ :is_closing ]
727
+ close_src( src )
728
+ return
763
729
  end
764
730
 
765
- if data.empty?
766
- if src_info[ :is_closing ]
767
- close_src( src )
768
- else
769
- @writes.delete( src )
770
- end
731
+ data = src_info[ :wbuff ]
771
732
 
733
+ if data.empty?
734
+ @writes.delete( src )
772
735
  return
773
736
  end
774
737
 
@@ -783,7 +746,7 @@ module Girl
783
746
 
784
747
  # puts "debug2 write src #{ written }"
785
748
  data = data[ written..-1 ]
786
- src_info[ from ] = data
749
+ src_info[ :wbuff ] = data
787
750
  src_info[ :last_continue_at ] = Time.new
788
751
  end
789
752
 
@@ -792,32 +755,16 @@ module Girl
792
755
  #
793
756
  def write_dst( dst )
794
757
  dst_info = @dst_infos[ dst ]
795
- from, data = :cache, dst_info[ :cache ]
796
758
 
797
- if data.empty?
798
- if dst_info[ :chunks ].any?
799
- path = File.join( @dst_chunk_dir, dst_info[ :chunks ].shift )
800
-
801
- begin
802
- data = dst_info[ :cache ] = IO.binread( path )
803
- File.delete( path )
804
- rescue Errno::ENOENT => e
805
- puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
806
- close_dst( dst )
807
- return
808
- end
809
- else
810
- from, data = :wbuff, dst_info[ :wbuff ]
811
- end
759
+ if dst_info[ :is_closing ]
760
+ close_dst( dst )
761
+ return
812
762
  end
813
763
 
814
- if data.empty?
815
- if dst_info[ :is_closing ]
816
- close_dst( dst )
817
- else
818
- @writes.delete( dst )
819
- end
764
+ data = dst_info[ :wbuff ]
820
765
 
766
+ if data.empty?
767
+ @writes.delete( dst )
821
768
  return
822
769
  end
823
770
 
@@ -833,7 +780,7 @@ module Girl
833
780
 
834
781
  # puts "debug2 write dst #{ written }"
835
782
  data = data[ written..-1 ]
836
- dst_info[ from ] = data
783
+ dst_info[ :wbuff ] = data
837
784
  dst_info[ :last_continue_at ] = Time.new
838
785
  end
839
786
 
@@ -846,106 +793,7 @@ module Girl
846
793
  return
847
794
  end
848
795
 
849
- now = Time.new
850
-
851
- # 传ctlmsg
852
- while @tun_info[ :ctlmsgs ].any?
853
- to_addr, data = @tun_info[ :ctlmsgs ].first
854
-
855
- unless send_data( tun, data, to_addr )
856
- return
857
- end
858
-
859
- @tun_info[ :ctlmsgs ].shift
860
- end
861
-
862
- # 重传
863
- while @tun_info[ :resendings ].any?
864
- src_id, pack_id = @tun_info[ :resendings ].first
865
- src_ext = @tun_info[ :src_exts ][ src_id ]
866
-
867
- if src_ext
868
- data = src_ext[ :wmems ][ pack_id ]
869
-
870
- if data
871
- unless send_data( tun, data, @tun_info[ :tund_addr ] )
872
- return
873
- end
874
-
875
- src_ext[ :last_continue_at ] = now
876
- end
877
- end
878
-
879
- @tun_info[ :resendings ].shift
880
- end
881
-
882
- # 若写后达到上限,暂停取写前
883
- if @tun_info[ :src_exts ].map{ | _, src_ext | src_ext[ :wmems ].size }.sum >= WMEMS_LIMIT
884
- unless @tun_info[ :paused ]
885
- puts "p#{ Process.pid } #{ Time.new } pause tun"
886
- @tun_info[ :paused ] = true
887
- end
888
-
889
- @writes.delete( tun )
890
- return
891
- end
892
-
893
- # 取写前
894
- if @tun_info[ :caches ].any?
895
- datas = @tun_info[ :caches ]
896
- elsif @tun_info[ :chunks ].any?
897
- path = File.join( @tun_chunk_dir, @tun_info[ :chunks ].shift )
898
-
899
- begin
900
- data = IO.binread( path )
901
- File.delete( path )
902
- rescue Errno::ENOENT => e
903
- puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
904
- close_tun( tun )
905
- return
906
- end
907
-
908
- caches = []
909
-
910
- until data.empty?
911
- _src_id, _pack_id, pack_size = data[ 0, 18 ].unpack( 'Q>Q>n' )
912
- caches << [ _src_id, _pack_id, data[ 18, pack_size ] ]
913
- data = data[ ( 18 + pack_size )..-1 ]
914
- end
915
-
916
- datas = @tun_info[ :caches ] = caches
917
- elsif @tun_info[ :wbuffs ].any?
918
- datas = @tun_info[ :wbuffs ]
919
- else
920
- @writes.delete( tun )
921
- return
922
- end
923
-
924
- while datas.any?
925
- src_id, pack_id, data = datas.first
926
- src_ext = @tun_info[ :src_exts ][ src_id ]
927
-
928
- if src_ext
929
- if pack_id <= CONFUSE_UNTIL
930
- data = @custom.encode( data )
931
- # puts "debug1 encoded pack #{ pack_id }"
932
- end
933
-
934
- data = [ [ pack_id, src_id ].pack( 'Q>Q>' ), data ].join
935
-
936
- unless send_data( tun, data, @tun_info[ :tund_addr ] )
937
- return
938
- end
939
-
940
- # puts "debug2 written pack #{ pack_id }"
941
- src_ext[ :relay_pack_id ] = pack_id
942
- src_ext[ :wmems ][ pack_id ] = data
943
- src_ext[ :send_ats ][ pack_id ] = now
944
- src_ext[ :last_continue_at ] = now
945
- end
946
-
947
- datas.shift
948
- end
796
+ @writes.delete( tun )
949
797
  end
950
798
 
951
799
  ##
@@ -965,11 +813,11 @@ module Girl
965
813
  return
966
814
  end
967
815
 
968
- id = rand( ( 2 ** 64 ) - 2 ) + 1
969
- # puts "debug1 accept a src #{ addrinfo.inspect } #{ id }"
816
+ src_id = rand( ( 2 ** 64 ) - 2 ) + 1
817
+ # puts "debug1 accept a src #{ addrinfo.inspect } #{ src_id }"
970
818
 
971
819
  @src_infos[ src ] = {
972
- id: id, # id
820
+ id: src_id, # id
973
821
  proxy_proto: :uncheck, # :uncheck / :http / :socks5
974
822
  proxy_type: :uncheck, # :uncheck / :checking / :direct / :tunnel / :negotiation
975
823
  dst: nil, # :direct的场合,对应的dst
@@ -977,11 +825,15 @@ module Girl
977
825
  destination_port: nil, # 目的地端口
978
826
  biggest_pack_id: 0, # 最大包号码
979
827
  is_connect: true, # 代理协议是http的场合,是否是CONNECT
980
- rbuffs: [], # 非CONNECT,dst或者远端dst未准备好,暂存流量 [ pack_id, data ]
828
+ rbuff: '', # 非CONNECT,dst或者远端dst未准备好,暂存流量
981
829
  wbuff: '', # 写前
982
- cache: '', # 块读出缓存
983
- chunks: [], # 块队列,写前达到块大小时结一个块 filename
984
- spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
830
+ dst_id: nil, # 远端dst id
831
+ send_ats: {}, # 上一次发出时间 pack_id => send_at
832
+ continue_dst_pack_id: 0, # 收到几
833
+ pieces: {}, # 跳号包 dst_pack_id => data
834
+ is_dst_closed: false, # dst是否已关闭
835
+ biggest_dst_pack_id: 0, # dst最大包号码
836
+ completed_pack_id: 0, # 完成到几(对面收到几)
985
837
  last_continue_at: Time.new, # 上一次发生流量的时间
986
838
  is_closing: false # 是否准备关闭
987
839
  }
@@ -994,7 +846,7 @@ module Girl
994
846
  #
995
847
  def read_src( src )
996
848
  begin
997
- data = src.read_nonblock( PACK_SIZE )
849
+ data = src.read_nonblock( READ_SIZE )
998
850
  rescue IO::WaitReadable, Errno::EINTR
999
851
  return
1000
852
  rescue Exception => e
@@ -1074,9 +926,7 @@ module Girl
1074
926
  end
1075
927
 
1076
928
  src_info[ :is_connect ] = false
1077
- pack_id = src_info[ :biggest_pack_id ] + 1
1078
- src_info[ :biggest_pack_id ] = pack_id
1079
- src_info[ :rbuffs ] << [ pack_id, data ]
929
+ src_info[ :rbuff ] << data
1080
930
  end
1081
931
 
1082
932
  domain, port = domain_and_port.split( ':' )
@@ -1089,9 +939,7 @@ module Girl
1089
939
  resolve_domain( src, domain )
1090
940
  when :checking
1091
941
  # puts "debug1 add src rbuff while checking #{ data.inspect }"
1092
- pack_id = src_info[ :biggest_pack_id ] + 1
1093
- src_info[ :biggest_pack_id ] = pack_id
1094
- src_info[ :rbuffs ] << [ pack_id, data ]
942
+ src_info[ :rbuff ] << data
1095
943
  when :negotiation
1096
944
  # +----+-----+-------+------+----------+----------+
1097
945
  # |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
@@ -1129,19 +977,7 @@ module Girl
1129
977
  puts "p#{ Process.pid } #{ Time.new } socks5 cmd #{ cmd } not implement"
1130
978
  end
1131
979
  when :tunnel
1132
- src_id = src_info[ :id ]
1133
- src_ext = @tun_info[ :src_exts ][ src_id ]
1134
-
1135
- unless src_ext
1136
- # puts "debug1 not found src ext"
1137
- set_is_closing( src )
1138
- return
1139
- end
1140
-
1141
- pack_id = src_info[ :biggest_pack_id ] + 1
1142
- src_info[ :biggest_pack_id ] = pack_id
1143
-
1144
- if src_ext[ :dst_port ]
980
+ if src_info[ :dst_id ]
1145
981
  if @tun.closed?
1146
982
  # puts "debug1 tun closed, close src"
1147
983
  set_is_closing( src )
@@ -1152,10 +988,10 @@ module Girl
1152
988
  data, _ = sub_http_request( data )
1153
989
  end
1154
990
 
1155
- add_tun_wbuff( src_id, pack_id, data )
991
+ tunnel_data( src, data )
1156
992
  else
1157
993
  # puts "debug1 remote dst not ready, save data to src rbuff"
1158
- src_info[ :rbuffs ] << [ pack_id, data ]
994
+ src_info[ :rbuff ] << data
1159
995
  end
1160
996
  when :direct
1161
997
  dst = src_info[ :dst ]
@@ -1174,7 +1010,7 @@ module Girl
1174
1010
  add_dst_wbuff( dst, data )
1175
1011
  else
1176
1012
  # puts "debug1 dst not ready, save data to src rbuff"
1177
- src_info[ :rbuffs ] << [ nil, data ]
1013
+ src_info[ :rbuff ] << data
1178
1014
  end
1179
1015
  end
1180
1016
  end
@@ -1184,7 +1020,7 @@ module Girl
1184
1020
  #
1185
1021
  def read_dst( dst )
1186
1022
  begin
1187
- data = dst.read_nonblock( PACK_SIZE )
1023
+ data = dst.read_nonblock( READ_SIZE )
1188
1024
  rescue IO::WaitReadable, Errno::EINTR
1189
1025
  return
1190
1026
  rescue Exception => e
@@ -1230,71 +1066,73 @@ module Girl
1230
1066
  tund_addr = Socket.sockaddr_in( tund_port, @proxyd_host )
1231
1067
  @tun_info[ :tund_addr ] = tund_addr
1232
1068
 
1233
- if @tun_info[ :ctlmsg_rbuffs ].any?
1234
- # puts "debug1 move #{ @tun_info[ :ctlmsg_rbuffs ].size } ctlmsg rbuffs to ctlmsgs"
1235
- @tun_info[ :ctlmsgs ] += @tun_info[ :ctlmsg_rbuffs ].map{ | _data | [ tund_addr, _data ] }
1236
- @tun_info[ :ctlmsg_rbuffs ].clear
1237
- add_write( tun )
1069
+ if @tun_info[ :pending_sources ].any?
1070
+ puts "p#{ Process.pid } #{ Time.new } send pending sources"
1071
+
1072
+ @tun_info[ :pending_sources ].each do | src |
1073
+ loop_send_a_new_source( src )
1074
+ end
1075
+
1076
+ @tun_info[ :pending_sources ].clear
1238
1077
  end
1239
1078
  when PAIRED
1240
1079
  return if from_addr != @tun_info[ :tund_addr ]
1241
1080
 
1242
- src_id, dst_port = data[ 9, 10 ].unpack( 'Q>n' )
1243
-
1244
- src_ext = @tun_info[ :src_exts ][ src_id ]
1245
- return if src_ext.nil? || src_ext[ :dst_port ]
1081
+ src_id, dst_id = data[ 9, 10 ].unpack( 'Q>n' )
1246
1082
 
1247
- src = src_ext[ :src ]
1083
+ src = @tun_info[ :srcs ][ src_id ]
1248
1084
  return if src.closed?
1249
1085
 
1250
- # puts "debug1 got paired #{ src_id } #{ dst_port }"
1086
+ src_info = @src_infos[ src ]
1087
+ return if src_info[ :dst_id ]
1088
+
1089
+ # puts "debug1 got paired #{ src_id } #{ dst_id }"
1251
1090
 
1252
- if dst_port == 0
1091
+ if dst_id == 0
1253
1092
  set_is_closing( src )
1254
1093
  return
1255
1094
  end
1256
1095
 
1257
- src_ext[ :dst_port ] = dst_port
1258
- @tun_info[ :src_ids ][ dst_port ] = src_id
1259
-
1260
- src_info = @src_infos[ src ]
1096
+ src_info[ :dst_id ] = dst_id
1097
+ @tun_info[ :src_ids ][ dst_id ] = src_id
1261
1098
 
1262
1099
  if src_info[ :proxy_proto ] == :http
1263
1100
  if src_info[ :is_connect ]
1264
1101
  # puts "debug1 add src wbuff http ok"
1265
1102
  add_src_wbuff( src, HTTP_OK )
1266
1103
  else
1267
- # puts "debug1 add src rbuffs to tun wbuffs"
1268
-
1269
- src_info[ :rbuffs ].each do | pack_id, _data |
1270
- add_tun_wbuff( src_id, pack_id, _data )
1271
- end
1104
+ # puts "debug1 send src rbuff to tund"
1105
+ tunnel_data( src, src_info[ :rbuff ] )
1272
1106
  end
1273
1107
  elsif src_info[ :proxy_proto ] == :socks5
1274
- add_src_wbuff_socks5_conn_reply( src_ext[ :src ] )
1108
+ add_src_wbuff_socks5_conn_reply( src )
1275
1109
  end
1276
1110
  when DEST_STATUS
1277
1111
  return if from_addr != @tun_info[ :tund_addr ]
1278
1112
 
1279
- dst_port, relay_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
1113
+ dst_id, relay_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
1280
1114
 
1281
- src_id = @tun_info[ :src_ids ][ dst_port ]
1115
+ src_id = @tun_info[ :src_ids ][ dst_id ]
1282
1116
  return unless src_id
1283
1117
 
1284
- src_ext = @tun_info[ :src_exts ][ src_id ]
1285
- return unless src_ext
1118
+ src = @tun_info[ :srcs ][ src_id ]
1119
+ return unless src
1120
+
1121
+ src_info = @src_infos[ src ]
1122
+ return unless src_info
1286
1123
 
1287
- # puts "debug2 got dest status"
1124
+ # puts "debug2 got dest status #{ Time.new }"
1288
1125
 
1289
- release_wmems( src_ext, continue_src_pack_id )
1126
+ # 消写后
1127
+ release_wmems( src_info, continue_src_pack_id )
1290
1128
 
1291
1129
  # 发miss
1292
- if !src_ext[ :src ].closed? && ( src_ext[ :continue_dst_pack_id ] < relay_dst_pack_id )
1130
+ if !src.closed? && ( src_info[ :continue_dst_pack_id ] < relay_dst_pack_id )
1293
1131
  ranges = []
1294
1132
  ignored = false
1295
- curr_pack_id = src_ext[ :continue_dst_pack_id ] + 1
1133
+ curr_pack_id = src_info[ :continue_dst_pack_id ] + 1
1296
1134
 
1297
- src_ext[ :pieces ].keys.sort.each do | pack_id |
1135
+ src_info[ :pieces ].keys.sort.each do | pack_id |
1298
1136
  if pack_id > curr_pack_id
1299
1137
  ranges << [ curr_pack_id, pack_id - 1 ]
1300
1138
 
@@ -1312,57 +1150,106 @@ module Girl
1312
1150
  ranges << [ curr_pack_id, relay_dst_pack_id ]
1313
1151
  end
1314
1152
 
1315
- # puts "debug1 continue/relay #{ src_ext[ :continue_dst_pack_id ] }/#{ relay_dst_pack_id } send MISS #{ ranges.size }"
1153
+ # puts "debug1 continue/relay #{ src_info[ :continue_dst_pack_id ] }/#{ relay_dst_pack_id } send MISS #{ ranges.size }"
1154
+ idx = 0
1155
+ ranges = ranges.map{ | pack_id_begin, pack_id_end | [ pack_id_begin, pack_id_end ].pack( 'Q>Q>' ) }
1316
1156
 
1317
- ranges.each do | pack_id_begin, pack_id_end |
1318
- data2 = [ 0, MISS, dst_port, pack_id_begin, pack_id_end ].pack( 'Q>CnQ>Q>' )
1319
- add_tun_ctlmsg( data2 )
1157
+ while idx < ranges.size
1158
+ chunk = ranges[ idx, MULTI_MISS_SIZE ].join
1159
+ data2 = [ [ 0, MULTI_MISS, dst_id ].pack( 'Q>Cn' ), chunk ].join
1160
+ send_data( tun, data2, @tun_info[ :tund_addr ] )
1161
+ idx += MULTI_MISS_SIZE
1320
1162
  end
1321
1163
  end
1164
+ when MULTI_MISS
1165
+ src_id, *ranges = data[ 9..-1 ].unpack( 'Q>Q>*' )
1166
+
1167
+ src = @tun_info[ :srcs ][ src_id ]
1168
+ return unless src
1169
+
1170
+ src_info = @src_infos[ src ]
1171
+ return unless src_info
1172
+
1173
+ return if ranges.empty? || ( ranges.size % 2 != 0 )
1174
+
1175
+ # puts "debug1 got multi miss #{ src_id } #{ ranges.size }"
1176
+
1177
+ idx = 0
1178
+
1179
+ while idx < ranges.size
1180
+ pack_id_begin, pack_id_end = ranges[ idx ], ranges[ idx + 1 ]
1181
+
1182
+ ( pack_id_begin..pack_id_end ).each do | pack_id |
1183
+ send_at = src_info[ :send_ats ][ pack_id ]
1184
+
1185
+ if send_at
1186
+ break if now - send_at < CHECK_STATUS_INTERVAL
1187
+ data2 = @tun_info[ :wmems ][ [ src_id, pack_id ] ]
1188
+
1189
+ if data2
1190
+ if send_data( tun, data2, @tun_info[ :tund_addr ] )
1191
+ src_info[ :last_continue_at ] = now
1192
+ end
1193
+ end
1194
+ end
1195
+ end
1196
+
1197
+ idx += 2
1198
+ end
1322
1199
  when MISS
1323
- return if ( from_addr != @tun_info[ :tund_addr ] ) || ( @tun_info[ :resendings ].size >= RESENDING_LIMIT )
1200
+ return if from_addr != @tun_info[ :tund_addr ]
1324
1201
 
1325
1202
  src_id, pack_id_begin, pack_id_end = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
1326
1203
 
1327
- src_ext = @tun_info[ :src_exts ][ src_id ]
1328
- return unless src_ext
1204
+ src = @tun_info[ :srcs ][ src_id ]
1205
+ return unless src
1206
+
1207
+ src_info = @src_infos[ src ]
1208
+ return unless src_info
1329
1209
 
1330
1210
  ( pack_id_begin..pack_id_end ).each do | pack_id |
1331
- send_at = src_ext[ :send_ats ][ pack_id ]
1211
+ send_at = src_info[ :send_ats ][ pack_id ]
1332
1212
 
1333
1213
  if send_at
1334
1214
  break if now - send_at < CHECK_STATUS_INTERVAL
1335
- @tun_info[ :resendings ] << [ src_id, pack_id ]
1215
+ data2 = @tun_info[ :wmems ][ [ src_id, pack_id ] ]
1216
+
1217
+ if data2
1218
+ if send_data( tun, data2, @tun_info[ :tund_addr ] )
1219
+ src_info[ :last_continue_at ] = now
1220
+ end
1221
+ end
1336
1222
  end
1337
1223
  end
1338
-
1339
- add_write( tun )
1340
1224
  when FIN1
1341
1225
  return if from_addr != @tun_info[ :tund_addr ]
1342
1226
 
1343
- dst_port, biggest_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
1227
+ dst_id, biggest_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
1344
1228
 
1345
- src_id = @tun_info[ :src_ids ][ dst_port ]
1229
+ src_id = @tun_info[ :src_ids ][ dst_id ]
1346
1230
  return unless src_id
1347
1231
 
1348
- src_ext = @tun_info[ :src_exts ][ src_id ]
1349
- return unless src_ext
1232
+ src = @tun_info[ :srcs ][ src_id ]
1233
+ return unless src
1350
1234
 
1351
- # puts "debug1 got fin1 #{ dst_port } biggest dst pack #{ biggest_dst_pack_id } completed src pack #{ continue_src_pack_id }"
1352
- src_ext[ :is_dst_closed ] = true
1353
- src_ext[ :biggest_dst_pack_id ] = biggest_dst_pack_id
1354
- release_wmems( src_ext, continue_src_pack_id )
1235
+ src_info = @src_infos[ src ]
1236
+ return unless src_info
1355
1237
 
1356
- if ( biggest_dst_pack_id == src_ext[ :continue_dst_pack_id ] )
1238
+ # puts "debug1 got fin1 #{ dst_id } biggest dst pack #{ biggest_dst_pack_id } completed src pack #{ continue_src_pack_id }"
1239
+ src_info[ :is_dst_closed ] = true
1240
+ src_info[ :biggest_dst_pack_id ] = biggest_dst_pack_id
1241
+ release_wmems( src_info, continue_src_pack_id )
1242
+
1243
+ if ( biggest_dst_pack_id == src_info[ :continue_dst_pack_id ] )
1357
1244
  # puts "debug1 2-1. tun recv fin1 -> all traffic received ? -> close src after write"
1358
- set_is_closing( src_ext[ :src ] )
1245
+ set_is_closing( src )
1359
1246
  end
1360
1247
  when FIN2
1361
1248
  return if from_addr != @tun_info[ :tund_addr ]
1362
1249
 
1363
- dst_port = data[ 9, 2 ].unpack( 'n' ).first
1250
+ dst_id = data[ 9, 2 ].unpack( 'n' ).first
1364
1251
 
1365
- src_id = @tun_info[ :src_ids ][ dst_port ]
1252
+ src_id = @tun_info[ :src_ids ][ dst_id ]
1366
1253
  return unless src_id
1367
1254
 
1368
1255
  # puts "debug1 1-2. tun recv fin2 -> del src ext"
@@ -1384,14 +1271,18 @@ module Girl
1384
1271
 
1385
1272
  return if from_addr != @tun_info[ :tund_addr ]
1386
1273
 
1387
- dst_port = data[ 8, 2 ].unpack( 'n' ).first
1274
+ dst_id = data[ 8, 2 ].unpack( 'n' ).first
1388
1275
 
1389
- src_id = @tun_info[ :src_ids ][ dst_port ]
1276
+ src_id = @tun_info[ :src_ids ][ dst_id ]
1390
1277
  return unless src_id
1391
1278
 
1392
- src_ext = @tun_info[ :src_exts ][ src_id ]
1393
- return if src_ext.nil? || src_ext[ :src ].closed?
1394
- return if ( pack_id <= src_ext[ :continue_dst_pack_id ] ) || src_ext[ :pieces ].include?( pack_id )
1279
+ src = @tun_info[ :srcs ][ src_id ]
1280
+ return unless src
1281
+
1282
+ src_info = @src_infos[ src ]
1283
+ return unless src_info
1284
+
1285
+ return if ( pack_id <= src_info[ :continue_dst_pack_id ] ) || src_info[ :pieces ].include?( pack_id )
1395
1286
 
1396
1287
  data = data[ 10..-1 ]
1397
1288
  # puts "debug2 got pack #{ pack_id }"
@@ -1403,24 +1294,25 @@ module Girl
1403
1294
  end
1404
1295
 
1405
1296
  # 放进写前,跳号放碎片缓存
1406
- if pack_id - src_ext[ :continue_dst_pack_id ] == 1
1407
- while src_ext[ :pieces ].include?( pack_id + 1 )
1408
- data << src_ext[ :pieces ].delete( pack_id + 1 )
1297
+ if pack_id - src_info[ :continue_dst_pack_id ] == 1
1298
+ while src_info[ :pieces ].include?( pack_id + 1 )
1299
+ data << src_info[ :pieces ].delete( pack_id + 1 )
1409
1300
  pack_id += 1
1410
1301
  end
1411
1302
 
1412
- src_ext[ :continue_dst_pack_id ] = pack_id
1413
- src_ext[ :last_continue_at ] = now
1414
- add_src_wbuff( src_ext[ :src ], data )
1303
+ src_info[ :continue_dst_pack_id ] = pack_id
1304
+ src_info[ :last_continue_at ] = now
1305
+ add_src_wbuff( src, data )
1415
1306
  # puts "debug2 update continue dst pack #{ pack_id }"
1416
1307
 
1417
- # 接到流量,若对面已关闭,且流量正好收全,关闭src
1418
- if src_ext[ :is_dst_closed ] && ( pack_id == src_ext[ :biggest_dst_pack_id ] )
1308
+ # 若对面已关闭,且流量正好收全,关闭src
1309
+ if src_info[ :is_dst_closed ] && ( pack_id == src_info[ :biggest_dst_pack_id ] )
1419
1310
  # puts "debug1 2-2. tun recv traffic -> dst closed and all traffic received ? -> close src after write"
1420
- set_is_closing( src_ext[ :src ] )
1311
+ set_is_closing( src )
1421
1312
  end
1422
- else
1423
- src_ext[ :pieces ][ pack_id ] = data
1313
+ elsif !src_info[ :pieces ].include?( pack_id )
1314
+ src_info[ :pieces ][ pack_id ] = data
1315
+ src_info[ :last_continue_at ] = now
1424
1316
  end
1425
1317
  end
1426
1318