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