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 +4 -4
- data/lib/girl/head.rb +29 -29
- data/lib/girl/proxy.rb +5 -37
- data/lib/girl/proxy_worker.rb +355 -463
- data/lib/girl/proxyd.rb +23 -24
- data/lib/girl/proxyd_worker.rb +338 -414
- data/lib/girl/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 590ceead2e46e0803325aff199ec4fa4610a554f873ad58e91f83e8cba7bd4a9
|
4
|
+
data.tar.gz: 3034b02ee1ddf592a67446d82a3f974f2439aef9f380f20b39c96aa943a4a7ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27d1dd5ef6d6f4d29c1916af5c10c8eb694e7cbf11f2f8518a6d4a3ebd0d368aa92518a9c5c0f91079f9291c67b1050be16db3f0154d7fb710f55d818ca75576
|
7
|
+
data.tar.gz: ae5ab8293caf167146784342a93e059ef03a201dbd1a1a3df6bbe206321f95b13526e78713ca77903e3be44873ce02474c4d3260187fcd85c993206401fef586
|
data/lib/girl/head.rb
CHANGED
@@ -1,33 +1,33 @@
|
|
1
1
|
module Girl
|
2
|
-
PACK_SIZE
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
MISS_RANGE_LIMIT
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
HTTP_OK
|
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
|
data/lib/girl/proxy.rb
CHANGED
@@ -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
|
-
|
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,
|
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,
|
195
|
+
Girl::ProxyWorker.new( proxy_port, proxyd_host, proxyd_port, directs, remotes, im ).looping
|
228
196
|
end
|
229
197
|
end
|
230
198
|
|
data/lib/girl/proxy_worker.rb
CHANGED
@@ -4,18 +4,16 @@ module Girl
|
|
4
4
|
##
|
5
5
|
# initialize
|
6
6
|
#
|
7
|
-
def initialize( proxy_port, proxyd_host, proxyd_port, directs, remotes,
|
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
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
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
|
-
|
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
|
-
|
160
|
-
|
161
|
-
if @tun_info[ :src_exts ].any?
|
168
|
+
if @tun_info[ :srcs ].any?
|
162
169
|
now = Time.new
|
163
170
|
|
164
|
-
@tun_info[ :
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
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 @
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
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
|
-
|
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
|
-
|
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
|
196
|
-
# puts "debug1 break loop send
|
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
|
-
|
202
|
-
|
203
|
-
|
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
|
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
|
-
|
308
|
-
|
309
|
-
|
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
|
-
|
315
|
-
src_ids: {}, #
|
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
|
-
|
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
|
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
|
-
|
422
|
-
|
423
|
-
|
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
|
-
|
500
|
+
def add_read( sock, role = nil )
|
501
|
+
if sock && !sock.closed? && !@reads.include?( sock )
|
567
502
|
@reads << sock
|
568
|
-
end
|
569
503
|
|
570
|
-
|
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
|
-
|
619
|
+
@pause_srcs.delete( src )
|
620
|
+
src_info = @src_infos[ src ]
|
630
621
|
|
631
|
-
src_info[ :
|
632
|
-
|
633
|
-
|
634
|
-
|
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
|
-
|
629
|
+
return
|
630
|
+
end
|
639
631
|
|
640
|
-
if src_info[ :
|
641
|
-
|
632
|
+
if @tun.closed? || src_info[ :dst_id ].nil?
|
633
|
+
@src_infos.delete( src )
|
634
|
+
return
|
635
|
+
end
|
642
636
|
|
643
|
-
|
644
|
-
return if src_ext.nil? || src_ext[ :dst_port ].nil?
|
637
|
+
src_id = src_info[ :id ]
|
645
638
|
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
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
|
-
|
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
|
713
|
-
|
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(
|
721
|
-
if 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 =
|
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
|
-
|
727
|
-
|
705
|
+
@tun_info[ :wmems ].delete( [ src_info[ :id ], pack_id ] )
|
706
|
+
src_info[ :send_ats ].delete( pack_id )
|
728
707
|
end
|
729
708
|
|
730
|
-
|
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
|
749
|
-
|
750
|
-
|
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
|
-
|
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[
|
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
|
798
|
-
|
799
|
-
|
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
|
-
|
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[
|
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
|
-
|
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
|
-
|
969
|
-
# puts "debug1 accept a src #{ addrinfo.inspect } #{
|
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:
|
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
|
-
|
828
|
+
rbuff: '', # 非CONNECT,dst或者远端dst未准备好,暂存流量
|
981
829
|
wbuff: '', # 写前
|
982
|
-
|
983
|
-
|
984
|
-
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
991
|
+
tunnel_data( src, data )
|
1156
992
|
else
|
1157
993
|
# puts "debug1 remote dst not ready, save data to src rbuff"
|
1158
|
-
src_info[ :
|
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[ :
|
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(
|
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[ :
|
1234
|
-
|
1235
|
-
|
1236
|
-
@tun_info[ :
|
1237
|
-
|
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,
|
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 =
|
1083
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1248
1084
|
return if src.closed?
|
1249
1085
|
|
1250
|
-
|
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
|
1091
|
+
if dst_id == 0
|
1253
1092
|
set_is_closing( src )
|
1254
1093
|
return
|
1255
1094
|
end
|
1256
1095
|
|
1257
|
-
|
1258
|
-
@tun_info[ :src_ids ][
|
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
|
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(
|
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
|
-
|
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 ][
|
1115
|
+
src_id = @tun_info[ :src_ids ][ dst_id ]
|
1282
1116
|
return unless src_id
|
1283
1117
|
|
1284
|
-
|
1285
|
-
return unless
|
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
|
-
|
1126
|
+
# 消写后
|
1127
|
+
release_wmems( src_info, continue_src_pack_id )
|
1290
1128
|
|
1291
1129
|
# 发miss
|
1292
|
-
if !
|
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 =
|
1133
|
+
curr_pack_id = src_info[ :continue_dst_pack_id ] + 1
|
1296
1134
|
|
1297
|
-
|
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 #{
|
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
|
-
|
1318
|
-
|
1319
|
-
|
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
|
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
|
-
|
1328
|
-
return unless
|
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 =
|
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[ :
|
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
|
-
|
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 ][
|
1229
|
+
src_id = @tun_info[ :src_ids ][ dst_id ]
|
1346
1230
|
return unless src_id
|
1347
1231
|
|
1348
|
-
|
1349
|
-
return unless
|
1232
|
+
src = @tun_info[ :srcs ][ src_id ]
|
1233
|
+
return unless src
|
1350
1234
|
|
1351
|
-
|
1352
|
-
|
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
|
-
|
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(
|
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
|
-
|
1250
|
+
dst_id = data[ 9, 2 ].unpack( 'n' ).first
|
1364
1251
|
|
1365
|
-
src_id = @tun_info[ :src_ids ][
|
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
|
-
|
1274
|
+
dst_id = data[ 8, 2 ].unpack( 'n' ).first
|
1388
1275
|
|
1389
|
-
src_id = @tun_info[ :src_ids ][
|
1276
|
+
src_id = @tun_info[ :src_ids ][ dst_id ]
|
1390
1277
|
return unless src_id
|
1391
1278
|
|
1392
|
-
|
1393
|
-
return
|
1394
|
-
|
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 -
|
1407
|
-
while
|
1408
|
-
data <<
|
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
|
-
|
1413
|
-
|
1414
|
-
add_src_wbuff(
|
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
|
-
#
|
1418
|
-
if
|
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(
|
1311
|
+
set_is_closing( src )
|
1421
1312
|
end
|
1422
|
-
|
1423
|
-
|
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
|
|