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