girl 0.88.0 → 0.89.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 +49 -90
- data/lib/girl/proxy_worker.rb +900 -838
- data/lib/girl/proxyd.rb +6 -25
- data/lib/girl/proxyd_worker.rb +655 -609
- 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: 8a1e3e17f5d9ca7e92f7c61d52732b78e80b93fcaf9c39c19cb0d4ebc0bb353c
|
4
|
+
data.tar.gz: 981a168ddcda54ccbddc39acb0dec0af00b018f1fba64ffd04444f584d306671
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08f46bb81ff9d4ad4767aad8528e7c7c899f9c305db62f1dcb5079f3ebea28aed0ffc49946ac2b3503303c8dd807e9b27204c0042d3aca73f3c06e42881d294b'
|
7
|
+
data.tar.gz: 533abffc741dcb060bfc80bf6ac9cdae98a3be4f38d70a7a2e3a0cd3df5eef2b617a961b66d965a306e5adab3d9464fbd3cec7ecd6bddf1b34cbe9cc8acd03c8
|
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 # 写前上限,超过上限暂停读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
|
data/lib/girl/proxy.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
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 |
|
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
|
|
data/lib/girl/proxy_worker.rb
CHANGED
@@ -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
|
-
@
|
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
|
-
|
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 :
|
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 :
|
63
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
136
|
-
|
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
|
-
|
143
|
-
|
144
|
-
|
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
|
385
|
+
# loop check resume
|
160
386
|
#
|
161
|
-
def
|
387
|
+
def loop_check_resume
|
162
388
|
Thread.new do
|
163
389
|
loop do
|
164
|
-
sleep
|
390
|
+
sleep CHECK_RESUME_INTERVAL
|
165
391
|
|
166
392
|
@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 ]
|
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
|
-
|
182
|
-
|
395
|
+
@src_infos.select{ | _, src_info | src_info[ :paused ] }.each do | src, src_info |
|
396
|
+
dst = src_info[ :dst ]
|
183
397
|
|
184
|
-
|
185
|
-
|
398
|
+
if dst then
|
399
|
+
dst_info = @dst_infos[ dst ]
|
186
400
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
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
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
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
|
-
|
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
|
-
|
246
|
-
if @tun.nil? || @tun.closed? || src.closed? || src_info[ :
|
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
|
-
|
448
|
+
add_ctlmsg( data )
|
449
|
+
next_tick
|
257
450
|
end
|
258
451
|
|
259
|
-
sleep
|
452
|
+
sleep 1
|
260
453
|
end
|
261
454
|
end
|
262
455
|
end
|
263
456
|
end
|
264
457
|
|
265
458
|
##
|
266
|
-
#
|
459
|
+
# new a dst
|
267
460
|
#
|
268
|
-
def
|
269
|
-
|
270
|
-
|
271
|
-
|
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
|
-
|
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
|
-
|
278
|
-
|
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
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
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
|
-
|
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[ :
|
517
|
+
return if src_info[ :dst_id ]
|
292
518
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
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
|
-
|
301
|
-
|
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
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
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
|
-
|
313
|
-
|
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
|
-
|
319
|
-
|
320
|
-
|
321
|
-
src_info = @src_infos[ src ]
|
544
|
+
@stream_infos[ stream ] = {
|
545
|
+
src: src, # 对应src
|
546
|
+
wbuff: data # 写前,写往远端streamd
|
547
|
+
}
|
322
548
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
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(
|
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: [],
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
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
|
-
|
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
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
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
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
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
|
-
|
414
|
-
|
415
|
-
|
627
|
+
add_ctlmsg( data, @proxyd_addr )
|
628
|
+
next_tick
|
629
|
+
end
|
416
630
|
|
417
|
-
|
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
|
-
#
|
637
|
+
# next tick
|
432
638
|
#
|
433
|
-
def
|
434
|
-
|
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
|
-
#
|
644
|
+
# resolve domain
|
452
645
|
#
|
453
|
-
def
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
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
|
472
|
-
|
473
|
-
end
|
655
|
+
if resolv_cache then
|
656
|
+
ip_info, created_at = resolv_cache
|
474
657
|
|
475
|
-
|
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
|
-
|
478
|
-
|
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[ :
|
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
|
-
|
512
|
-
|
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
|
-
|
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
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
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
|
-
#
|
696
|
+
# resume src
|
563
697
|
#
|
564
|
-
def
|
565
|
-
now = Time.new
|
698
|
+
def resume_src( src )
|
566
699
|
src_info = @src_infos[ src ]
|
567
|
-
|
568
|
-
|
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(
|
603
|
-
unless to_addr
|
604
|
-
|
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.
|
713
|
+
written = @tun.sendmsg_nonblock( data, 0, to_addr )
|
609
714
|
rescue IO::WaitWritable, Errno::EINTR
|
610
|
-
|
715
|
+
print '.'
|
716
|
+
return :wait
|
611
717
|
rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
|
612
|
-
puts "#{ Time.new } #{ e.class }, close tun"
|
613
|
-
|
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
|
-
|
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
|
-
#
|
726
|
+
# set dst closing
|
689
727
|
#
|
690
|
-
def
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
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
|
-
#
|
737
|
+
# set dst closing write
|
723
738
|
#
|
724
|
-
def
|
725
|
-
|
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
|
-
#
|
747
|
+
# set src is closing
|
730
748
|
#
|
731
|
-
def
|
749
|
+
def set_src_closing( src )
|
750
|
+
return if src.closed?
|
751
|
+
@reads.delete( src )
|
732
752
|
src_info = @src_infos[ src ]
|
733
|
-
|
734
|
-
|
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
|
758
|
+
# set src closing write
|
763
759
|
#
|
764
|
-
def
|
765
|
-
|
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
|
-
|
768
|
-
|
769
|
-
|
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
|
-
|
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
|
775
|
-
|
776
|
-
|
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
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
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
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
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
|
-
#
|
809
|
+
# set tun is closing
|
797
810
|
#
|
798
|
-
def
|
799
|
-
if @
|
800
|
-
|
801
|
-
|
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
|
-
|
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,
|
829
|
-
proxy_proto: :uncheck,
|
830
|
-
proxy_type: :uncheck,
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
dst_id: nil,
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
996
|
-
|
997
|
-
|
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
|
-
|
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
|
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
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
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
|
-
|
1015
|
-
|
1016
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
1046
|
-
|
1047
|
-
|
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
|
-
#
|
1189
|
+
# write tun
|
1056
1190
|
#
|
1057
|
-
def
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
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
|
-
|
1179
|
-
return unless src_info
|
1198
|
+
now = Time.new
|
1180
1199
|
|
1181
|
-
|
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
|
-
|
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
|
-
|
1214
|
+
@tun_info[ :ctlmsgs ].shift
|
1215
|
+
end
|
1186
1216
|
|
1187
|
-
|
1188
|
-
|
1217
|
+
@tun_info[ :last_sent_at ] = now
|
1218
|
+
@writes.delete( tun )
|
1219
|
+
end
|
1189
1220
|
|
1190
|
-
|
1191
|
-
|
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
|
-
|
1194
|
-
|
1195
|
-
|
1229
|
+
# 处理关闭
|
1230
|
+
if src_info[ :closing ] then
|
1231
|
+
close_src( src )
|
1196
1232
|
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
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
|
-
|
1239
|
+
if stream then
|
1240
|
+
close_read_stream( stream )
|
1241
|
+
set_stream_closing_write( stream )
|
1206
1242
|
end
|
1207
|
-
|
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
|
-
|
1219
|
-
|
1245
|
+
return
|
1246
|
+
end
|
1220
1247
|
|
1221
|
-
|
1222
|
-
|
1223
|
-
data2 = @tun_info[ :wmems ][ [ src_id, pack_id ] ]
|
1248
|
+
# 处理wbuff
|
1249
|
+
data = src_info[ :wbuff ]
|
1224
1250
|
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
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
|
-
|
1259
|
+
return
|
1260
|
+
end
|
1236
1261
|
|
1237
|
-
|
1238
|
-
|
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
|
-
|
1241
|
-
|
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
|
-
|
1244
|
-
|
1279
|
+
return
|
1280
|
+
end
|
1245
1281
|
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1282
|
+
# puts "debug2 written src #{ written }"
|
1283
|
+
data = data[ written..-1 ]
|
1284
|
+
src_info[ :wbuff ] = data
|
1285
|
+
end
|
1250
1286
|
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
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
|
-
|
1295
|
+
# 处理关闭
|
1296
|
+
if dst_info[ :closing ] then
|
1297
|
+
close_dst( dst )
|
1259
1298
|
|
1260
|
-
|
1261
|
-
|
1299
|
+
if src then
|
1300
|
+
close_read_src( src )
|
1301
|
+
set_src_closing_write( src )
|
1302
|
+
end
|
1262
1303
|
|
1263
|
-
|
1264
|
-
|
1265
|
-
when TUND_FIN
|
1266
|
-
return if from_addr != @tun_info[ :tund_addr ]
|
1304
|
+
return
|
1305
|
+
end
|
1267
1306
|
|
1268
|
-
|
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
|
-
|
1274
|
-
|
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
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
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
|
-
|
1288
|
-
|
1333
|
+
data = data[ written..-1 ]
|
1334
|
+
dst_info[ :wbuff ] = data
|
1335
|
+
end
|
1289
1336
|
|
1290
|
-
|
1291
|
-
|
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
|
-
|
1353
|
+
data = stream_info[ :wbuff ]
|
1294
1354
|
|
1295
|
-
|
1296
|
-
|
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
|
-
|
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
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
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
|
-
|
1312
|
-
|
1313
|
-
|
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
|
-
|
1317
|
-
|
1318
|
-
|
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
|
|