girl 0.88.0 → 0.89.0

This diff has not been reviewed by any users.
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b93e96a7869493e3817af21b5a482605adbe9be7a4d4156b14eed2a6b40c25d5
4
- data.tar.gz: 4adea82e1e09ce9cb2b1da33f05618d8bd3837bd50bd452b8d99631e523a040b
3
+ metadata.gz: 8a1e3e17f5d9ca7e92f7c61d52732b78e80b93fcaf9c39c19cb0d4ebc0bb353c
4
+ data.tar.gz: 981a168ddcda54ccbddc39acb0dec0af00b018f1fba64ffd04444f584d306671
5
5
  SHA512:
6
- metadata.gz: 38d15c8e1104feb3079c6ee14af795adb319808c9899c6013b28cf3cf4d082b9c1feca3160d95cbf67beb88343a202a823b2e1b823591fcbc3abb7b040a19839
7
- data.tar.gz: 8e1f3255a7c297e33dd0ee6931483584760198ba0559936ac213b62a900451a8658749ded5dc1ebb490ab45958a4e8c7a0bfea6756047955d358b4c4cafa6d6d
6
+ metadata.gz: '08f46bb81ff9d4ad4767aad8528e7c7c899f9c305db62f1dcb5079f3ebea28aed0ffc49946ac2b3503303c8dd807e9b27204c0042d3aca73f3c06e42881d294b'
7
+ data.tar.gz: 533abffc741dcb060bfc80bf6ac9cdae98a3be4f38d70a7a2e3a0cd3df5eef2b617a961b66d965a306e5adab3d9464fbd3cec7ecd6bddf1b34cbe9cc8acd03c8
@@ -1,33 +1,32 @@
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
- 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"
2
+ READ_SIZE = 1024 * 1024 # 一次读多少
3
+ WBUFF_LIMIT = 100 * 1024 * 1024 # 写前上限,超过上限暂停读src/dst
4
+ RESUME_BELOW = WBUFF_LIMIT / 2 # 降到多少以下恢复读
5
+ SEND_HELLO_COUNT = 10 # hello最多发几次
6
+ EXPIRE_AFTER = 300 # 多久没有新流量,过期
7
+ CHECK_EXPIRE_INTERVAL = 30 # 检查过期间隔
8
+ CHECK_RESUME_INTERVAL = 1 # 检查恢复读间隔
9
+ RESOLV_CACHE_EXPIRE = 300 # dns查询结果缓存多久过期
10
+ TUND_PORT = 1
11
+ HEARTBEAT = 2
12
+ A_NEW_SOURCE = 3
13
+ PAIRED = 4
14
+ DEST_STATUS = 5
15
+ SOURCE_STATUS = 6
16
+ MISS = 7
17
+ FIN1 = 8
18
+ GOT_FIN1 = 9
19
+ FIN2 = 10
20
+ GOT_FIN2 = 11
21
+ TUND_FIN = 12
22
+ TUN_FIN = 13
23
+ IP_CHANGED = 14
24
+ SINGLE_MISS = 15
25
+ RANGE_MISS = 16
26
+ CONTINUE = 17
27
+ IS_RESEND_READY = 18
28
+ RESEND_READY = 19
29
+ HTTP_OK = "HTTP/1.1 200 OK\r\n\r\n"
31
30
  # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
32
31
  RESERVED_ROUTE = <<EOF
33
32
  0.0.0.0/8
@@ -38,4 +37,14 @@ module Girl
38
37
  192.168.0.0/16
39
38
  255.255.255.255/32
40
39
  EOF
40
+ CONSTS = %w[
41
+ READ_SIZE
42
+ WBUFF_LIMIT
43
+ RESUME_BELOW
44
+ SEND_HELLO_COUNT
45
+ EXPIRE_AFTER
46
+ CHECK_EXPIRE_INTERVAL
47
+ CHECK_RESUME_INTERVAL
48
+ RESOLV_CACHE_EXPIRE
49
+ ]
41
50
  end
@@ -7,67 +7,50 @@ require 'ipaddr'
7
7
  require 'json'
8
8
  require 'socket'
9
9
 
10
- ##
10
+ =begin
11
11
  # Girl::Proxy - 代理服务,近端。
12
- #
13
- # 包结构
14
- # ======
15
- #
16
- # tun-proxyd:
17
- #
18
- # hello
19
- #
20
- # proxyd-tun:
21
- #
22
- # Q>: 0 ctlmsg -> C: 1 tund port -> n: tund port
23
- #
24
- # tun-tund:
25
- #
26
- # Q>: 0 ctlmsg -> C: 2 heartbeat -> C: random char
27
- # 3 a new source -> Q>: src id -> encoded destination address
28
- # 4 paired -> Q>: src id -> n: dst port
29
- # 5 dest status -> n: dst port -> Q>: biggest relayed dst pack id -> Q>: continue src pack id
30
- # 6 source status -> Q>: src id -> Q>: biggest relayed src pack id -> Q>: continue dst pack id
31
- # 7 miss -> Q>/n: src id / dst port -> Q>: pack id begin -> Q>: pack id end
32
- # 8 fin1 -> Q>/n: src id / dst port -> Q>: biggest src pack id / biggest dst pack id -> Q>: continue dst pack id / continue src pack id
33
- # 9 not use
34
- # 10 fin2 -> Q>/n: src id / dst port
35
- # 11 not use
36
- # 12 tund fin
37
- # 13 tun fin
38
- # 14 tun ip changed
39
- # 15 multi miss -> Q>/n: src id / dst port -> Q>: pack id begin -> Q>: pack id end -> Q>*
40
- #
41
- # Q>: 1+ pack_id -> Q>/n: src id / dst port -> traffic
42
- #
43
- # close logic
44
- # ===========
45
- #
46
- # 1-1. after close src -> dst closed ? no -> send fin1
47
- # 1-2. tun recv fin2 -> del src ext
48
- #
49
- # 2-1. tun recv fin1 -> all traffic received ? -> close src after write
50
- # 2-2. tun recv traffic -> dst closed and all traffic received ? -> close src after write
51
- # 2-3. after close src -> dst closed ? yes -> del src ext -> send fin2
52
- #
53
- # 3-1. after close dst -> src closed ? no -> send fin1
54
- # 3-2. tund recv fin2 -> del dst ext
55
- #
56
- # 4-1. tund recv fin1 -> all traffic received ? -> close dst after write
57
- # 4-2. tund recv traffic -> src closed and all traffic received ? -> close dst after write
58
- # 4-3. after close dst -> src closed ? yes -> del dst ext -> send fin2
59
- #
12
+
13
+ ## 包结构
14
+
15
+ tun-proxyd:
16
+
17
+ hello
18
+
19
+ proxyd-tun:
20
+
21
+ Q>: 0 ctlmsg -> C: 1 tund port -> n: tund port -> n: tcpd port
22
+
23
+ tun-tund:
24
+
25
+ Q>: 0 ctlmsg -> C: 2 heartbeat not use
26
+ 3 a new source -> Q>: src id -> encoded destination address
27
+ 4 paired -> Q>: src id -> n: dst id
28
+ 5 dest status not use
29
+ 6 source status not use
30
+ 7 miss not use
31
+ 8 fin1 not use
32
+ 9 confirm fin1 not use
33
+ 10 fin2 not use
34
+ 11 confirm fin2 not use
35
+ 12 tund fin
36
+ 13 tun fin
37
+ 14 tun ip changed
38
+ 15 single miss not use
39
+ 16 range miss not use
40
+ 17 continue not use
41
+ 18 is resend ready not use
42
+ 19 resend ready not use
43
+ =end
44
+
60
45
  module Girl
61
46
  class Proxy
62
47
 
63
48
  def initialize( config_path = nil )
64
- unless config_path
49
+ unless config_path then
65
50
  config_path = File.expand_path( '../girl.conf.json', __FILE__ )
66
51
  end
67
52
 
68
- unless File.exist?( config_path )
69
- raise "missing config file #{ config_path }"
70
- end
53
+ raise "missing config file #{ config_path }" unless File.exist?( config_path )
71
54
 
72
55
  # {
73
56
  # "proxy_port": 6666, // 代理服务,近端(本地)端口
@@ -87,45 +70,37 @@ module Girl
87
70
  im = conf[ :im ]
88
71
  worker_count = conf[ :worker_count ]
89
72
 
90
- unless proxy_port
73
+ unless proxy_port then
91
74
  proxy_port = 6666
92
75
  end
93
76
 
94
- unless proxyd_host
95
- raise "missing proxyd host"
96
- end
77
+ raise "missing proxyd host" unless proxyd_host
97
78
 
98
- unless proxyd_port
79
+ unless proxyd_port then
99
80
  proxyd_port = 6060
100
81
  end
101
82
 
102
83
  directs = []
103
84
 
104
- if direct_path
105
- unless File.exist?( direct_path )
106
- raise "not found direct file #{ direct_path }"
107
- end
108
-
85
+ if direct_path then
86
+ raise "not found direct file #{ direct_path }" unless File.exist?( direct_path )
109
87
  directs = ( RESERVED_ROUTE.split( "\n" ) + IO.binread( direct_path ).split( "\n" ) ).map { | line | IPAddr.new( line.strip ) }
110
88
  end
111
89
 
112
90
  remotes = []
113
91
 
114
- if remote_path
115
- unless File.exist?( remote_path )
116
- raise "not found remote file #{ remote_path }"
117
- end
118
-
92
+ if remote_path then
93
+ raise "not found remote file #{ remote_path }" unless File.exist?( remote_path )
119
94
  remotes = IO.binread( remote_path ).split( "\n" ).map { | line | line.strip }
120
95
  end
121
96
 
122
- unless im
97
+ unless im then
123
98
  im = 'girl'
124
99
  end
125
100
 
126
101
  nprocessors = Etc.nprocessors
127
102
 
128
- if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors
103
+ if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors then
129
104
  worker_count = nprocessors
130
105
  end
131
106
 
@@ -139,29 +114,13 @@ module Girl
139
114
  puts "im #{ im }"
140
115
  puts "worker count #{ worker_count }"
141
116
 
142
- names = %w[
143
- PACK_SIZE
144
- READ_SIZE
145
- WMEMS_LIMIT
146
- RESUME_BELOW
147
- EXPIRE_NEW
148
- EXPIRE_AFTER
149
- CHECK_EXPIRE_INTERVAL
150
- CHECK_STATUS_INTERVAL
151
- SEND_STATUS_UNTIL
152
- MULTI_MISS_SIZE
153
- MISS_RANGE_LIMIT
154
- CONFUSE_UNTIL
155
- RESOLV_CACHE_EXPIRE
156
- ]
157
-
158
- len = names.map{ | name | name.size }.max
159
-
160
- names.each do | name |
117
+ len = CONSTS.map{ | name | name.size }.max
118
+
119
+ CONSTS.each do | name |
161
120
  puts "#{ name.gsub( '_', ' ' ).ljust( len ) } #{ Girl.const_get( name ) }"
162
121
  end
163
122
 
164
- if RUBY_PLATFORM.include?( 'linux' )
123
+ if RUBY_PLATFORM.include?( 'linux' ) then
165
124
  $0 = title
166
125
  workers = []
167
126
 
@@ -7,16 +7,17 @@ module Girl
7
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
+ @proxyd_ip = Addrinfo.new( @proxyd_addr ).ip_address
10
11
  @directs = directs
11
12
  @remotes = remotes
12
13
  @custom = Girl::ProxyCustom.new( im )
13
14
  @mutex = Mutex.new
14
15
  @reads = []
15
16
  @writes = []
16
- @pause_srcs = []
17
- @roles = {} # sock => :dotr / :proxy / :src / :dst / :tun
17
+ @roles = {} # sock => :dotr / :proxy / :src / :dst / :tun / :stream
18
18
  @src_infos = {} # src => {}
19
19
  @dst_infos = {} # dst => {}
20
+ @stream_infos = {} # stream => {}
20
21
  @resolv_caches = {} # domain => [ ip, created_at ]
21
22
 
22
23
  dotr, dotw = IO.pipe
@@ -31,36 +32,40 @@ module Girl
31
32
  def looping
32
33
  puts "p#{ Process.pid } #{ Time.new } looping"
33
34
  loop_check_expire
34
- loop_check_status
35
+ loop_check_resume
35
36
 
36
37
  loop do
37
38
  rs, ws = IO.select( @reads, @writes )
38
39
 
39
40
  @mutex.synchronize do
40
- # 先写,再读
41
- ws.each do | sock |
42
- case @roles[ sock ]
43
- when :src
44
- write_src( sock )
45
- when :dst
46
- write_dst( sock )
47
- when :tun
48
- write_tun( sock )
49
- end
50
- end
51
-
41
+ # 先读,再写,避免打上关闭标记后读到
52
42
  rs.each do | sock |
53
43
  case @roles[ sock ]
54
- when :dotr
44
+ when :dotr then
55
45
  read_dotr( sock )
56
- when :proxy
46
+ when :proxy then
57
47
  read_proxy( sock )
58
- when :src
48
+ when :tun then
49
+ read_tun( sock )
50
+ when :src then
59
51
  read_src( sock )
60
- when :dst
52
+ when :dst then
61
53
  read_dst( sock )
62
- when :tun
63
- read_tun( sock )
54
+ when :stream then
55
+ read_stream( sock )
56
+ end
57
+ end
58
+
59
+ ws.each do | sock |
60
+ case @roles[ sock ]
61
+ when :tun then
62
+ write_tun( sock )
63
+ when :src then
64
+ write_src( sock )
65
+ when :dst then
66
+ write_dst( sock )
67
+ when :stream then
68
+ write_stream( sock )
64
69
  end
65
70
  end
66
71
  end
@@ -74,7 +79,7 @@ module Girl
74
79
  # quit!
75
80
  #
76
81
  def quit!
77
- if @tun && !@tun.closed? && @tun_info[ :tund_addr ]
82
+ if @tun && !@tun.closed? && @tun_info[ :tund_addr ] then
78
83
  # puts "debug1 send tun fin"
79
84
  data = [ 0, TUN_FIN ].pack( 'Q>C' )
80
85
  @tun.sendmsg( data, 0, @tun_info[ :tund_addr ] )
@@ -86,6 +91,256 @@ module Girl
86
91
 
87
92
  private
88
93
 
94
+ ##
95
+ # add ctlmsg
96
+ #
97
+ def add_ctlmsg( data, to_addr = nil )
98
+ unless to_addr then
99
+ to_addr = @tun_info[ :tund_addr ]
100
+ end
101
+
102
+ if to_addr then
103
+ @tun_info[ :ctlmsgs ] << [ data, to_addr ]
104
+ add_write( @tun )
105
+ end
106
+ end
107
+
108
+ ##
109
+ # add read
110
+ #
111
+ def add_read( sock, role = nil )
112
+ unless @reads.include?( sock ) then
113
+ @reads << sock
114
+
115
+ if role then
116
+ @roles[ sock ] = role
117
+ end
118
+ end
119
+ end
120
+
121
+ ##
122
+ # add src wbuff
123
+ #
124
+ def add_src_wbuff( src, data )
125
+ return if src.closed?
126
+ src_info = @src_infos[ src ]
127
+ src_info[ :wbuff ] << data
128
+ add_write( src )
129
+ src_info[ :last_recv_at ] = Time.new
130
+ end
131
+
132
+ ##
133
+ # add src wbuff socks5 conn reply
134
+ #
135
+ def add_src_wbuff_socks5_conn_reply( src )
136
+ # +----+-----+-------+------+----------+----------+
137
+ # |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
138
+ # +----+-----+-------+------+----------+----------+
139
+ # | 1 | 1 | X'00' | 1 | Variable | 2 |
140
+ # +----+-----+-------+------+----------+----------+
141
+ proxy_ip, proxy_port = @proxy_local_address.ip_unpack
142
+ data = [ [ 5, 0, 0, 1 ].pack( 'C4' ), IPAddr.new( proxy_ip ).hton, [ proxy_port ].pack( 'n' ) ].join
143
+ # puts "debug1 add src wbuff socks5 conn reply #{ data.inspect }"
144
+ add_src_wbuff( src, data )
145
+ end
146
+
147
+ ##
148
+ # add write
149
+ #
150
+ def add_write( sock )
151
+ unless @writes.include?( sock ) then
152
+ @writes << sock
153
+ end
154
+ end
155
+
156
+ ##
157
+ # close sock
158
+ #
159
+ def close_sock( sock )
160
+ sock.close
161
+ @reads.delete( sock )
162
+ @writes.delete( sock )
163
+ @roles.delete( sock )
164
+ end
165
+
166
+ ##
167
+ # close dst
168
+ #
169
+ def close_dst( dst )
170
+ # puts "debug1 close dst"
171
+ close_sock( dst )
172
+ @dst_infos.delete( dst )
173
+ end
174
+
175
+ ##
176
+ # close read src
177
+ #
178
+ def close_read_src( src )
179
+ return if src.closed?
180
+ # puts "debug1 close read src"
181
+ src.close_read
182
+ @reads.delete( src )
183
+
184
+ if src.closed? then
185
+ # puts "debug1 delete src info"
186
+ @roles.delete( src )
187
+ src_info = del_src_info( src )
188
+ else
189
+ src_info = @src_infos[ src ]
190
+ end
191
+
192
+ src_info[ :paused ] = false
193
+ src_info
194
+ end
195
+
196
+ ##
197
+ # close read dst
198
+ #
199
+ def close_read_dst( dst )
200
+ return if dst.closed?
201
+ # puts "debug1 close read dst"
202
+ dst.close_read
203
+ @reads.delete( dst )
204
+
205
+ if dst.closed? then
206
+ # puts "debug1 delete dst info"
207
+ @roles.delete( dst )
208
+ dst_info = @dst_infos.delete( dst )
209
+ else
210
+ dst_info = @dst_infos[ dst ]
211
+ end
212
+
213
+ dst_info
214
+ end
215
+
216
+ ##
217
+ # close read stream
218
+ #
219
+ def close_read_stream( stream )
220
+ return if stream.closed?
221
+ # puts "debug1 close read stream"
222
+ stream.close_read
223
+ @reads.delete( stream )
224
+
225
+ if stream.closed? then
226
+ # puts "debug1 delete stream info"
227
+ @roles.delete( stream )
228
+ stream_info = @stream_infos.delete( stream )
229
+ else
230
+ stream_info = @stream_infos[ stream ]
231
+ end
232
+
233
+ stream_info
234
+ end
235
+
236
+ ##
237
+ # close src
238
+ #
239
+ def close_src( src )
240
+ # puts "debug1 close src"
241
+ close_sock( src )
242
+ del_src_info( src )
243
+ end
244
+
245
+ ##
246
+ # close tun
247
+ #
248
+ def close_tun( tun )
249
+ # puts "debug1 close tun"
250
+ close_sock( tun )
251
+ @tun_info[ :srcs ].each{ | _, src | set_src_closing( src ) }
252
+ end
253
+
254
+ ##
255
+ # close write src
256
+ #
257
+ def close_write_src( src )
258
+ return if src.closed?
259
+ # puts "debug1 close write src"
260
+ src.close_write
261
+ @writes.delete( src )
262
+
263
+ if src.closed? then
264
+ # puts "debug1 delete src info"
265
+ @roles.delete( src )
266
+ src_info = del_src_info( src )
267
+ else
268
+ src_info = @src_infos[ src ]
269
+ end
270
+
271
+ src_info
272
+ end
273
+
274
+ ##
275
+ # close write dst
276
+ #
277
+ def close_write_dst( dst )
278
+ return if dst.closed?
279
+ # puts "debug1 close write dst"
280
+ dst.close_write
281
+ @writes.delete( dst )
282
+
283
+ if dst.closed? then
284
+ # puts "debug1 delete dst info"
285
+ @roles.delete( dst )
286
+ dst_info = @dst_infos.delete( dst )
287
+ else
288
+ dst_info = @dst_infos[ dst ]
289
+ end
290
+
291
+ dst_info
292
+ end
293
+
294
+ ##
295
+ # close write stream
296
+ #
297
+ def close_write_stream( stream )
298
+ return if stream.closed?
299
+ # puts "debug1 close write stream"
300
+ stream.close_write
301
+ @writes.delete( stream )
302
+
303
+ if stream.closed? then
304
+ # puts "debug1 delete stream info"
305
+ @roles.delete( stream )
306
+ stream_info = @stream_infos.delete( stream )
307
+ else
308
+ stream_info = @stream_infos[ stream ]
309
+ end
310
+
311
+ stream_info
312
+ end
313
+
314
+ ##
315
+ # deal with destination ip
316
+ #
317
+ def deal_with_destination_ip( src, ip_info )
318
+ src_info = @src_infos[ src ]
319
+
320
+ if ( @directs.any? { | direct | direct.include?( ip_info.ip_address ) } ) || ( ( src_info[ :destination_domain ] == @proxyd_host ) && ![ 80, 443 ].include?( src_info[ :destination_port ] ) ) then
321
+ # ip命中直连列表,或者访问远端非80/443端口,直连
322
+ # puts "debug1 #{ ip_info.inspect } hit directs"
323
+ new_a_dst( src, ip_info )
324
+ else
325
+ # 走远端
326
+ # puts "debug1 #{ ip_info.inspect } go tunnel"
327
+ set_src_proxy_type_tunnel( src )
328
+ end
329
+ end
330
+
331
+ ##
332
+ # del src info
333
+ #
334
+ def del_src_info( src )
335
+ src_info = @src_infos.delete( src )
336
+
337
+ if src_info[ :stream ] && @tun && !@tun.closed? then
338
+ @tun_info[ :srcs ].delete( src_info[ :id ] )
339
+ end
340
+
341
+ src_info
342
+ end
343
+
89
344
  ##
90
345
  # loop check expire
91
346
  #
@@ -98,133 +353,70 @@ module Girl
98
353
  trigger = false
99
354
  now = Time.new
100
355
 
101
- if @tun && !@tun.closed?
102
- is_expired = @tun_info[ :last_recv_at ] ? ( now - @tun_info[ :last_recv_at ] > EXPIRE_AFTER ) : ( now - @tun_info[ :created_at ] > EXPIRE_NEW )
356
+ if @tun && !@tun.closed? then
357
+ last_recv_at = @tun_info[ :last_recv_at ] || @tun_info[ :created_at ]
358
+ last_sent_at = @tun_info[ :last_sent_at ] || @tun_info[ :created_at ]
103
359
 
104
- if is_expired
360
+ if @tun_info[ :srcs ].empty? && ( now - last_recv_at >= EXPIRE_AFTER ) && ( now - last_sent_at >= EXPIRE_AFTER ) then
105
361
  puts "p#{ Process.pid } #{ Time.new } expire tun"
106
- set_is_closing( @tun )
362
+ set_tun_closing
107
363
  trigger = true
108
- else
109
- data = [ 0, HEARTBEAT, rand( 128 ) ].pack( 'Q>CC' )
110
- # puts "debug1 #{ Time.new } heartbeat"
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_pack_id, _ | src_id_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
125
- end
126
- end
127
-
128
- if del_src_ids.any?
129
- @tun_info[ :srcs ].delete_if { | src_id, _ | del_src_ids.include?( src_id ) }
130
- end
131
364
  end
132
365
  end
133
366
 
134
367
  @src_infos.each do | src, src_info |
135
- if now - src_info[ :last_continue_at ] > EXPIRE_AFTER
136
- puts "p#{ Process.pid } #{ Time.new } expire src #{ src_info[ :destination_domain ] }"
137
- set_is_closing( src )
138
- trigger = true
139
- end
140
- end
368
+ last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
369
+ last_sent_at = src_info[ :last_sent_at ] || src_info[ :created_at ]
141
370
 
142
- @dst_infos.each do | dst, dst_info |
143
- if now - dst_info[ :last_continue_at ] > EXPIRE_AFTER
144
- puts "p#{ Process.pid } #{ Time.new } expire dst #{ dst_info[ :domain ] }"
145
- set_is_closing( dst )
371
+ if ( now - last_recv_at >= EXPIRE_AFTER ) && ( now - last_sent_at >= EXPIRE_AFTER ) then
372
+ puts "p#{ Process.pid } #{ Time.new } expire src #{ src_info[ :destination_domain ] }"
373
+ set_src_closing( src )
146
374
  trigger = true
147
375
  end
148
376
  end
149
377
 
150
- if trigger
151
- next_tick
152
- end
378
+ next_tick if trigger
153
379
  end
154
380
  end
155
381
  end
156
382
  end
157
383
 
158
384
  ##
159
- # loop check status
385
+ # loop check resume
160
386
  #
161
- def loop_check_status
387
+ def loop_check_resume
162
388
  Thread.new do
163
389
  loop do
164
- sleep CHECK_STATUS_INTERVAL
390
+ sleep CHECK_RESUME_INTERVAL
165
391
 
166
392
  @mutex.synchronize do
167
- if @tun && !@tun.closed? && @tun_info[ :tund_addr ]
168
- if @tun_info[ :srcs ].any?
169
- now = Time.new
170
-
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 ] )
177
- end
178
- end
179
- end
393
+ trigger = false
180
394
 
181
- if @pause_srcs.any? && ( @tun_info[ :wmems ].size < RESUME_BELOW )
182
- trigger = false
395
+ @src_infos.select{ | _, src_info | src_info[ :paused ] }.each do | src, src_info |
396
+ dst = src_info[ :dst ]
183
397
 
184
- @pause_srcs.each do | src |
185
- src_info = @src_infos[ src ]
398
+ if dst then
399
+ dst_info = @dst_infos[ dst ]
186
400
 
187
- if src_info
188
- puts "p#{ Process.pid } #{ Time.new } resume src #{ src_info[ :destination_domain ] }"
189
- add_read( src )
190
- trigger = true
191
- end
401
+ if dst_info[ :wbuff ].size < RESUME_BELOW then
402
+ puts "p#{ Process.pid } #{ Time.new } dst.wbuff below #{ RESUME_BELOW }, resume src #{ src_info[ :destination_domain ] }"
403
+ resume_src( src )
404
+ trigger = true
192
405
  end
406
+ else
407
+ stream = src_info[ :stream ]
408
+ stream_info = @stream_infos[ stream ]
193
409
 
194
- @pause_srcs.clear
195
-
196
- if trigger
197
- next_tick
410
+ if stream_info[ :wbuff ].size < RESUME_BELOW then
411
+ puts "p#{ Process.pid } #{ Time.new } stream.wbuff below #{ RESUME_BELOW }, resume src #{ src_info[ :destination_domain ] }"
412
+ resume_src( src )
413
+ trigger = true
198
414
  end
199
415
  end
200
416
  end
201
- end
202
- end
203
- end
204
- end
205
-
206
- ##
207
- # loop send hello
208
- #
209
- def loop_send_hello
210
- data = @custom.hello
211
-
212
- Thread.new do
213
- EXPIRE_NEW.times do | i |
214
- if @tun.closed? || @tun_info[ :tund_addr ]
215
- # puts "debug1 break loop send hello"
216
- break
217
- end
218
-
219
- @mutex.synchronize do
220
- msg = i >= 1 ? "resend hello #{ i }" : "hello i'm tun"
221
- puts "p#{ Process.pid } #{ Time.new } #{ msg }"
222
- # puts "debug1 #{ data.inspect }"
223
417
 
224
- send_data( @tun, data, @proxyd_addr )
418
+ next_tick if trigger
225
419
  end
226
-
227
- sleep CHECK_STATUS_INTERVAL
228
420
  end
229
421
  end
230
422
  end
@@ -235,98 +427,137 @@ module Girl
235
427
  def loop_send_a_new_source( src )
236
428
  src_info = @src_infos[ src ]
237
429
 
238
- if src_info
430
+ if src_info then
239
431
  destination_domain = src_info[ :destination_domain ]
240
432
  destination_port = src_info[ :destination_port ]
241
433
  domain_port = [ destination_domain, destination_port ].join( ':' )
242
434
  data = [ [ 0, A_NEW_SOURCE, src_info[ :id ] ].pack( 'Q>CQ>' ), @custom.encode( domain_port ) ].join
243
435
 
244
436
  Thread.new do
245
- EXPIRE_NEW.times do | i |
246
- if @tun.nil? || @tun.closed? || src.closed? || src_info[ :dst_id ]
437
+ SEND_HELLO_COUNT.times do | i |
438
+ if @tun.nil? || @tun.closed? || src.closed? || src_info[ :stream ] then
247
439
  # puts "debug1 break loop send a new source #{ src_info[ :dst_port ] }"
248
440
  break
249
441
  end
250
442
 
251
443
  @mutex.synchronize do
252
- if i >= 1
444
+ if i >= 1 then
253
445
  puts "p#{ Process.pid } #{ Time.new } resend a new source #{ domain_port } #{ i }"
254
446
  end
255
447
 
256
- send_data( @tun, data, @tun_info[ :tund_addr ] )
448
+ add_ctlmsg( data )
449
+ next_tick
257
450
  end
258
451
 
259
- sleep CHECK_STATUS_INTERVAL
452
+ sleep 1
260
453
  end
261
454
  end
262
455
  end
263
456
  end
264
457
 
265
458
  ##
266
- # resolve domain
459
+ # new a dst
267
460
  #
268
- def resolve_domain( src, domain )
269
- if @remotes.any? { | remote | ( domain.size >= remote.size ) && ( domain[ ( remote.size * -1 )..-1 ] == remote ) }
270
- # puts "debug1 #{ domain } hit remotes"
271
- new_a_src_ext( src )
461
+ def new_a_dst( src, ip_info )
462
+ src_info = @src_infos[ src ]
463
+ domain = src_info[ :destination_domain ]
464
+ destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
465
+ dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
466
+ dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 ) if RUBY_PLATFORM.include?( 'linux' )
467
+
468
+ begin
469
+ dst.connect_nonblock( destination_addr )
470
+ rescue IO::WaitWritable
471
+ # connect nonblock 必抛 wait writable
472
+ rescue Exception => e
473
+ puts "p#{ Process.pid } #{ Time.new } dst connect destination #{ e.class }, close src"
474
+ set_src_closing( src )
272
475
  return
273
476
  end
274
477
 
275
- resolv_cache = @resolv_caches[ domain ]
478
+ # puts "debug1 a new dst #{ dst.local_address.inspect }"
479
+ local_port = dst.local_address.ip_port
480
+ dst_info = {
481
+ local_port: local_port, # 本地端口
482
+ src: src, # 对应src
483
+ domain: domain, # 域名
484
+ wbuff: '', # 写前,从src读到的流量
485
+ closing: false, # 准备关闭
486
+ closing_read: false, # 准备关闭读
487
+ closing_write: false # 准备关闭写
488
+ }
276
489
 
277
- if resolv_cache
278
- ip_info, created_at = resolv_cache
490
+ @dst_infos[ dst ] = dst_info
491
+ add_read( dst, :dst )
492
+ src_info[ :proxy_type ] = :direct
493
+ src_info[ :dst ] = dst
279
494
 
280
- if Time.new - created_at < RESOLV_CACHE_EXPIRE
281
- # puts "debug1 #{ domain } hit resolv cache #{ ip_info.inspect }"
282
- deal_with_destination_ip( src, ip_info )
283
- return
495
+ if src_info[ :proxy_proto ] == :http then
496
+ if src_info[ :is_connect ] then
497
+ # puts "debug1 add src.wbuff http ok"
498
+ add_src_wbuff( src, HTTP_OK )
499
+ elsif src_info[ :rbuff ] then
500
+ # puts "debug1 move src.rbuff to dst.wbuff"
501
+ dst_info[ :wbuff ] << src_info[ :rbuff ]
502
+ add_write( dst )
284
503
  end
285
-
286
- # puts "debug1 expire #{ domain } resolv cache"
287
- @resolv_caches.delete( domain )
504
+ elsif src_info[ :proxy_proto ] == :socks5 then
505
+ add_src_wbuff_socks5_conn_reply( src )
288
506
  end
507
+ end
508
+
509
+ ##
510
+ # new a stream
511
+ #
512
+ def new_a_stream( src_id, dst_id )
513
+ src = @tun_info[ :srcs ][ src_id ]
514
+ return if src.nil? || src.closed?
289
515
 
290
516
  src_info = @src_infos[ src ]
291
- src_info[ :proxy_type ] = :checking
517
+ return if src_info[ :dst_id ]
292
518
 
293
- Thread.new do
294
- begin
295
- ip_info = Addrinfo.ip( domain )
296
- rescue Exception => e
297
- puts "p#{ Process.pid } #{ Time.new } resolv #{ domain } #{ e.class }"
298
- end
519
+ if dst_id == 0 then
520
+ puts "p#{ Process.pid } #{ Time.new } remote dst already closed"
521
+ set_src_closing( src )
522
+ return
523
+ end
299
524
 
300
- @mutex.synchronize do
301
- if ip_info
302
- @resolv_caches[ domain ] = [ ip_info, Time.new ]
525
+ stream = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
526
+ stream.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 ) if RUBY_PLATFORM.include?( 'linux' )
303
527
 
304
- unless src.closed?
305
- puts "p#{ Process.pid } #{ Time.new } resolved #{ domain } #{ ip_info.ip_address }"
306
- deal_with_destination_ip( src, ip_info )
307
- end
308
- else
309
- set_is_closing( src )
310
- end
528
+ begin
529
+ stream.connect_nonblock( @tun_info[ :tcpd_addr ] )
530
+ rescue IO::WaitWritable
531
+ rescue Exception => e
532
+ puts "p#{ Process.pid } #{ Time.new } connect tcpd #{ e.class }"
533
+ return
534
+ end
311
535
 
312
- next_tick
313
- end
536
+ # puts "debug1 set stream.wbuff #{ dst_id }"
537
+ data = [ dst_id ].pack( 'n' )
538
+
539
+ unless src_info[ :rbuff ].empty? then
540
+ # puts "debug1 encode and move src.rbuff to stream.wbuff"
541
+ data << @custom.encode( src_info[ :rbuff ] )
314
542
  end
315
- end
316
543
 
317
- ##
318
- # deal with destination ip
319
- #
320
- def deal_with_destination_ip( src, ip_info )
321
- src_info = @src_infos[ src ]
544
+ @stream_infos[ stream ] = {
545
+ src: src, # 对应src
546
+ wbuff: data # 写前,写往远端streamd
547
+ }
322
548
 
323
- if ( @directs.any? { | direct | direct.include?( ip_info.ip_address ) } ) || ( ( src_info[ :destination_domain ] == @proxyd_host ) && ![ 80, 443 ].include?( src_info[ :destination_port ] ) )
324
- # ip命中直连列表,或者访问远端非80/443端口,直连
325
- # puts "debug1 #{ ip_info.inspect } hit directs"
326
- new_a_dst( src, ip_info )
327
- else
328
- # 走远端
329
- new_a_src_ext( src )
549
+ src_info[ :dst_id ] = dst_id
550
+ src_info[ :stream ] = stream
551
+ add_read( stream, :stream )
552
+ add_write( stream )
553
+
554
+ if src_info[ :proxy_proto ] == :http then
555
+ if src_info[ :is_connect ] then
556
+ # puts "debug1 add src.wbuff http ok"
557
+ add_src_wbuff( src, HTTP_OK )
558
+ end
559
+ elsif src_info[ :proxy_proto ] == :socks5 then
560
+ add_src_wbuff_socks5_conn_reply( src )
330
561
  end
331
562
  end
332
563
 
@@ -337,13 +568,13 @@ module Girl
337
568
  proxy = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
338
569
  proxy.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
339
570
 
340
- if RUBY_PLATFORM.include?( 'linux' )
571
+ if RUBY_PLATFORM.include?( 'linux' ) then
341
572
  proxy.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
342
573
  proxy.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
343
574
  end
344
575
 
345
576
  proxy.bind( Socket.sockaddr_in( proxy_port, '0.0.0.0' ) )
346
- proxy.listen( 511 )
577
+ proxy.listen( 127 )
347
578
  puts "p#{ Process.pid } #{ Time.new } proxy listen on #{ proxy_port }"
348
579
  add_read( proxy, :proxy )
349
580
  @proxy_local_address = proxy.local_address
@@ -357,451 +588,250 @@ module Girl
357
588
  tun.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
358
589
  port = tun.local_address.ip_port
359
590
  tun_info = {
360
- port: port, # 端口
361
- pending_sources: [], # 还没配上tund,暂存的src
362
- wbuffs: [], # 写前 [ src_id, pack_id, data ]
363
- wmems: {}, # 写后 [ src_id, pack_id ] => data
364
- tund_addr: nil, # tund地址
365
- srcs: {}, # src_id => src
366
- src_ids: {}, # dst_id => src_id
367
- created_at: Time.new, # 创建时间
368
- last_recv_at: nil, # 上一次收到流量的时间,过期关闭
369
- is_closing: false # 是否准备关闭
591
+ port: port, # 端口
592
+ pending_sources: [], # 还没配上tund,暂存的src
593
+ ctlmsgs: [], # [ ctlmsg, to_addr ]
594
+ resend_newers: {}, # 尾巴流量重传队列 src_id => newer_pack_ids
595
+ resend_singles: {}, # 单个重传队列 src_id => single_miss_pack_ids
596
+ resend_ranges: {}, # 区间重传队列 src_id => range_miss_pack_ids
597
+ event_srcs: [], # rbuff不为空,或者准备关闭的src
598
+ tund_addr: nil, # tund地址
599
+ tcpd_addr: nil, # tcpd地址
600
+ srcs: {}, # src_id => src
601
+ created_at: Time.new, # 创建时间
602
+ last_recv_at: nil, # 上一次收到流量的时间
603
+ last_sent_at: nil, # 上一次发出流量的时间
604
+ sender_addrs: nil, # 远端发送者地址
605
+ last_ping_senders_at: nil, # 上一次ping发送者的时间
606
+ closing: false # 是否准备关闭
370
607
  }
371
608
 
372
609
  @tun = tun
373
610
  @tun_info = tun_info
374
611
 
375
612
  add_read( tun, :tun )
376
- loop_send_hello
377
- end
378
-
379
- ##
380
- # new a dst
381
- #
382
- def new_a_dst( src, ip_info )
383
- src_info = @src_infos[ src ]
384
- domain = src_info[ :destination_domain ]
385
- destination_addr = Socket.sockaddr_in( src_info[ :destination_port ], ip_info.ip_address )
386
- dst = Socket.new( ip_info.ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
387
-
388
- if RUBY_PLATFORM.include?( 'linux' )
389
- dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
390
- end
613
+ data = @custom.hello
391
614
 
392
- begin
393
- dst.connect_nonblock( destination_addr )
394
- rescue IO::WaitWritable
395
- # connect nonblock 必抛 wait writable,这里仅仅接一下,逻辑写外面,整齐
396
- rescue Exception => e
397
- puts "p#{ Process.pid } #{ Time.new } connect destination #{ e.class }, close src"
398
- set_is_closing( src )
399
- return
400
- end
615
+ Thread.new do
616
+ SEND_HELLO_COUNT.times do | i |
617
+ if @tun.nil? || @tun.closed? || @tun_info[ :tund_addr ] then
618
+ # puts "debug1 break loop send hello"
619
+ break
620
+ end
401
621
 
402
- # puts "debug1 a new dst #{ dst.local_address.inspect }"
403
- local_port = dst.local_address.ip_port
404
- @dst_infos[ dst ] = {
405
- local_port: local_port, # 本地端口
406
- src: src, # 对应src
407
- domain: domain, # 域名
408
- wbuff: '', # 写前
409
- last_continue_at: Time.new, # 上一次发生流量的时间
410
- is_closing: false # 是否准备关闭
411
- }
622
+ @mutex.synchronize do
623
+ msg = i >= 1 ? "resend hello #{ i }" : "hello i'm tun"
624
+ puts "p#{ Process.pid } #{ Time.new } #{ msg }"
625
+ # puts "debug1 #{ data.inspect }"
412
626
 
413
- add_read( dst, :dst )
414
- src_info[ :proxy_type ] = :direct
415
- src_info[ :dst ] = dst
627
+ add_ctlmsg( data, @proxyd_addr )
628
+ next_tick
629
+ end
416
630
 
417
- if src_info[ :proxy_proto ] == :http
418
- if src_info[ :is_connect ]
419
- # puts "debug1 add src wbuff http ok"
420
- add_src_wbuff( src, HTTP_OK )
421
- else
422
- # puts "debug1 add src rbuff to dst wbuff"
423
- add_dst_wbuff( dst, src_info[ :rbuff ] )
631
+ sleep 1
424
632
  end
425
- elsif src_info[ :proxy_proto ] == :socks5
426
- add_src_wbuff_socks5_conn_reply( src )
427
633
  end
428
634
  end
429
635
 
430
636
  ##
431
- # new a src ext
637
+ # next tick
432
638
  #
433
- def new_a_src_ext( src )
434
- if @tun.nil? || @tun.closed?
435
- new_a_tun
436
- end
437
-
438
- src_info = @src_infos[ src ]
439
- src_info[ :proxy_type ] = :tunnel
440
- src_id = src_info[ :id ]
441
- @tun_info[ :srcs ][ src_id ] = src
442
-
443
- if @tun_info[ :tund_addr ]
444
- loop_send_a_new_source( src )
445
- else
446
- @tun_info[ :pending_sources ] << src
447
- end
639
+ def next_tick
640
+ @dotw.write( '.' )
448
641
  end
449
642
 
450
643
  ##
451
- # add src wbuff socks5 conn reply
644
+ # resolve domain
452
645
  #
453
- def add_src_wbuff_socks5_conn_reply( src )
454
- # +----+-----+-------+------+----------+----------+
455
- # |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
456
- # +----+-----+-------+------+----------+----------+
457
- # | 1 | 1 | X'00' | 1 | Variable | 2 |
458
- # +----+-----+-------+------+----------+----------+
459
- proxy_ip, proxy_port = @proxy_local_address.ip_unpack
460
- data = [ [ 5, 0, 0, 1 ].pack( 'C4' ), IPAddr.new( proxy_ip ).hton, [ proxy_port ].pack( 'n' ) ].join
461
- # puts "debug1 add src wbuff socks5 conn reply #{ data.inspect }"
462
- add_src_wbuff( src, data )
463
- end
646
+ def resolve_domain( src, domain )
647
+ if @remotes.any? { | remote | ( domain.size >= remote.size ) && ( domain[ ( remote.size * -1 )..-1 ] == remote ) } then
648
+ # puts "debug1 #{ domain } hit remotes"
649
+ set_src_proxy_type_tunnel( src )
650
+ return
651
+ end
464
652
 
465
- ##
466
- # sub http request
467
- #
468
- def sub_http_request( data )
469
- lines = data.split( "\r\n" )
653
+ resolv_cache = @resolv_caches[ domain ]
470
654
 
471
- if lines.empty?
472
- return [ data, nil ]
473
- end
655
+ if resolv_cache then
656
+ ip_info, created_at = resolv_cache
474
657
 
475
- method, url, proto = lines.first.split( ' ' )
658
+ if Time.new - created_at < RESOLV_CACHE_EXPIRE then
659
+ # puts "debug1 #{ domain } hit resolv cache #{ ip_info.inspect }"
660
+ deal_with_destination_ip( src, ip_info )
661
+ return
662
+ end
476
663
 
477
- if proto && url && proto[ 0, 4 ] == 'HTTP' && url[ 0, 7 ] == 'http://'
478
- domain_port = url.split( '/' )[ 2 ]
479
- data = data.sub( "http://#{ domain_port }", '' )
480
- # puts "debug1 subed #{ data.inspect } #{ domain_port }"
664
+ # puts "debug1 expire #{ domain } resolv cache"
665
+ @resolv_caches.delete( domain )
481
666
  end
482
667
 
483
- [ data, domain_port ]
484
- end
485
-
486
- ##
487
- # add src wbuff
488
- #
489
- def add_src_wbuff( src, data )
490
668
  src_info = @src_infos[ src ]
491
- src_info[ :wbuff ] << data
492
- add_write( src )
493
- end
494
-
495
- ##
496
- # add dst wbuff
497
- #
498
- def add_dst_wbuff( dst, data )
499
- dst_info = @dst_infos[ dst ]
500
- dst_info[ :wbuff ] << data
501
- add_write( dst )
502
- end
503
-
504
- ##
505
- # add read
506
- #
507
- def add_read( sock, role = nil )
508
- if sock && !sock.closed? && !@reads.include?( sock )
509
- @reads << sock
669
+ src_info[ :proxy_type ] = :checking
510
670
 
511
- if role
512
- @roles[ sock ] = role
671
+ Thread.new do
672
+ begin
673
+ ip_info = Addrinfo.ip( domain )
674
+ rescue Exception => e
675
+ puts "p#{ Process.pid } #{ Time.new } resolv #{ domain } #{ e.class }"
513
676
  end
514
- end
515
- end
516
677
 
517
- ##
518
- # add write
519
- #
520
- def add_write( sock )
521
- if sock && !sock.closed? && !@writes.include?( sock )
522
- @writes << sock
523
- end
524
- end
525
-
526
- ##
527
- # add pause src
528
- #
529
- def add_pause_src( src )
530
- @reads.delete( src )
678
+ @mutex.synchronize do
679
+ if ip_info then
680
+ @resolv_caches[ domain ] = [ ip_info, Time.new ]
531
681
 
532
- unless @pause_srcs.include?( src )
533
- @pause_srcs << src
534
- end
535
- end
682
+ unless src.closed? then
683
+ puts "p#{ Process.pid } #{ Time.new } resolved #{ domain } #{ ip_info.ip_address }"
684
+ deal_with_destination_ip( src, ip_info )
685
+ end
686
+ else
687
+ set_src_closing( src )
688
+ end
536
689
 
537
- ##
538
- # set is closing
539
- #
540
- def set_is_closing( sock )
541
- if sock && !sock.closed?
542
- role = @roles[ sock ]
543
- # puts "debug1 set #{ role.to_s } is closing"
544
-
545
- case role
546
- when :src
547
- src_info = @src_infos[ sock ]
548
- src_info[ :is_closing ] = true
549
- when :dst
550
- dst_info = @dst_infos[ sock ]
551
- dst_info[ :is_closing ] = true
552
- when :tun
553
- @tun_info[ :is_closing ] = true
690
+ next_tick
554
691
  end
555
-
556
- @reads.delete( sock )
557
- add_write( sock )
558
692
  end
559
693
  end
560
694
 
561
695
  ##
562
- # tunnel data
696
+ # resume src
563
697
  #
564
- def tunnel_data( src, data )
565
- now = Time.new
698
+ def resume_src( src )
566
699
  src_info = @src_infos[ src ]
567
- src_id = src_info[ :id ]
568
- pack_id = src_info[ :biggest_pack_id ]
569
- idx = 0
570
- len = data.bytesize
571
-
572
- while idx < len
573
- chunk = data[ idx, PACK_SIZE ]
574
- pack_id += 1
575
-
576
- if pack_id <= CONFUSE_UNTIL
577
- chunk = @custom.encode( chunk )
578
- # puts "debug1 encoded chunk #{ pack_id }"
579
- end
580
-
581
- data2 = [ [ pack_id, src_id ].pack( 'Q>Q>' ), chunk ].join
582
- sent = send_data( @tun, data2, @tun_info[ :tund_addr ] )
583
- # puts "debug2 written pack #{ pack_id } #{ sent }"
584
- @tun_info[ :wmems ][ [ src_id, pack_id ] ] = data2
585
- src_info[ :send_ats ][ pack_id ] = now
586
- idx += PACK_SIZE
587
- end
588
-
589
- src_info[ :biggest_pack_id ] = pack_id
590
- src_info[ :last_continue_at ] = now
591
-
592
- # 写后超过上限,暂停读src
593
- if @tun_info[ :wmems ].size >= WMEMS_LIMIT
594
- puts "p#{ Process.pid } #{ Time.new } pause src #{ src_id } #{ src_info[ :destination_domain ] } #{ src_info[ :biggest_pack_id ] }"
595
- add_pause_src( src )
596
- end
700
+ src_info[ :paused ] = false
701
+ add_read( src )
597
702
  end
598
703
 
599
704
  ##
600
705
  # send data
601
706
  #
602
- def send_data( tun, data, to_addr )
603
- unless to_addr
604
- return false
707
+ def send_data( data, to_addr = nil )
708
+ unless to_addr then
709
+ to_addr = @tun_info[ :tund_addr ]
605
710
  end
606
711
 
607
712
  begin
608
- tun.sendmsg( data, 0, to_addr )
713
+ written = @tun.sendmsg_nonblock( data, 0, to_addr )
609
714
  rescue IO::WaitWritable, Errno::EINTR
610
- return false
715
+ print '.'
716
+ return :wait
611
717
  rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
612
- puts "#{ Time.new } #{ e.class }, close tun"
613
- close_tun( tun )
614
- return false
615
- end
616
-
617
- true
618
- end
619
-
620
- ##
621
- # close src
622
- #
623
- def close_src( src )
624
- # puts "debug1 close src"
625
- close_sock( src )
626
- @pause_srcs.delete( src )
627
- src_info = @src_infos[ src ]
628
-
629
- if src_info[ :proxy_type ] == :direct
630
- @src_infos.delete( src )
631
-
632
- if src_info[ :dst ]
633
- set_is_closing( src_info[ :dst ] )
634
- end
635
-
636
- return
718
+ puts "#{ Time.new } sendmsg #{ e.class }, close tun"
719
+ return :fatal
637
720
  end
638
721
 
639
- if @tun.closed? || src_info[ :dst_id ].nil?
640
- @src_infos.delete( src )
641
- return
642
- end
643
-
644
- src_id = src_info[ :id ]
645
-
646
- if src_info[ :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
- else
651
- # puts "debug1 1-1. after close src -> dst closed ? no -> send fin1"
652
- data = [ 0, FIN1, src_id, src_info[ :biggest_pack_id ], src_info[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
653
- end
654
-
655
- send_data( @tun, data, @tun_info[ :tund_addr ] )
656
- end
657
-
658
- ##
659
- # close dst
660
- #
661
- def close_dst( dst )
662
- # puts "debug1 close dst"
663
- close_sock( dst )
664
- dst_info = @dst_infos.delete( dst )
665
- set_is_closing( dst_info[ :src ] )
666
- end
667
-
668
- ##
669
- # close tun
670
- #
671
- def close_tun( tun )
672
- # puts "debug1 close tun"
673
- close_sock( tun )
674
- @tun_info[ :srcs ].each{ | _, src | set_is_closing( src ) }
675
- end
676
-
677
- ##
678
- # close sock
679
- #
680
- def close_sock( sock )
681
- sock.close
682
- @reads.delete( sock )
683
- @writes.delete( sock )
684
- @roles.delete( sock )
722
+ written
685
723
  end
686
724
 
687
725
  ##
688
- # del src ext
726
+ # set dst closing
689
727
  #
690
- def del_src_ext( src_id )
691
- src = @tun_info[ :srcs ][ src_id ]
692
-
693
- if src && src.closed?
694
- @tun_info[ :wmems ].delete_if { | src_id_pack_id, _ | src_id_pack_id.first == src_id }
695
- @tun_info[ :srcs ].delete( src_id )
696
- src_info = @src_infos.delete( src )
697
-
698
- if src_info
699
- @tun_info[ :src_ids ].delete( src_info[ :dst_id ] )
700
- end
701
- end
702
- end
703
-
704
- ##
705
- # release wmems
706
- #
707
- def release_wmems( src_info, completed_pack_id )
708
- if completed_pack_id > src_info[ :completed_pack_id ]
709
- # puts "debug2 update completed pack #{ completed_pack_id }"
710
- pack_ids = src_info[ :send_ats ].keys.select { | pack_id | pack_id <= completed_pack_id }
711
-
712
- pack_ids.each do | pack_id |
713
- @tun_info[ :wmems ].delete( [ src_info[ :id ], pack_id ] )
714
- src_info[ :send_ats ].delete( pack_id )
715
- end
716
-
717
- src_info[ :completed_pack_id ] = completed_pack_id
718
- end
728
+ def set_dst_closing( dst )
729
+ return if dst.closed?
730
+ dst_info = @dst_infos[ dst ]
731
+ dst_info[ :closing ] = true
732
+ @reads.delete( dst )
733
+ add_write( dst )
719
734
  end
720
735
 
721
736
  ##
722
- # next tick
737
+ # set dst closing write
723
738
  #
724
- def next_tick
725
- @dotw.write( '.' )
739
+ def set_dst_closing_write( dst )
740
+ return if dst.closed?
741
+ dst_info = @dst_infos[ dst ]
742
+ dst_info[ :closing_write ] = true
743
+ add_write( dst )
726
744
  end
727
745
 
728
746
  ##
729
- # write src
747
+ # set src is closing
730
748
  #
731
- def write_src( src )
749
+ def set_src_closing( src )
750
+ return if src.closed?
751
+ @reads.delete( src )
732
752
  src_info = @src_infos[ src ]
733
-
734
- if src_info[ :is_closing ]
735
- close_src( src )
736
- return
737
- end
738
-
739
- data = src_info[ :wbuff ]
740
-
741
- if data.empty?
742
- @writes.delete( src )
743
- return
744
- end
745
-
746
- begin
747
- written = src.write_nonblock( data )
748
- rescue IO::WaitWritable, Errno::EINTR
749
- return
750
- rescue Exception => e
751
- close_src( src )
752
- return
753
- end
754
-
755
- # puts "debug2 write src #{ written }"
756
- data = data[ written..-1 ]
757
- src_info[ :wbuff ] = data
758
- src_info[ :last_continue_at ] = Time.new
753
+ src_info[ :closing ] = true
754
+ add_write( src )
759
755
  end
760
756
 
761
757
  ##
762
- # write dst
758
+ # set src closing write
763
759
  #
764
- def write_dst( dst )
765
- dst_info = @dst_infos[ dst ]
760
+ def set_src_closing_write( src )
761
+ return if src.closed?
762
+ src_info = @src_infos[ src ]
763
+ src_info[ :closing_write ] = true
764
+ add_write( src )
765
+ end
766
766
 
767
- if dst_info[ :is_closing ]
768
- close_dst( dst )
769
- return
767
+ ##
768
+ # set src proxy type tunnel
769
+ #
770
+ def set_src_proxy_type_tunnel( src )
771
+ if @tun.nil? || @tun.closed? then
772
+ new_a_tun
770
773
  end
771
774
 
772
- data = dst_info[ :wbuff ]
775
+ src_info = @src_infos[ src ]
776
+ src_info[ :proxy_type ] = :tunnel
777
+ src_id = src_info[ :id ]
778
+ @tun_info[ :srcs ][ src_id ] = src
773
779
 
774
- if data.empty?
775
- @writes.delete( dst )
776
- return
780
+ if @tun_info[ :tund_addr ] then
781
+ loop_send_a_new_source( src )
782
+ else
783
+ @tun_info[ :pending_sources ] << src
777
784
  end
785
+ end
778
786
 
779
- begin
780
- written = dst.write_nonblock( data )
781
- rescue IO::WaitWritable, Errno::EINTR
782
- return
783
- rescue Exception => e
784
- # puts "debug1 write dst #{ e.class }"
785
- close_dst( dst )
786
- return
787
- end
787
+ ##
788
+ # set stream closing
789
+ #
790
+ def set_stream_closing( stream )
791
+ return if stream.closed?
792
+ stream_info = @stream_infos[ stream ]
793
+ stream_info[ :closing ] = true
794
+ @reads.delete( stream )
795
+ add_write( stream )
796
+ end
788
797
 
789
- # puts "debug2 write dst #{ written }"
790
- data = data[ written..-1 ]
791
- dst_info[ :wbuff ] = data
792
- dst_info[ :last_continue_at ] = Time.new
798
+ ##
799
+ # set stream closing write
800
+ #
801
+ def set_stream_closing_write( stream )
802
+ return if stream.closed?
803
+ stream_info = @stream_infos[ stream ]
804
+ stream_info[ :closing_write ] = true
805
+ add_write( stream )
793
806
  end
794
807
 
795
808
  ##
796
- # write tun
809
+ # set tun is closing
797
810
  #
798
- def write_tun( tun )
799
- if @tun_info[ :is_closing ]
800
- close_tun( tun )
801
- return
811
+ def set_tun_closing
812
+ return if @tun.closed?
813
+ @tun_info[ :closing ] = true
814
+ @reads.delete( @tun )
815
+ add_write( @tun )
816
+ end
817
+
818
+ ##
819
+ # sub http request
820
+ #
821
+ def sub_http_request( data )
822
+ lines = data.split( "\r\n" )
823
+
824
+ return [ data, nil ] if lines.empty?
825
+
826
+ method, url, proto = lines.first.split( ' ' )
827
+
828
+ if proto && url && proto[ 0, 4 ] == 'HTTP' && url[ 0, 7 ] == 'http://' then
829
+ domain_port = url.split( '/' )[ 2 ]
830
+ data = data.sub( "http://#{ domain_port }", '' )
831
+ # puts "debug1 subed #{ data.inspect } #{ domain_port }"
802
832
  end
803
833
 
804
- @writes.delete( tun )
834
+ [ data, domain_port ]
805
835
  end
806
836
 
807
837
  ##
@@ -818,6 +848,7 @@ module Girl
818
848
  begin
819
849
  src, addrinfo = proxy.accept_nonblock
820
850
  rescue IO::WaitReadable, Errno::EINTR
851
+ print 'r'
821
852
  return
822
853
  end
823
854
 
@@ -825,30 +856,86 @@ module Girl
825
856
  # puts "debug1 accept a src #{ addrinfo.inspect } #{ src_id }"
826
857
 
827
858
  @src_infos[ src ] = {
828
- id: src_id, # id
829
- proxy_proto: :uncheck, # :uncheck / :http / :socks5
830
- proxy_type: :uncheck, # :uncheck / :checking / :direct / :tunnel / :negotiation
831
- dst: nil, # :direct的场合,对应的dst
832
- destination_domain: nil, # 目的地域名
833
- destination_port: nil, # 目的地端口
834
- biggest_pack_id: 0, # 最大包号码
835
- is_connect: true, # 代理协议是http的场合,是否是CONNECT
836
- rbuff: '', # 非CONNECT,dst或者远端dst未准备好,暂存流量
837
- wbuff: '', # 写前
838
- dst_id: nil, # 远端dst id
839
- send_ats: {}, # 上一次发出时间 pack_id => send_at
840
- continue_dst_pack_id: 0, # 收到几
841
- pieces: {}, # 跳号包 dst_pack_id => data
842
- is_dst_closed: false, # dst是否已关闭
843
- biggest_dst_pack_id: 0, # dst最大包号码
844
- completed_pack_id: 0, # 完成到几(对面收到几)
845
- last_continue_at: Time.new, # 上一次发生流量的时间
846
- is_closing: false # 是否准备关闭
859
+ id: src_id, # id
860
+ proxy_proto: :uncheck, # :uncheck / :http / :socks5
861
+ proxy_type: :uncheck, # :uncheck / :checking / :direct / :tunnel / :negotiation
862
+ destination_domain: nil, # 目的地域名
863
+ destination_port: nil, # 目的地端口
864
+ is_connect: true, # 代理协议是http的场合,是否是CONNECT
865
+ rbuff: '', # 读到的流量
866
+ stream: nil, # :tunnel的场合,对应的stream
867
+ wbuff: '', # dst/stream读到的流量
868
+ dst: nil, # :direct的场合,对应的dst
869
+ dst_id: nil, # 远端dst id
870
+ created_at: Time.new, # 创建时间
871
+ last_recv_at: nil, # 上一次收到新流量(由dst收到,或者由stream收到)的时间
872
+ last_sent_at: nil, # 上一次发出流量(由dst发出,或者由stream发出)的时间
873
+ paused: false, # 是否已暂停
874
+ closing: false, # 准备关闭
875
+ closing_read: false, # 准备关闭读
876
+ closing_write: false # 准备关闭写
847
877
  }
848
878
 
849
879
  add_read( src, :src )
850
880
  end
851
881
 
882
+ ##
883
+ # read tun
884
+ #
885
+ def read_tun( tun )
886
+ begin
887
+ data, addrinfo, rflags, *controls = tun.recvmsg_nonblock
888
+ rescue IO::WaitReadable, Errno::EINTR
889
+ print 'r'
890
+ return
891
+ end
892
+
893
+ from_addr = addrinfo.to_sockaddr
894
+ @tun_info[ :last_recv_at ] = Time.new
895
+ pack_id = data[ 0, 8 ].unpack( 'Q>' ).first
896
+ return if pack_id != 0
897
+
898
+ ctl_num = data[ 8 ].unpack( 'C' ).first
899
+
900
+ case ctl_num
901
+ when TUND_PORT then
902
+ return if ( from_addr != @proxyd_addr ) || @tun_info[ :tund_addr ]
903
+
904
+ tund_port, tcpd_port = data[ 9, 4 ].unpack( 'nn' )
905
+
906
+ puts "p#{ Process.pid } #{ Time.new } got tund port #{ tund_port }, #{ tcpd_port }"
907
+ @tun_info[ :tund_addr ] = Socket.sockaddr_in( tund_port, @proxyd_host )
908
+ @tun_info[ :tcpd_addr ] = Socket.sockaddr_in( tcpd_port, @proxyd_host )
909
+
910
+ if @tun_info[ :pending_sources ].any? then
911
+ puts "p#{ Process.pid } #{ Time.new } send pending sources"
912
+
913
+ @tun_info[ :pending_sources ].each do | src |
914
+ loop_send_a_new_source( src )
915
+ end
916
+
917
+ @tun_info[ :pending_sources ].clear
918
+ end
919
+ when PAIRED then
920
+ return if from_addr != @tun_info[ :tund_addr ]
921
+
922
+ src_id, dst_id = data[ 9, 10 ].unpack( 'Q>n' )
923
+
924
+ # puts "debug1 got paired #{ src_id } #{ dst_id }"
925
+ new_a_stream( src_id, dst_id )
926
+ when TUND_FIN then
927
+ return if from_addr != @tun_info[ :tund_addr ]
928
+
929
+ puts "p#{ Process.pid } #{ Time.new } recv tund fin"
930
+ set_tun_closing
931
+ when IP_CHANGED then
932
+ return if from_addr != @tun_info[ :tund_addr ]
933
+
934
+ puts "p#{ Process.pid } #{ Time.new } recv ip changed"
935
+ set_tun_closing
936
+ end
937
+ end
938
+
852
939
  ##
853
940
  # read src
854
941
  #
@@ -856,30 +943,38 @@ module Girl
856
943
  begin
857
944
  data = src.read_nonblock( READ_SIZE )
858
945
  rescue IO::WaitReadable, Errno::EINTR
946
+ print 'r'
859
947
  return
860
948
  rescue Exception => e
861
949
  # puts "debug1 read src #{ e.class }"
862
- set_is_closing( src )
950
+ src_info = close_read_src( src )
951
+ dst = src_info[ :dst ]
952
+
953
+ if dst then
954
+ set_dst_closing_write( dst )
955
+ else
956
+ stream = src_info[ :stream ]
957
+ set_stream_closing_write( stream ) if stream
958
+ end
959
+
863
960
  return
864
961
  end
865
962
 
866
- # puts "debug2 read src #{ data.inspect }"
867
963
  src_info = @src_infos[ src ]
868
- src_info[ :last_continue_at ] = Time.new
869
964
  proxy_type = src_info[ :proxy_type ]
870
965
 
871
966
  case proxy_type
872
- when :uncheck
873
- if data[ 0, 7 ] == 'CONNECT'
967
+ when :uncheck then
968
+ if data[ 0, 7 ] == 'CONNECT' then
874
969
  # puts "debug1 CONNECT"
875
970
  domain_port = data.split( "\r\n" )[ 0 ].split( ' ' )[ 1 ]
876
971
 
877
- unless domain_port
972
+ unless domain_port then
878
973
  puts "p#{ Process.pid } #{ Time.new } CONNECT miss domain"
879
- set_is_closing( src )
974
+ set_src_closing( src )
880
975
  return
881
976
  end
882
- elsif data[ 0 ].unpack( 'C' ).first == 5
977
+ elsif data[ 0 ].unpack( 'C' ).first == 5 then
883
978
  # puts "debug1 socks5 #{ data.inspect }"
884
979
 
885
980
  # https://tools.ietf.org/html/rfc1928
@@ -892,9 +987,9 @@ module Girl
892
987
  nmethods = data[ 1 ].unpack( 'C' ).first
893
988
  methods = data[ 2, nmethods ].unpack( 'C*' )
894
989
 
895
- unless methods.include?( 0 )
990
+ unless methods.include?( 0 ) then
896
991
  puts "p#{ Process.pid } #{ Time.new } miss method 00"
897
- set_is_closing( src )
992
+ set_src_closing( src )
898
993
  return
899
994
  end
900
995
 
@@ -905,30 +1000,28 @@ module Girl
905
1000
  # +----+--------+
906
1001
  data2 = [ 5, 0 ].pack( 'CC' )
907
1002
  add_src_wbuff( src, data2 )
908
-
909
1003
  src_info[ :proxy_proto ] = :socks5
910
1004
  src_info[ :proxy_type ] = :negotiation
911
-
912
1005
  return
913
1006
  else
914
1007
  # puts "debug1 not CONNECT #{ data.inspect }"
915
1008
  host_line = data.split( "\r\n" ).find { | _line | _line[ 0, 6 ] == 'Host: ' }
916
1009
 
917
- unless host_line
1010
+ unless host_line then
918
1011
  # puts "debug1 not found host line"
919
- set_is_closing( src )
1012
+ set_src_closing( src )
920
1013
  return
921
1014
  end
922
1015
 
923
1016
  data, domain_port = sub_http_request( data )
924
1017
 
925
- unless domain_port
1018
+ unless domain_port then
926
1019
  # puts "debug1 not HTTP"
927
1020
  domain_port = host_line.split( ' ' )[ 1 ]
928
1021
 
929
- unless domain_port
1022
+ unless domain_port then
930
1023
  puts "p#{ Process.pid } #{ Time.new } Host line miss domain"
931
- set_is_closing( src )
1024
+ set_src_closing( src )
932
1025
  return
933
1026
  end
934
1027
  end
@@ -945,10 +1038,10 @@ module Girl
945
1038
  src_info[ :destination_port ] = port
946
1039
 
947
1040
  resolve_domain( src, domain )
948
- when :checking
949
- # puts "debug1 add src rbuff while checking #{ data.inspect }"
1041
+ when :checking then
1042
+ # puts "debug1 add src rbuff before resolved #{ data.inspect }"
950
1043
  src_info[ :rbuff ] << data
951
- when :negotiation
1044
+ when :negotiation then
952
1045
  # +----+-----+-------+------+----------+----------+
953
1046
  # |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
954
1047
  # +----+-----+-------+------+----------+----------+
@@ -957,10 +1050,10 @@ module Girl
957
1050
  # puts "debug1 negotiation #{ data.inspect }"
958
1051
  ver, cmd, rsv, atyp = data[ 0, 4 ].unpack( 'C4' )
959
1052
 
960
- if cmd == 1
1053
+ if cmd == 1 then
961
1054
  # puts "debug1 socks5 CONNECT"
962
1055
 
963
- if atyp == 1
1056
+ if atyp == 1 then
964
1057
  destination_host, destination_port = data[ 4, 6 ].unpack( 'Nn' )
965
1058
  destination_addr = Socket.sockaddr_in( destination_port, destination_host )
966
1059
  destination_addrinfo = Addrinfo.new( destination_addr )
@@ -969,10 +1062,10 @@ module Girl
969
1062
  src_info[ :destination_port ] = destination_port
970
1063
  # puts "debug1 IP V4 address #{ destination_addrinfo.inspect }"
971
1064
  deal_with_destination_ip( src, destination_addrinfo )
972
- elsif atyp == 3
1065
+ elsif atyp == 3 then
973
1066
  domain_len = data[ 4 ].unpack( 'C' ).first
974
1067
 
975
- if ( domain_len + 7 ) == data.bytesize
1068
+ if ( domain_len + 7 ) == data.bytesize then
976
1069
  domain = data[ 5, domain_len ]
977
1070
  port = data[ ( 5 + domain_len ), 2 ].unpack( 'n' ).first
978
1071
  src_info[ :destination_domain ] = domain
@@ -984,41 +1077,64 @@ module Girl
984
1077
  else
985
1078
  puts "p#{ Process.pid } #{ Time.new } socks5 cmd #{ cmd } not implement"
986
1079
  end
987
- when :tunnel
988
- if src_info[ :dst_id ]
989
- if @tun.closed?
990
- # puts "debug1 tun closed, close src"
991
- set_is_closing( src )
992
- return
993
- end
1080
+ when :tunnel then
1081
+ stream = src_info[ :stream ]
994
1082
 
995
- unless src_info[ :is_connect ]
996
- data, _ = sub_http_request( data )
997
- end
1083
+ if stream then
1084
+ unless stream.closed? then
1085
+ unless src_info[ :is_connect ] then
1086
+ data, _ = sub_http_request( data )
1087
+ end
1088
+
1089
+ stream_info = @stream_infos[ stream ]
1090
+ data = @custom.encode( data )
1091
+ # puts "debug2 add stream.wbuff encoded #{ data.bytesize }"
1092
+ stream_info[ :wbuff ] << data
1093
+ add_write( stream )
998
1094
 
999
- tunnel_data( src, data )
1095
+ if stream_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
1096
+ puts "p#{ Process.pid } #{ Time.new } pause tunnel src #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
1097
+ src_info[ :paused ] = true
1098
+ @reads.delete( src )
1099
+ end
1100
+ end
1000
1101
  else
1001
- # puts "debug1 remote dst not ready, save data to src rbuff"
1102
+ # puts "debug1 stream not ready, save data to src.rbuff"
1002
1103
  src_info[ :rbuff ] << data
1104
+
1105
+ if src_info[ :rbuff ].bytesize >= WBUFF_LIMIT then
1106
+ # puts "debug1 tunnel src.rbuff full"
1107
+ set_src_closing( src )
1108
+ end
1003
1109
  end
1004
- when :direct
1110
+ when :direct then
1005
1111
  dst = src_info[ :dst ]
1006
1112
 
1007
- if dst
1008
- if dst.closed?
1009
- # puts "debug1 dst closed, close src"
1010
- set_is_closing( src )
1011
- return
1012
- end
1113
+ if dst then
1114
+ unless dst.closed? then
1115
+ unless src_info[ :is_connect ] then
1116
+ data, _ = sub_http_request( data )
1117
+ end
1013
1118
 
1014
- unless src_info[ :is_connect ]
1015
- data, _ = sub_http_request( data )
1016
- end
1119
+ dst_info = @dst_infos[ dst ]
1120
+ # puts "debug2 add dst.wbuff #{ data.bytesize }"
1121
+ dst_info[ :wbuff ] << data
1122
+ add_write( dst )
1017
1123
 
1018
- add_dst_wbuff( dst, data )
1124
+ if dst_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
1125
+ puts "p#{ Process.pid } #{ Time.new } pause direct src #{ src_info[ :id ] } #{ src_info[ :destination_domain ] }"
1126
+ src_info[ :paused ] = true
1127
+ @reads.delete( src )
1128
+ end
1129
+ end
1019
1130
  else
1020
- # puts "debug1 dst not ready, save data to src rbuff"
1131
+ # puts "debug1 dst not ready, save data to src.rbuff"
1021
1132
  src_info[ :rbuff ] << data
1133
+
1134
+ if src_info[ :rbuff ].bytesize >= WBUFF_LIMIT then
1135
+ # puts "debug1 direct src.rbuff full"
1136
+ set_src_closing( src )
1137
+ end
1022
1138
  end
1023
1139
  end
1024
1140
  end
@@ -1030,297 +1146,243 @@ module Girl
1030
1146
  begin
1031
1147
  data = dst.read_nonblock( READ_SIZE )
1032
1148
  rescue IO::WaitReadable, Errno::EINTR
1149
+ print 'r'
1033
1150
  return
1034
1151
  rescue Exception => e
1035
1152
  # puts "debug1 read dst #{ e.class }"
1036
- set_is_closing( dst )
1153
+ dst_info = close_read_dst( dst )
1154
+ src = dst_info[ :src ]
1155
+ set_src_closing_write( src )
1037
1156
  return
1038
1157
  end
1039
1158
 
1040
- # puts "debug2 read dst #{ data.inspect }"
1041
1159
  dst_info = @dst_infos[ dst ]
1042
- dst_info[ :last_continue_at ] = Time.new
1043
1160
  src = dst_info[ :src ]
1161
+ add_src_wbuff( src, data )
1162
+ end
1044
1163
 
1045
- if src.closed?
1046
- puts "p#{ Process.pid } #{ Time.new } src closed, close dst #{ dst_info[ :domain ] }"
1047
- set_is_closing( dst )
1164
+ ##
1165
+ # read stream
1166
+ #
1167
+ def read_stream( stream )
1168
+ begin
1169
+ data = stream.read_nonblock( READ_SIZE )
1170
+ rescue IO::WaitReadable, Errno::EINTR
1171
+ print 'r'
1172
+ return
1173
+ rescue Exception => e
1174
+ # puts "debug1 read stream #{ e.class }"
1175
+ stream_info = close_read_stream( stream )
1176
+ src = stream_info[ :src ]
1177
+ set_src_closing_write( src )
1048
1178
  return
1049
1179
  end
1050
1180
 
1181
+ stream_info = @stream_infos[ stream ]
1182
+ src = stream_info[ :src ]
1183
+ data = @custom.decode( data )
1184
+ # puts "debug2 add src.wbuff decoded #{ data.bytesize }"
1051
1185
  add_src_wbuff( src, data )
1052
1186
  end
1053
1187
 
1054
1188
  ##
1055
- # read tun
1189
+ # write tun
1056
1190
  #
1057
- def read_tun( tun )
1058
- data, addrinfo, rflags, *controls = tun.recvmsg
1059
- from_addr = addrinfo.to_sockaddr
1060
- now = Time.new
1061
- @tun_info[ :last_recv_at ] = now
1062
- pack_id = data[ 0, 8 ].unpack( 'Q>' ).first
1063
-
1064
- if pack_id == 0
1065
- ctl_num = data[ 8 ].unpack( 'C' ).first
1066
-
1067
- case ctl_num
1068
- when TUND_PORT
1069
- return if ( from_addr != @proxyd_addr ) || @tun_info[ :tund_addr ]
1070
-
1071
- tund_port = data[ 9, 2 ].unpack( 'n' ).first
1072
-
1073
- puts "p#{ Process.pid } #{ Time.new } got tund port #{ tund_port }"
1074
- tund_addr = Socket.sockaddr_in( tund_port, @proxyd_host )
1075
- @tun_info[ :tund_addr ] = tund_addr
1076
-
1077
- if @tun_info[ :pending_sources ].any?
1078
- puts "p#{ Process.pid } #{ Time.new } send pending sources"
1079
-
1080
- @tun_info[ :pending_sources ].each do | src |
1081
- loop_send_a_new_source( src )
1082
- end
1083
-
1084
- @tun_info[ :pending_sources ].clear
1085
- end
1086
- when PAIRED
1087
- return if from_addr != @tun_info[ :tund_addr ]
1088
-
1089
- src_id, dst_id = data[ 9, 10 ].unpack( 'Q>n' )
1090
-
1091
- src = @tun_info[ :srcs ][ src_id ]
1092
- return if src.nil? || src.closed?
1093
-
1094
- src_info = @src_infos[ src ]
1095
- return if src_info.nil? || src_info[ :dst_id ]
1096
-
1097
- # puts "debug1 got paired #{ src_id } #{ dst_id }"
1098
-
1099
- if dst_id == 0
1100
- set_is_closing( src )
1101
- return
1102
- end
1103
-
1104
- src_info[ :dst_id ] = dst_id
1105
- @tun_info[ :src_ids ][ dst_id ] = src_id
1106
-
1107
- if src_info[ :proxy_proto ] == :http
1108
- if src_info[ :is_connect ]
1109
- # puts "debug1 add src wbuff http ok"
1110
- add_src_wbuff( src, HTTP_OK )
1111
- else
1112
- # puts "debug1 send src rbuff to tund"
1113
- tunnel_data( src, src_info[ :rbuff ] )
1114
- end
1115
- elsif src_info[ :proxy_proto ] == :socks5
1116
- add_src_wbuff_socks5_conn_reply( src )
1117
- end
1118
- when DEST_STATUS
1119
- return if from_addr != @tun_info[ :tund_addr ]
1120
-
1121
- dst_id, relay_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
1122
-
1123
- src_id = @tun_info[ :src_ids ][ dst_id ]
1124
- return unless src_id
1125
-
1126
- src = @tun_info[ :srcs ][ src_id ]
1127
- return unless src
1128
-
1129
- src_info = @src_infos[ src ]
1130
- return unless src_info
1131
-
1132
- # puts "debug2 got dest status #{ Time.new }"
1133
-
1134
- # 消写后
1135
- release_wmems( src_info, continue_src_pack_id )
1136
-
1137
- # 发miss
1138
- if !src.closed? && ( src_info[ :continue_dst_pack_id ] < relay_dst_pack_id )
1139
- ranges = []
1140
- ignored = false
1141
- curr_pack_id = src_info[ :continue_dst_pack_id ] + 1
1142
-
1143
- src_info[ :pieces ].keys.sort.each do | pack_id |
1144
- if pack_id > curr_pack_id
1145
- ranges << [ curr_pack_id, pack_id - 1 ]
1146
-
1147
- if ranges.size >= MISS_RANGE_LIMIT
1148
- puts "p#{ Process.pid } #{ Time.new } break add miss range at #{ pack_id }"
1149
- ignored = true
1150
- break
1151
- end
1152
- end
1153
-
1154
- curr_pack_id = pack_id + 1
1155
- end
1156
-
1157
- if !ignored && ( curr_pack_id <= relay_dst_pack_id )
1158
- ranges << [ curr_pack_id, relay_dst_pack_id ]
1159
- end
1160
-
1161
- # puts "debug1 continue/relay #{ src_info[ :continue_dst_pack_id ] }/#{ relay_dst_pack_id } send MISS #{ ranges.size }"
1162
- idx = 0
1163
- ranges = ranges.map{ | pack_id_begin, pack_id_end | [ pack_id_begin, pack_id_end ].pack( 'Q>Q>' ) }
1164
-
1165
- while idx < ranges.size
1166
- chunk = ranges[ idx, MULTI_MISS_SIZE ].join
1167
- data2 = [ [ 0, MULTI_MISS, dst_id ].pack( 'Q>Cn' ), chunk ].join
1168
- send_data( tun, data2, @tun_info[ :tund_addr ] )
1169
- idx += MULTI_MISS_SIZE
1170
- end
1171
- end
1172
- when MULTI_MISS
1173
- src_id, *ranges = data[ 9..-1 ].unpack( 'Q>Q>*' )
1174
-
1175
- src = @tun_info[ :srcs ][ src_id ]
1176
- return unless src
1191
+ def write_tun( tun )
1192
+ # 处理关闭
1193
+ if @tun_info[ :closing ] then
1194
+ close_tun( tun )
1195
+ return
1196
+ end
1177
1197
 
1178
- src_info = @src_infos[ src ]
1179
- return unless src_info
1198
+ now = Time.new
1180
1199
 
1181
- return if ranges.empty? || ( ranges.size % 2 != 0 )
1200
+ # 发ctlmsg
1201
+ while @tun_info[ :ctlmsgs ].any? do
1202
+ data, to_addr = @tun_info[ :ctlmsgs ].first
1203
+ sent = send_data( data, to_addr )
1182
1204
 
1183
- # puts "debug1 got multi miss #{ src_id } #{ ranges.size }"
1205
+ if sent == :fatal then
1206
+ close_tun( tun )
1207
+ return
1208
+ elsif sent == :wait then
1209
+ # puts "debug1 #{ Time.new } wait send ctlmsg left #{ @tun_info[ :ctlmsgs ].size }"
1210
+ @tun_info[ :last_sent_at ] = now
1211
+ return
1212
+ end
1184
1213
 
1185
- idx = 0
1214
+ @tun_info[ :ctlmsgs ].shift
1215
+ end
1186
1216
 
1187
- while idx < ranges.size
1188
- pack_id_begin, pack_id_end = ranges[ idx ], ranges[ idx + 1 ]
1217
+ @tun_info[ :last_sent_at ] = now
1218
+ @writes.delete( tun )
1219
+ end
1189
1220
 
1190
- ( pack_id_begin..pack_id_end ).each do | pack_id |
1191
- send_at = src_info[ :send_ats ][ pack_id ]
1221
+ ##
1222
+ # write src
1223
+ #
1224
+ def write_src( src )
1225
+ return if src.closed?
1226
+ src_info = @src_infos[ src ]
1227
+ dst = src_info[ :dst ]
1192
1228
 
1193
- if send_at
1194
- break if now - send_at < CHECK_STATUS_INTERVAL
1195
- data2 = @tun_info[ :wmems ][ [ src_id, pack_id ] ]
1229
+ # 处理关闭
1230
+ if src_info[ :closing ] then
1231
+ close_src( src )
1196
1232
 
1197
- if data2
1198
- if send_data( tun, data2, @tun_info[ :tund_addr ] )
1199
- src_info[ :last_continue_at ] = now
1200
- end
1201
- end
1202
- end
1203
- end
1233
+ if dst then
1234
+ close_read_dst( dst )
1235
+ set_dst_closing_write( dst )
1236
+ else
1237
+ stream = src_info[ :stream ]
1204
1238
 
1205
- idx += 2
1239
+ if stream then
1240
+ close_read_stream( stream )
1241
+ set_stream_closing_write( stream )
1206
1242
  end
1207
- when MISS
1208
- return if from_addr != @tun_info[ :tund_addr ]
1209
-
1210
- src_id, pack_id_begin, pack_id_end = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
1211
-
1212
- src = @tun_info[ :srcs ][ src_id ]
1213
- return unless src
1214
-
1215
- src_info = @src_infos[ src ]
1216
- return unless src_info
1243
+ end
1217
1244
 
1218
- ( pack_id_begin..pack_id_end ).each do | pack_id |
1219
- send_at = src_info[ :send_ats ][ pack_id ]
1245
+ return
1246
+ end
1220
1247
 
1221
- if send_at
1222
- break if now - send_at < CHECK_STATUS_INTERVAL
1223
- data2 = @tun_info[ :wmems ][ [ src_id, pack_id ] ]
1248
+ # 处理wbuff
1249
+ data = src_info[ :wbuff ]
1224
1250
 
1225
- if data2
1226
- if send_data( tun, data2, @tun_info[ :tund_addr ] )
1227
- src_info[ :last_continue_at ] = now
1228
- end
1229
- end
1230
- end
1231
- end
1232
- when FIN1
1233
- return if from_addr != @tun_info[ :tund_addr ]
1251
+ # 写前为空,处理关闭写
1252
+ if data.empty? then
1253
+ if src_info[ :closing_write ] then
1254
+ close_write_src( src )
1255
+ else
1256
+ @writes.delete( src )
1257
+ end
1234
1258
 
1235
- dst_id, biggest_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
1259
+ return
1260
+ end
1236
1261
 
1237
- src_id = @tun_info[ :src_ids ][ dst_id ]
1238
- return unless src_id
1262
+ # 写入
1263
+ begin
1264
+ written = src.write_nonblock( data )
1265
+ rescue IO::WaitWritable, Errno::EINTR
1266
+ print 'w'
1267
+ return
1268
+ rescue Exception => e
1269
+ # puts "debug1 write src #{ e.class }"
1270
+ close_write_src( src )
1239
1271
 
1240
- src = @tun_info[ :srcs ][ src_id ]
1241
- return unless src
1272
+ if dst then
1273
+ close_read_dst( dst )
1274
+ else
1275
+ stream = src_info[ :stream ]
1276
+ close_read_stream( stream ) if stream
1277
+ end
1242
1278
 
1243
- src_info = @src_infos[ src ]
1244
- return unless src_info
1279
+ return
1280
+ end
1245
1281
 
1246
- # puts "debug1 got fin1 #{ dst_id } biggest dst pack #{ biggest_dst_pack_id } completed src pack #{ continue_src_pack_id }"
1247
- src_info[ :is_dst_closed ] = true
1248
- src_info[ :biggest_dst_pack_id ] = biggest_dst_pack_id
1249
- release_wmems( src_info, continue_src_pack_id )
1282
+ # puts "debug2 written src #{ written }"
1283
+ data = data[ written..-1 ]
1284
+ src_info[ :wbuff ] = data
1285
+ end
1250
1286
 
1251
- if ( biggest_dst_pack_id == src_info[ :continue_dst_pack_id ] )
1252
- # puts "debug1 2-1. tun recv fin1 -> all traffic received ? -> close src after write"
1253
- set_is_closing( src )
1254
- end
1255
- when FIN2
1256
- return if from_addr != @tun_info[ :tund_addr ]
1287
+ ##
1288
+ # write dst
1289
+ #
1290
+ def write_dst( dst )
1291
+ return if dst.closed?
1292
+ dst_info = @dst_infos[ dst ]
1293
+ src = dst_info[ :src ]
1257
1294
 
1258
- dst_id = data[ 9, 2 ].unpack( 'n' ).first
1295
+ # 处理关闭
1296
+ if dst_info[ :closing ] then
1297
+ close_dst( dst )
1259
1298
 
1260
- src_id = @tun_info[ :src_ids ][ dst_id ]
1261
- return unless src_id
1299
+ if src then
1300
+ close_read_src( src )
1301
+ set_src_closing_write( src )
1302
+ end
1262
1303
 
1263
- # puts "debug1 1-2. tun recv fin2 -> del src ext"
1264
- del_src_ext( src_id )
1265
- when TUND_FIN
1266
- return if from_addr != @tun_info[ :tund_addr ]
1304
+ return
1305
+ end
1267
1306
 
1268
- puts "p#{ Process.pid } #{ Time.new } recv tund fin"
1269
- set_is_closing( tun )
1270
- when IP_CHANGED
1271
- return if from_addr != @tun_info[ :tund_addr ]
1307
+ data = dst_info[ :wbuff ]
1272
1308
 
1273
- puts "p#{ Process.pid } #{ Time.new } recv ip changed"
1274
- set_is_closing( tun )
1309
+ # 写前为空,处理关闭写
1310
+ if data.empty? then
1311
+ if dst_info[ :closing_write ] then
1312
+ close_write_dst( dst )
1313
+ else
1314
+ @writes.delete( dst )
1275
1315
  end
1276
1316
 
1277
1317
  return
1278
1318
  end
1279
1319
 
1280
- return if from_addr != @tun_info[ :tund_addr ]
1281
-
1282
- dst_id = data[ 8, 2 ].unpack( 'n' ).first
1283
-
1284
- src_id = @tun_info[ :src_ids ][ dst_id ]
1285
- return unless src_id
1320
+ # 写入
1321
+ begin
1322
+ written = dst.write_nonblock( data )
1323
+ rescue IO::WaitWritable, Errno::EINTR
1324
+ print 'w'
1325
+ return
1326
+ rescue Exception => e
1327
+ # puts "debug1 write dst #{ e.class }"
1328
+ close_write_dst( dst )
1329
+ close_read_src( src ) if src
1330
+ return
1331
+ end
1286
1332
 
1287
- src = @tun_info[ :srcs ][ src_id ]
1288
- return if src.nil? || src.closed?
1333
+ data = data[ written..-1 ]
1334
+ dst_info[ :wbuff ] = data
1335
+ end
1289
1336
 
1290
- src_info = @src_infos[ src ]
1291
- return unless src_info
1337
+ ##
1338
+ # write stream
1339
+ #
1340
+ def write_stream( stream )
1341
+ return if stream.closed?
1342
+ stream_info = @stream_infos[ stream ]
1343
+ src = stream_info[ :src ]
1344
+
1345
+ # 处理关闭
1346
+ if stream_info[ :closing ] then
1347
+ close_stream( stream )
1348
+ close_read_src( src )
1349
+ set_src_closing_write( src )
1350
+ return
1351
+ end
1292
1352
 
1293
- return if ( pack_id <= src_info[ :continue_dst_pack_id ] ) || src_info[ :pieces ].include?( pack_id )
1353
+ data = stream_info[ :wbuff ]
1294
1354
 
1295
- data = data[ 10..-1 ]
1296
- # puts "debug2 got pack #{ pack_id }"
1355
+ # 写前为空,处理关闭写
1356
+ if data.empty? then
1357
+ if stream_info[ :closing_write ] then
1358
+ close_write_stream( stream )
1359
+ else
1360
+ @writes.delete( stream )
1361
+ end
1297
1362
 
1298
- if pack_id <= CONFUSE_UNTIL
1299
- # puts "debug2 #{ data.inspect }"
1300
- data = @custom.decode( data )
1301
- # puts "debug1 decoded pack #{ pack_id }"
1363
+ return
1302
1364
  end
1303
1365
 
1304
- # 放进写前,跳号放碎片缓存
1305
- if pack_id - src_info[ :continue_dst_pack_id ] == 1
1306
- while src_info[ :pieces ].include?( pack_id + 1 )
1307
- data << src_info[ :pieces ].delete( pack_id + 1 )
1308
- pack_id += 1
1309
- end
1366
+ # 写入
1367
+ begin
1368
+ written = stream.write_nonblock( data )
1369
+ rescue IO::WaitWritable, Errno::EINTR
1370
+ print 'w'
1371
+ return
1372
+ rescue Exception => e
1373
+ # puts "debug1 write stream #{ e.class }"
1374
+ close_write_stream( stream )
1375
+ close_read_src( src )
1376
+ return
1377
+ end
1310
1378
 
1311
- src_info[ :continue_dst_pack_id ] = pack_id
1312
- src_info[ :last_continue_at ] = now
1313
- add_src_wbuff( src, data )
1314
- # puts "debug2 update continue dst pack #{ pack_id }"
1379
+ # puts "debug2 written stream #{ written }"
1380
+ data = data[ written..-1 ]
1381
+ stream_info[ :wbuff ] = data
1315
1382
 
1316
- # 若对面已关闭,且流量正好收全,关闭src
1317
- if src_info[ :is_dst_closed ] && ( pack_id == src_info[ :biggest_dst_pack_id ] )
1318
- # puts "debug1 2-2. tun recv traffic -> dst closed and all traffic received ? -> close src after write"
1319
- set_is_closing( src )
1320
- end
1321
- else
1322
- src_info[ :pieces ][ pack_id ] = data
1323
- src_info[ :last_continue_at ] = now
1383
+ unless src.closed? then
1384
+ src_info = @src_infos[ src ]
1385
+ src_info[ :last_sent_at ] = Time.new
1324
1386
  end
1325
1387
  end
1326
1388