girl 0.86.0 → 0.90.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 +23 -14
- data/lib/girl/proxy.rb +48 -126
- data/lib/girl/proxy_worker.rb +907 -966
- data/lib/girl/proxyd.rb +11 -31
- data/lib/girl/proxyd_worker.rb +661 -700
- data/lib/girl/udp.rb +37 -47
- data/lib/girl/udpd.rb +26 -36
- data/lib/girl/version.rb +1 -1
- metadata +2 -2
data/lib/girl/proxyd.rb
CHANGED
@@ -13,61 +13,41 @@ module Girl
|
|
13
13
|
class Proxyd
|
14
14
|
|
15
15
|
def initialize( config_path = nil )
|
16
|
-
if config_path
|
17
|
-
unless File.exist?( config_path )
|
18
|
-
raise "not found config file #{ config_path }"
|
19
|
-
end
|
20
|
-
|
16
|
+
if config_path then
|
17
|
+
raise "not found config file #{ config_path }" unless File.exist?( config_path )
|
21
18
|
conf = JSON.parse( IO.binread( config_path ), symbolize_names: true )
|
22
19
|
proxyd_port = conf[ :proxyd_port ]
|
23
|
-
proxyd_tmp_dir = conf[ :proxyd_tmp_dir ]
|
24
20
|
worker_count = conf[ :worker_count ]
|
25
21
|
end
|
26
22
|
|
27
|
-
unless proxyd_port
|
23
|
+
unless proxyd_port then
|
28
24
|
proxyd_port = 6060
|
29
25
|
end
|
30
26
|
|
31
|
-
unless proxyd_tmp_dir
|
32
|
-
proxyd_tmp_dir = '/tmp/girl.proxyd'
|
33
|
-
end
|
34
|
-
|
35
|
-
unless File.exist?( proxyd_tmp_dir )
|
36
|
-
Dir.mkdir( proxyd_tmp_dir )
|
37
|
-
end
|
38
|
-
|
39
|
-
dst_chunk_dir = File.join( proxyd_tmp_dir, 'dst.chunk' )
|
40
|
-
|
41
|
-
unless Dir.exist?( dst_chunk_dir )
|
42
|
-
Dir.mkdir( dst_chunk_dir )
|
43
|
-
end
|
44
|
-
|
45
|
-
tund_chunk_dir = File.join( proxyd_tmp_dir, 'tund.chunk' )
|
46
|
-
|
47
|
-
unless Dir.exist?( tund_chunk_dir )
|
48
|
-
Dir.mkdir( tund_chunk_dir )
|
49
|
-
end
|
50
|
-
|
51
27
|
nprocessors = Etc.nprocessors
|
52
28
|
|
53
|
-
if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors
|
29
|
+
if worker_count.nil? || worker_count <= 0 || worker_count > nprocessors then
|
54
30
|
worker_count = nprocessors
|
55
31
|
end
|
56
32
|
|
57
33
|
title = "girl proxyd #{ Girl::VERSION }"
|
58
34
|
puts title
|
59
35
|
puts "proxyd port #{ proxyd_port }"
|
60
|
-
puts "dst chunk dir #{ dst_chunk_dir }"
|
61
|
-
puts "tund chunk dir #{ tund_chunk_dir }"
|
62
36
|
puts "worker count #{ worker_count }"
|
63
37
|
|
38
|
+
len = CONSTS.map{ | name | name.size }.max
|
39
|
+
|
40
|
+
CONSTS.each do | name |
|
41
|
+
puts "#{ name.gsub( '_', ' ' ).ljust( len ) } #{ Girl.const_get( name ) }"
|
42
|
+
end
|
43
|
+
|
64
44
|
$0 = title
|
65
45
|
workers = []
|
66
46
|
|
67
47
|
worker_count.times do | i |
|
68
48
|
workers << fork do
|
69
49
|
$0 = 'girl proxyd worker'
|
70
|
-
worker = Girl::ProxydWorker.new( proxyd_port
|
50
|
+
worker = Girl::ProxydWorker.new( proxyd_port )
|
71
51
|
|
72
52
|
Signal.trap( :TERM ) do
|
73
53
|
puts "w#{ i } exit"
|
data/lib/girl/proxyd_worker.rb
CHANGED
@@ -4,17 +4,16 @@ module Girl
|
|
4
4
|
##
|
5
5
|
# initialize
|
6
6
|
#
|
7
|
-
def initialize( proxyd_port
|
8
|
-
@dst_chunk_dir = dst_chunk_dir
|
9
|
-
@tund_chunk_dir = tund_chunk_dir
|
7
|
+
def initialize( proxyd_port )
|
10
8
|
@custom = Girl::ProxydCustom.new
|
11
9
|
@mutex = Mutex.new
|
12
10
|
@reads = []
|
13
11
|
@writes = []
|
14
|
-
@roles = {} # sock => :dotr / :proxyd / :dst / :tund
|
15
|
-
@dst_infos = {} # dst => {}
|
16
|
-
@tunds = {} # port => tund
|
12
|
+
@roles = {} # sock => :dotr / :proxyd / :dst / :tund / :tcpd / :streamd
|
17
13
|
@tund_infos = {} # tund => {}
|
14
|
+
@tcpd_infos = {} # tcpd => {}
|
15
|
+
@dst_infos = {} # dst => {}
|
16
|
+
@streamd_infos = {} # streamd => {}
|
18
17
|
@tunneling_tunds = {} # tunneling_addr => tund
|
19
18
|
@resolv_caches = {} # domain => [ ip, created_at ]
|
20
19
|
|
@@ -30,34 +29,40 @@ module Girl
|
|
30
29
|
def looping
|
31
30
|
puts "p#{ Process.pid } #{ Time.new } looping"
|
32
31
|
loop_check_expire
|
33
|
-
|
32
|
+
loop_check_resume
|
34
33
|
|
35
34
|
loop do
|
36
35
|
rs, ws = IO.select( @reads, @writes )
|
37
36
|
|
38
37
|
@mutex.synchronize do
|
39
|
-
#
|
40
|
-
ws.each do | sock |
|
41
|
-
case @roles[ sock ]
|
42
|
-
when :proxyd
|
43
|
-
write_proxyd( sock )
|
44
|
-
when :dst
|
45
|
-
write_dst( sock )
|
46
|
-
when :tund
|
47
|
-
write_tund( sock )
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
38
|
+
# 先读,再写,避免打上关闭标记后读到
|
51
39
|
rs.each do | sock |
|
52
40
|
case @roles[ sock ]
|
53
|
-
when :dotr
|
41
|
+
when :dotr then
|
54
42
|
read_dotr( sock )
|
55
|
-
when :proxyd
|
43
|
+
when :proxyd then
|
56
44
|
read_proxyd( sock )
|
57
|
-
when :
|
58
|
-
read_dst( sock )
|
59
|
-
when :tund
|
45
|
+
when :tund then
|
60
46
|
read_tund( sock )
|
47
|
+
when :tcpd then
|
48
|
+
read_tcpd( sock )
|
49
|
+
when :dst then
|
50
|
+
read_dst( sock )
|
51
|
+
when :streamd then
|
52
|
+
read_streamd( sock )
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
ws.each do | sock |
|
57
|
+
case @roles[ sock ]
|
58
|
+
when :proxyd then
|
59
|
+
write_proxyd( sock )
|
60
|
+
when :tund then
|
61
|
+
write_tund( sock )
|
62
|
+
when :dst then
|
63
|
+
write_dst( sock )
|
64
|
+
when :streamd then
|
65
|
+
write_streamd( sock )
|
61
66
|
end
|
62
67
|
end
|
63
68
|
end
|
@@ -74,7 +79,7 @@ module Girl
|
|
74
79
|
data = [ 0, TUND_FIN ].pack( 'Q>C' )
|
75
80
|
|
76
81
|
@tund_infos.each do | tund, tund_info |
|
77
|
-
if !tund.closed? && tund_info[ :tun_addr ]
|
82
|
+
if !tund.closed? && tund_info[ :tun_addr ] then
|
78
83
|
# puts "debug1 send tund fin"
|
79
84
|
tund.sendmsg( data, 0, tund_info[ :tun_addr ] )
|
80
85
|
end
|
@@ -87,153 +92,172 @@ module Girl
|
|
87
92
|
private
|
88
93
|
|
89
94
|
##
|
90
|
-
#
|
95
|
+
# add proxyd ctlmsg
|
91
96
|
#
|
92
|
-
def
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
@mutex.synchronize do
|
98
|
-
need_trigger = false
|
99
|
-
now = Time.new
|
97
|
+
def add_proxyd_ctlmsg_tund_port( tund_info )
|
98
|
+
data = [ 0, TUND_PORT, tund_info[ :port ], tund_info[ :tcpd_port ] ].pack( 'Q>Cnn' )
|
99
|
+
@proxyd_info[ :ctlmsgs ] << [ data, tund_info[ :tun_addr ] ]
|
100
|
+
add_write( @proxyd )
|
101
|
+
end
|
100
102
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
data = [ 0, HEARTBEAT, rand( 128 ) ].pack( 'Q>CC' )
|
110
|
-
# puts "debug1 #{ Time.new } #{ tund_info[ :port ] } heartbeat"
|
111
|
-
add_tund_ctlmsg( tund, data )
|
112
|
-
|
113
|
-
tund_info[ :dst_exts ].each do | dst_local_port, dst_ext |
|
114
|
-
if dst_ext[ :dst ].closed? && ( now - dst_ext[ :last_continue_at ] > EXPIRE_AFTER )
|
115
|
-
puts "p#{ Process.pid } #{ Time.new } expire dst ext #{ dst_ext[ :domain_port ] }"
|
116
|
-
del_dst_ext( tund, dst_local_port )
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
need_trigger = true
|
122
|
-
end
|
123
|
-
end
|
103
|
+
##
|
104
|
+
# add ctlmsg
|
105
|
+
#
|
106
|
+
def add_ctlmsg( tund, data )
|
107
|
+
tund_info = @tund_infos[ tund ]
|
108
|
+
tund_info[ :ctlmsgs ] << data
|
109
|
+
add_write( tund )
|
110
|
+
end
|
124
111
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
end
|
112
|
+
##
|
113
|
+
# add read
|
114
|
+
#
|
115
|
+
def add_read( sock, role = nil )
|
116
|
+
unless @reads.include?( sock ) then
|
117
|
+
@reads << sock
|
132
118
|
|
133
|
-
|
134
|
-
|
135
|
-
end
|
136
|
-
end
|
119
|
+
if role then
|
120
|
+
@roles[ sock ] = role
|
137
121
|
end
|
138
122
|
end
|
139
123
|
end
|
140
124
|
|
141
125
|
##
|
142
|
-
#
|
126
|
+
# add write
|
143
127
|
#
|
144
|
-
def
|
145
|
-
|
146
|
-
|
147
|
-
sleep CHECK_STATUS_INTERVAL
|
148
|
-
|
149
|
-
if @tunds.any?
|
150
|
-
@mutex.synchronize do
|
151
|
-
need_trigger = false
|
152
|
-
|
153
|
-
@tunds.each do | tund_port, tund |
|
154
|
-
tund_info = @tund_infos[ tund ]
|
155
|
-
|
156
|
-
if tund_info[ :dst_exts ].any?
|
157
|
-
now = Time.new
|
158
|
-
|
159
|
-
tund_info[ :dst_exts ].each do | dst_local_port, dst_ext |
|
160
|
-
if now - dst_ext[ :last_continue_at ] < SEND_STATUS_UNTIL
|
161
|
-
data = [ 0, DEST_STATUS, dst_local_port, dst_ext[ :relay_pack_id ], dst_ext[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
|
162
|
-
add_tund_ctlmsg( tund, data )
|
163
|
-
need_trigger = true
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
if tund_info[ :paused ] && ( tund_info[ :dst_exts ].map{ | _, dst_ext | dst_ext[ :wmems ].size }.sum < RESUME_BELOW )
|
169
|
-
puts "p#{ Process.pid } #{ Time.new } resume tund"
|
170
|
-
tund_info[ :paused ] = false
|
171
|
-
add_write( tund )
|
172
|
-
need_trigger = true
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
if need_trigger
|
177
|
-
next_tick
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
128
|
+
def add_write( sock )
|
129
|
+
unless @writes.include?( sock ) then
|
130
|
+
@writes << sock
|
182
131
|
end
|
183
132
|
end
|
184
133
|
|
185
134
|
##
|
186
|
-
#
|
135
|
+
# close dst
|
187
136
|
#
|
188
|
-
def
|
189
|
-
|
137
|
+
def close_dst( dst )
|
138
|
+
# puts "debug1 close dst"
|
139
|
+
close_sock( dst )
|
140
|
+
del_dst_info( dst )
|
141
|
+
end
|
190
142
|
|
191
|
-
|
192
|
-
|
143
|
+
##
|
144
|
+
# close read dst
|
145
|
+
#
|
146
|
+
def close_read_dst( dst )
|
147
|
+
return if dst.closed?
|
148
|
+
# puts "debug1 close read dst"
|
149
|
+
dst.close_read
|
150
|
+
@reads.delete( dst )
|
151
|
+
|
152
|
+
if dst.closed? then
|
153
|
+
# puts "debug1 delete dst info"
|
154
|
+
@roles.delete( dst )
|
155
|
+
dst_info = del_dst_info( dst )
|
156
|
+
else
|
157
|
+
dst_info = @dst_infos[ dst ]
|
158
|
+
end
|
193
159
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
return
|
198
|
-
end
|
160
|
+
dst_info[ :paused ] = false
|
161
|
+
dst_info
|
162
|
+
end
|
199
163
|
|
200
|
-
|
201
|
-
|
164
|
+
##
|
165
|
+
# close read streamd
|
166
|
+
#
|
167
|
+
def close_read_streamd( streamd )
|
168
|
+
return if streamd.closed?
|
169
|
+
# puts "debug1 close read streamd"
|
170
|
+
streamd.close_read
|
171
|
+
@reads.delete( streamd )
|
172
|
+
|
173
|
+
if streamd.closed? then
|
174
|
+
# puts "debug1 delete streamd info"
|
175
|
+
@roles.delete( streamd )
|
176
|
+
streamd_info = @streamd_infos.delete( streamd )
|
177
|
+
else
|
178
|
+
streamd_info = @streamd_infos[ streamd ]
|
202
179
|
end
|
203
180
|
|
204
|
-
|
205
|
-
|
181
|
+
streamd_info
|
182
|
+
end
|
206
183
|
|
207
|
-
|
208
|
-
|
209
|
-
|
184
|
+
##
|
185
|
+
# close sock
|
186
|
+
#
|
187
|
+
def close_sock( sock )
|
188
|
+
sock.close
|
189
|
+
@reads.delete( sock )
|
190
|
+
@writes.delete( sock )
|
191
|
+
@roles.delete( sock )
|
192
|
+
end
|
210
193
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
194
|
+
##
|
195
|
+
# close streamd
|
196
|
+
#
|
197
|
+
def close_streamd( streamd )
|
198
|
+
# puts "debug1 close streamd"
|
199
|
+
close_sock( streamd )
|
200
|
+
@streamd_infos.delete( streamd )
|
201
|
+
end
|
217
202
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
203
|
+
##
|
204
|
+
# close tund
|
205
|
+
#
|
206
|
+
def close_tund( tund )
|
207
|
+
# puts "debug1 close tund"
|
208
|
+
close_sock( tund )
|
209
|
+
tund_info = @tund_infos.delete( tund )
|
210
|
+
tcpd = tund_info[ :tcpd ]
|
211
|
+
close_sock( tcpd )
|
212
|
+
@tcpd_infos.delete( tcpd )
|
213
|
+
tund_info[ :dsts ].each{ | _, dst | set_dst_closing( dst ) }
|
214
|
+
@tunneling_tunds.delete( tund_info[ :tun_addr ] )
|
215
|
+
end
|
222
216
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
217
|
+
##
|
218
|
+
# close write dst
|
219
|
+
#
|
220
|
+
def close_write_dst( dst )
|
221
|
+
return if dst.closed?
|
222
|
+
# puts "debug1 close write dst"
|
223
|
+
dst.close_write
|
224
|
+
@writes.delete( dst )
|
225
|
+
|
226
|
+
if dst.closed? then
|
227
|
+
# puts "debug1 delete dst info"
|
228
|
+
@roles.delete( dst )
|
229
|
+
dst_info = del_dst_info( dst )
|
230
|
+
else
|
231
|
+
dst_info = @dst_infos[ dst ]
|
232
|
+
end
|
233
|
+
|
234
|
+
dst_info
|
235
|
+
end
|
236
|
+
|
237
|
+
##
|
238
|
+
# close write streamd
|
239
|
+
#
|
240
|
+
def close_write_streamd( streamd )
|
241
|
+
return if streamd.closed?
|
242
|
+
# puts "debug1 close write streamd"
|
243
|
+
streamd.close_write
|
244
|
+
@writes.delete( streamd )
|
245
|
+
|
246
|
+
if streamd.closed? then
|
247
|
+
# puts "debug1 delete streamd info"
|
248
|
+
@roles.delete( streamd )
|
249
|
+
streamd_info = @streamd_infos.delete( streamd )
|
250
|
+
else
|
251
|
+
streamd_info = @streamd_infos[ streamd ]
|
230
252
|
end
|
253
|
+
|
254
|
+
streamd_info
|
231
255
|
end
|
232
256
|
|
233
257
|
##
|
234
258
|
# deal with destination addr
|
235
259
|
#
|
236
|
-
def deal_with_destination_addr( tund, src_id, destination_addr,
|
260
|
+
def deal_with_destination_addr( tund, src_id, destination_addr, domain_port )
|
237
261
|
dst = Socket.new( Addrinfo.new( destination_addr ).ipv4? ? Socket::AF_INET : Socket::AF_INET6, Socket::SOCK_STREAM, 0 )
|
238
262
|
dst.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
|
239
263
|
|
@@ -245,173 +269,191 @@ module Girl
|
|
245
269
|
return false
|
246
270
|
end
|
247
271
|
|
248
|
-
|
272
|
+
dst_id = dst.local_address.ip_port
|
249
273
|
|
250
274
|
@dst_infos[ dst ] = {
|
251
|
-
|
252
|
-
tund: tund,
|
253
|
-
domain_port:
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
275
|
+
id: dst_id, # id
|
276
|
+
tund: tund, # 对应tund
|
277
|
+
domain_port: domain_port, # 域名和端口
|
278
|
+
rbuff: '', # 对应的streamd没准备好,暂存读到的流量
|
279
|
+
streamd: nil, # 对应的streamd
|
280
|
+
wbuff: '', # 从streamd读到的流量
|
281
|
+
src_id: src_id, # 近端src id
|
282
|
+
created_at: Time.new, # 创建时间
|
283
|
+
last_recv_at: nil, # 上一次收到新流量(由streamd收到)的时间
|
284
|
+
last_sent_at: nil, # 上一次发出流量(由streamd发出)的时间
|
285
|
+
paused: false, # 是否已暂停
|
286
|
+
closing: false, # 准备关闭
|
287
|
+
closing_read: false, # 准备关闭读
|
288
|
+
closing_write: false # 准备关闭写
|
261
289
|
}
|
290
|
+
|
262
291
|
add_read( dst, :dst )
|
263
292
|
|
264
293
|
tund_info = @tund_infos[ tund ]
|
265
|
-
tund_info[ :
|
266
|
-
tund_info[ :
|
267
|
-
dst: dst, # dst
|
268
|
-
src_id: src_id, # 近端src id
|
269
|
-
domain_port: destination_domain_port, # 域名和端口
|
270
|
-
wmems: {}, # 写后 pack_id => data
|
271
|
-
send_ats: {}, # 上一次发出时间 pack_id => send_at
|
272
|
-
relay_pack_id: 0, # 转发到几
|
273
|
-
continue_src_pack_id: 0, # 收到几
|
274
|
-
pieces: {}, # 跳号包 src_pack_id => data
|
275
|
-
is_src_closed: false, # src是否已关闭
|
276
|
-
biggest_src_pack_id: 0, # src最大包号码
|
277
|
-
completed_pack_id: 0, # 完成到几(对面收到几)
|
278
|
-
last_continue_at: Time.new # 上一次发生流量的时间
|
279
|
-
}
|
280
|
-
|
281
|
-
data = [ 0, PAIRED, src_id, local_port ].pack( 'Q>CQ>n' )
|
282
|
-
# puts "debug1 add ctlmsg paired #{ data.inspect }"
|
283
|
-
add_tund_ctlmsg( tund, data )
|
294
|
+
tund_info[ :dst_ids ][ src_id ] = dst_id
|
295
|
+
tund_info[ :dsts ][ dst_id ] = dst
|
284
296
|
|
297
|
+
data = [ 0, PAIRED, src_id, dst_id ].pack( 'Q>CQ>n' )
|
298
|
+
# puts "debug1 add ctlmsg paired #{ src_id } #{ dst_id }"
|
299
|
+
add_ctlmsg( tund, data )
|
285
300
|
true
|
286
301
|
end
|
287
302
|
|
288
303
|
##
|
289
|
-
#
|
304
|
+
# del dst info
|
290
305
|
#
|
291
|
-
def
|
292
|
-
|
293
|
-
|
294
|
-
proxyd.bind( Socket.sockaddr_in( proxyd_port, '0.0.0.0' ) )
|
306
|
+
def del_dst_info( dst )
|
307
|
+
dst_info = @dst_infos.delete( dst )
|
308
|
+
tund = dst_info[ :tund ]
|
295
309
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
310
|
+
unless tund.closed? then
|
311
|
+
tund_info = @tund_infos[ tund ]
|
312
|
+
tund_info[ :dsts ].delete( dst_info[ :id ] )
|
313
|
+
tund_info[ :dst_ids ].delete( dst_info[ :src_id ] )
|
314
|
+
end
|
301
315
|
|
302
|
-
|
303
|
-
# add proxyd ctlmsg
|
304
|
-
#
|
305
|
-
def add_proxyd_ctlmsg( data, to_addr )
|
306
|
-
@proxyd_ctlmsgs << [ to_addr, data ]
|
307
|
-
add_write( @proxyd )
|
316
|
+
dst_info
|
308
317
|
end
|
309
318
|
|
310
319
|
##
|
311
|
-
#
|
320
|
+
# loop check expire
|
312
321
|
#
|
313
|
-
def
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
end
|
322
|
+
def loop_check_expire
|
323
|
+
Thread.new do
|
324
|
+
loop do
|
325
|
+
sleep CHECK_EXPIRE_INTERVAL
|
318
326
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
def add_tund_wbuff( tund, dst_local_port, pack_id, data )
|
323
|
-
tund_info = @tund_infos[ tund ]
|
324
|
-
tund_info[ :wbuffs ] << [ dst_local_port, pack_id, data ]
|
325
|
-
|
326
|
-
if tund_info[ :wbuffs ].size >= WBUFFS_LIMIT
|
327
|
-
spring = tund_info[ :chunks ].size > 0 ? ( tund_info[ :spring ] + 1 ) : 0
|
328
|
-
filename = "#{ Process.pid }-#{ tund_info[ :port ] }.#{ spring }"
|
329
|
-
chunk_path = File.join( @tund_chunk_dir, filename )
|
330
|
-
datas = tund_info[ :wbuffs ].map{ | _dst_local_port, _pack_id, _data | [ [ _dst_local_port, _pack_id, _data.bytesize ].pack( 'nQ>n' ), _data ].join }
|
331
|
-
|
332
|
-
begin
|
333
|
-
IO.binwrite( chunk_path, datas.join )
|
334
|
-
rescue Errno::ENOSPC => e
|
335
|
-
puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close tund"
|
336
|
-
set_is_closing( tund )
|
337
|
-
return
|
338
|
-
end
|
327
|
+
@mutex.synchronize do
|
328
|
+
trigger = false
|
329
|
+
now = Time.new
|
339
330
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
end
|
331
|
+
@tund_infos.each do | tund, tund_info |
|
332
|
+
last_recv_at = tund_info[ :last_recv_at ] || tund_info[ :created_at ]
|
333
|
+
last_sent_at = tund_info[ :last_sent_at ] || tund_info[ :created_at ]
|
344
334
|
|
345
|
-
|
335
|
+
if tund_info[ :dsts ].empty? && ( now - last_recv_at >= EXPIRE_AFTER ) && ( now - last_sent_at >= EXPIRE_AFTER ) then
|
336
|
+
puts "p#{ Process.pid } #{ Time.new } expire tund #{ tund_info[ :port ] }"
|
337
|
+
set_tund_closing( tund )
|
338
|
+
trigger = true
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
@dst_infos.each do | dst, dst_info |
|
343
|
+
last_recv_at = dst_info[ :last_recv_at ] || dst_info[ :created_at ]
|
344
|
+
last_sent_at = dst_info[ :last_sent_at ] || dst_info[ :created_at ]
|
345
|
+
|
346
|
+
if ( now - last_recv_at >= EXPIRE_AFTER ) && ( now - last_sent_at >= EXPIRE_AFTER ) then
|
347
|
+
puts "p#{ Process.pid } #{ Time.new } expire dst #{ dst_info[ :domain_port ] }"
|
348
|
+
set_dst_closing( dst )
|
349
|
+
trigger = true
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
next_tick if trigger
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
346
357
|
end
|
347
358
|
|
348
359
|
##
|
349
|
-
#
|
360
|
+
# loop check resume
|
350
361
|
#
|
351
|
-
def
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
if dst_info[ :wbuff ].bytesize >= CHUNK_SIZE
|
356
|
-
spring = dst_info[ :chunks ].size > 0 ? ( dst_info[ :spring ] + 1 ) : 0
|
357
|
-
filename = "#{ Process.pid }-#{ dst_info[ :local_port ] }.#{ spring }"
|
358
|
-
chunk_path = File.join( @dst_chunk_dir, filename )
|
359
|
-
|
360
|
-
begin
|
361
|
-
IO.binwrite( chunk_path, dst_info[ :wbuff ] )
|
362
|
-
rescue Errno::ENOSPC => e
|
363
|
-
puts "p#{ Process.pid } #{ Time.new } #{ e.class }, close dst"
|
364
|
-
set_is_closing( dst )
|
365
|
-
return
|
366
|
-
end
|
362
|
+
def loop_check_resume
|
363
|
+
Thread.new do
|
364
|
+
loop do
|
365
|
+
sleep CHECK_RESUME_INTERVAL
|
367
366
|
|
368
|
-
|
369
|
-
|
370
|
-
dst_info[ :wbuff ].clear
|
371
|
-
end
|
367
|
+
@mutex.synchronize do
|
368
|
+
trigger = false
|
372
369
|
|
373
|
-
|
370
|
+
@dst_infos.select{ | _, dst_info | dst_info[ :paused ] }.each do | dst, dst_info |
|
371
|
+
streamd = dst_info[ :streamd ]
|
372
|
+
streamd_info = @streamd_infos[ streamd ]
|
373
|
+
|
374
|
+
if streamd_info[ :wbuff ].size < RESUME_BELOW then
|
375
|
+
puts "p#{ Process.pid } #{ Time.new } resume dst #{ dst_info[ :domain_port ] }"
|
376
|
+
dst_info[ :paused ] = false
|
377
|
+
add_read( dst )
|
378
|
+
trigger = true
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
next_tick if trigger
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
374
386
|
end
|
375
387
|
|
376
388
|
##
|
377
|
-
#
|
389
|
+
# new a proxyd
|
378
390
|
#
|
379
|
-
def
|
380
|
-
|
381
|
-
|
382
|
-
|
391
|
+
def new_a_proxyd( proxyd_port )
|
392
|
+
proxyd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
393
|
+
proxyd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
394
|
+
proxyd.bind( Socket.sockaddr_in( proxyd_port, '0.0.0.0' ) )
|
395
|
+
|
396
|
+
puts "p#{ Process.pid } #{ Time.new } proxyd bind on #{ proxyd_port }"
|
397
|
+
@proxyd = proxyd
|
398
|
+
@proxyd_info = {
|
399
|
+
ctlmsgs: [] # [ ctlmsg, to_addr ]
|
400
|
+
}
|
383
401
|
|
384
|
-
|
402
|
+
add_read( proxyd, :proxyd )
|
385
403
|
end
|
386
404
|
|
387
405
|
##
|
388
|
-
#
|
406
|
+
# next tick
|
389
407
|
#
|
390
|
-
def
|
391
|
-
|
392
|
-
@writes << sock
|
393
|
-
end
|
408
|
+
def next_tick
|
409
|
+
@dotw.write( '.' )
|
394
410
|
end
|
395
411
|
|
396
412
|
##
|
397
|
-
#
|
413
|
+
# resolve domain
|
398
414
|
#
|
399
|
-
def
|
400
|
-
|
401
|
-
|
402
|
-
|
415
|
+
def resolve_domain( tund, src_id, domain_port )
|
416
|
+
resolv_cache = @resolv_caches[ domain_port ]
|
417
|
+
|
418
|
+
if resolv_cache then
|
419
|
+
destination_addr, created_at = resolv_cache
|
420
|
+
|
421
|
+
if Time.new - created_at < RESOLV_CACHE_EXPIRE then
|
422
|
+
# puts "debug1 #{ domain_port } hit resolv cache #{ Addrinfo.new( destination_addr ).inspect }"
|
423
|
+
deal_with_destination_addr( tund, src_id, destination_addr, domain_port )
|
424
|
+
return
|
425
|
+
end
|
426
|
+
|
427
|
+
# puts "debug1 expire #{ domain_port } resolv cache"
|
428
|
+
@resolv_caches.delete( domain_port )
|
429
|
+
end
|
403
430
|
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
431
|
+
Thread.new do
|
432
|
+
colon_idx = domain_port.rindex( ':' )
|
433
|
+
|
434
|
+
if colon_idx then
|
435
|
+
destination_domain = domain_port[ 0...colon_idx ]
|
436
|
+
destination_port = domain_port[ ( colon_idx + 1 )..-1 ].to_i
|
437
|
+
|
438
|
+
begin
|
439
|
+
destination_addr = Socket.sockaddr_in( destination_port, destination_domain )
|
440
|
+
rescue Exception => e
|
441
|
+
puts "p#{ Process.pid } #{ Time.new } sockaddr in #{ domain_port } #{ e.class }"
|
442
|
+
end
|
411
443
|
end
|
412
444
|
|
413
|
-
@
|
414
|
-
|
445
|
+
@mutex.synchronize do
|
446
|
+
if destination_addr then
|
447
|
+
# puts "debug1 resolved #{ domain_port } #{ Addrinfo.new( destination_addr ).inspect }"
|
448
|
+
@resolv_caches[ domain_port ] = [ destination_addr, Time.new ]
|
449
|
+
|
450
|
+
unless tund.closed? then
|
451
|
+
if deal_with_destination_addr( tund, src_id, destination_addr, domain_port ) then
|
452
|
+
next_tick
|
453
|
+
end
|
454
|
+
end
|
455
|
+
end
|
456
|
+
end
|
415
457
|
end
|
416
458
|
end
|
417
459
|
|
@@ -420,358 +462,217 @@ module Girl
|
|
420
462
|
#
|
421
463
|
def send_data( sock, data, to_addr )
|
422
464
|
begin
|
423
|
-
sock.
|
465
|
+
written = sock.sendmsg_nonblock( data, 0, to_addr )
|
424
466
|
rescue IO::WaitWritable, Errno::EINTR
|
425
|
-
return
|
467
|
+
return :wait
|
426
468
|
rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
|
427
|
-
|
428
|
-
|
429
|
-
close_tund( sock )
|
430
|
-
return false
|
431
|
-
end
|
469
|
+
puts "p#{ Process.pid } #{ Time.new } sendmsg #{ e.class }"
|
470
|
+
return :fatal
|
432
471
|
end
|
433
472
|
|
434
|
-
|
473
|
+
written
|
435
474
|
end
|
436
475
|
|
437
476
|
##
|
438
|
-
#
|
477
|
+
# set dst closing
|
439
478
|
#
|
440
|
-
def
|
441
|
-
|
442
|
-
|
443
|
-
dst_info
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
File.delete( File.join( @dst_chunk_dir, filename ) )
|
448
|
-
rescue Errno::ENOENT
|
449
|
-
end
|
450
|
-
end
|
479
|
+
def set_dst_closing( dst )
|
480
|
+
return if dst.closed?
|
481
|
+
dst_info = @dst_infos[ dst ]
|
482
|
+
dst_info[ :closing ] = true
|
483
|
+
@reads.delete( dst )
|
484
|
+
add_write( dst )
|
485
|
+
end
|
451
486
|
|
452
|
-
|
453
|
-
|
487
|
+
##
|
488
|
+
# set dst closing write
|
489
|
+
#
|
490
|
+
def set_dst_closing_write( dst )
|
491
|
+
return if dst.closed?
|
492
|
+
dst_info = @dst_infos[ dst ]
|
493
|
+
dst_info[ :closing_write ] = true
|
494
|
+
add_write( dst )
|
495
|
+
end
|
454
496
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
add_tund_ctlmsg( tund, data )
|
465
|
-
else
|
466
|
-
# puts "debug1 3-1. after close dst -> src closed ? no -> send fin1"
|
467
|
-
data = [ 0, FIN1, local_port, dst_info[ :biggest_pack_id ], dst_ext[ :continue_src_pack_id ] ].pack( 'Q>CnQ>Q>' )
|
468
|
-
add_tund_ctlmsg( tund, data )
|
469
|
-
end
|
497
|
+
##
|
498
|
+
# set streamd closing
|
499
|
+
#
|
500
|
+
def set_streamd_closing( streamd )
|
501
|
+
return if streamd.closed?
|
502
|
+
streamd_info = @streamd_infos[ streamd ]
|
503
|
+
streamd_info[ :closing ] = true
|
504
|
+
@reads.delete( streamd )
|
505
|
+
add_write( streamd )
|
470
506
|
end
|
471
507
|
|
472
508
|
##
|
473
|
-
#
|
509
|
+
# set streamd closing write
|
474
510
|
#
|
475
|
-
def
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
tund_info[ :chunks ].each do | filename |
|
481
|
-
begin
|
482
|
-
File.delete( File.join( @tund_chunk_dir, filename ) )
|
483
|
-
rescue Errno::ENOENT
|
484
|
-
end
|
485
|
-
end
|
486
|
-
|
487
|
-
tund_info[ :dst_exts ].each{ | _, dst_ext | set_is_closing( dst_ext[ :dst ] ) }
|
488
|
-
@tunneling_tunds.delete( tund_info[ :tun_addr ] )
|
489
|
-
@tunds.delete( tund_info[ :port ] )
|
511
|
+
def set_streamd_closing_write( streamd )
|
512
|
+
return if streamd.closed?
|
513
|
+
streamd_info = @streamd_infos[ streamd ]
|
514
|
+
streamd_info[ :closing_write ] = true
|
515
|
+
add_write( streamd )
|
490
516
|
end
|
491
517
|
|
492
518
|
##
|
493
|
-
#
|
519
|
+
# set tund is closing
|
494
520
|
#
|
495
|
-
def
|
496
|
-
|
497
|
-
@
|
498
|
-
|
499
|
-
@
|
521
|
+
def set_tund_closing( tund )
|
522
|
+
return if tund.closed?
|
523
|
+
tund_info = @tund_infos[ tund ]
|
524
|
+
tund_info[ :closing ] = true
|
525
|
+
@reads.delete( tund )
|
526
|
+
add_write( tund )
|
500
527
|
end
|
501
528
|
|
502
529
|
##
|
503
|
-
#
|
530
|
+
# read dotr
|
504
531
|
#
|
505
|
-
def
|
506
|
-
|
507
|
-
dst_ext = tund_info[ :dst_exts ].delete( dst_local_port )
|
508
|
-
|
509
|
-
if dst_ext
|
510
|
-
tund_info[ :dst_local_ports ].delete( dst_ext[ :src_id ] )
|
511
|
-
end
|
532
|
+
def read_dotr( dotr )
|
533
|
+
dotr.read( 1 )
|
512
534
|
end
|
513
535
|
|
514
536
|
##
|
515
|
-
#
|
537
|
+
# read proxyd
|
516
538
|
#
|
517
|
-
def
|
518
|
-
|
519
|
-
|
539
|
+
def read_proxyd( proxyd )
|
540
|
+
data, addrinfo, rflags, *controls = proxyd.recvmsg
|
541
|
+
from_addr = addrinfo.to_sockaddr
|
520
542
|
|
521
|
-
|
543
|
+
if @tunneling_tunds.include?( from_addr ) then
|
544
|
+
tund = @tunneling_tunds[ from_addr ]
|
545
|
+
tund_info = @tund_infos[ tund ]
|
546
|
+
puts "p#{ Process.pid } #{ Time.new } resend tund port #{ tund_info[ :port ] }, #{ tund_info[ :stream_port ] }"
|
547
|
+
add_proxyd_ctlmsg_tund_port( tund_info )
|
548
|
+
return
|
549
|
+
end
|
522
550
|
|
523
|
-
|
524
|
-
dst_ext[ :wmems ].delete( pack_id )
|
525
|
-
dst_ext[ :send_ats ].delete( pack_id )
|
526
|
-
end
|
551
|
+
result = @custom.check( data, addrinfo )
|
527
552
|
|
528
|
-
|
553
|
+
if result != :success then
|
554
|
+
puts "p#{ Process.pid } #{ Time.new } #{ result }"
|
555
|
+
return
|
529
556
|
end
|
530
|
-
end
|
531
557
|
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
@dotw.write( '.' )
|
537
|
-
end
|
538
|
-
|
539
|
-
##
|
540
|
-
# write proxyd
|
541
|
-
#
|
542
|
-
def write_proxyd( proxyd )
|
543
|
-
while @proxyd_ctlmsgs.any?
|
544
|
-
to_addr, data = @proxyd_ctlmsgs.first
|
558
|
+
tund = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
559
|
+
tund.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
560
|
+
tund_port = tund.local_address.ip_port
|
561
|
+
add_read( tund, :tund )
|
545
562
|
|
546
|
-
|
547
|
-
|
548
|
-
|
563
|
+
tcpd = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
564
|
+
tcpd.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 ) if RUBY_PLATFORM.include?( 'linux' )
|
565
|
+
tcpd.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
566
|
+
tcpd_port = tcpd.local_address.ip_port
|
567
|
+
tcpd.listen( 127 )
|
568
|
+
add_read( tcpd, :tcpd )
|
569
|
+
|
570
|
+
tund_info = {
|
571
|
+
port: tund_port, # 端口
|
572
|
+
tcpd: tcpd, # 对应的tcpd
|
573
|
+
tcpd_port: tcpd_port, # tcpd端口
|
574
|
+
ctlmsgs: [], # [ ctlmsg, to_addr ]
|
575
|
+
tun_addr: from_addr, # tun地址
|
576
|
+
dsts: {}, # dst_id => dst
|
577
|
+
dst_ids: {}, # src_id => dst_id
|
578
|
+
created_at: Time.new, # 创建时间
|
579
|
+
last_recv_at: nil, # 上一次收到流量的时间
|
580
|
+
last_sent_at: nil, # 上一次发出流量的时间
|
581
|
+
closing: false, # 准备关闭
|
582
|
+
closing_read: false, # 准备关闭读
|
583
|
+
closing_write: false, # 准备关闭写
|
584
|
+
changed_tun_addr: nil # 记录到和tun addr不符的来源地址
|
585
|
+
}
|
549
586
|
|
550
|
-
|
551
|
-
|
587
|
+
@tunneling_tunds[ from_addr ] = tund
|
588
|
+
@tund_infos[ tund ] = tund_info
|
589
|
+
@tcpd_infos[ tcpd ] = {
|
590
|
+
tund: tund
|
591
|
+
}
|
552
592
|
|
553
|
-
@
|
593
|
+
puts "p#{ Process.pid } #{ Time.new } a new tunnel #{ addrinfo.ip_unpack.inspect } - #{ tund_port }, #{ tcpd_port }, #{ @tund_infos.size } tunds"
|
594
|
+
add_proxyd_ctlmsg_tund_port( tund_info )
|
554
595
|
end
|
555
596
|
|
556
597
|
##
|
557
|
-
#
|
598
|
+
# read tund
|
558
599
|
#
|
559
|
-
def
|
560
|
-
dst_info = @dst_infos[ dst ]
|
561
|
-
from, data = :cache, dst_info[ :cache ]
|
562
|
-
|
563
|
-
if data.empty?
|
564
|
-
if dst_info[ :chunks ].any?
|
565
|
-
path = File.join( @dst_chunk_dir, dst_info[ :chunks ].shift )
|
566
|
-
|
567
|
-
begin
|
568
|
-
data = dst_info[ :cache ] = IO.binread( path )
|
569
|
-
File.delete( path )
|
570
|
-
rescue Errno::ENOENT => e
|
571
|
-
puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
|
572
|
-
close_dst( dst )
|
573
|
-
return
|
574
|
-
end
|
575
|
-
else
|
576
|
-
from, data = :wbuff, dst_info[ :wbuff ]
|
577
|
-
end
|
578
|
-
end
|
579
|
-
|
580
|
-
if data.empty?
|
581
|
-
if dst_info[ :is_closing ]
|
582
|
-
close_dst( dst )
|
583
|
-
else
|
584
|
-
@writes.delete( dst )
|
585
|
-
end
|
586
|
-
|
587
|
-
return
|
588
|
-
end
|
589
|
-
|
600
|
+
def read_tund( tund )
|
590
601
|
begin
|
591
|
-
|
592
|
-
rescue IO::
|
593
|
-
|
594
|
-
rescue Exception => e
|
595
|
-
# puts "debug1 write dst #{ e.class }"
|
596
|
-
close_dst( dst )
|
602
|
+
data, addrinfo, rflags, *controls = tund.recvmsg_nonblock
|
603
|
+
rescue IO::WaitReadable, Errno::EINTR
|
604
|
+
print 'r'
|
597
605
|
return
|
598
606
|
end
|
599
607
|
|
600
|
-
|
601
|
-
data = data[ written..-1 ]
|
602
|
-
dst_info[ from ] = data
|
603
|
-
dst_info[ :last_continue_at ] = Time.new
|
604
|
-
end
|
605
|
-
|
606
|
-
##
|
607
|
-
# write tund
|
608
|
-
#
|
609
|
-
def write_tund( tund )
|
610
|
-
now = Time.new
|
608
|
+
from_addr = addrinfo.to_sockaddr
|
611
609
|
tund_info = @tund_infos[ tund ]
|
612
610
|
|
613
|
-
if tund_info[ :
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
close_tund( tund )
|
611
|
+
if from_addr != tund_info[ :tun_addr ] then
|
612
|
+
# 通常是光猫刷新ip和端口,但万一不是,为了避免脏数据注入,关闭tund
|
613
|
+
puts "p#{ Process.pid } #{ Time.new } from #{ addrinfo.inspect } not match tun addr #{ Addrinfo.new( tund_info[ :tun_addr ] ).inspect }"
|
614
|
+
tund_info[ :changed_tun_addr ] = from_addr
|
615
|
+
set_tund_closing( tund )
|
620
616
|
return
|
621
617
|
end
|
622
618
|
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
unless send_data( tund, data, tund_info[ :tun_addr ] )
|
628
|
-
return
|
629
|
-
end
|
630
|
-
|
631
|
-
tund_info[ :ctlmsgs ].shift
|
632
|
-
end
|
619
|
+
tund_info[ :last_recv_at ] = Time.new
|
620
|
+
pack_id = data[ 0, 8 ].unpack( 'Q>' ).first
|
621
|
+
return if pack_id != 0
|
633
622
|
|
634
|
-
|
635
|
-
while tund_info[ :resendings ].any?
|
636
|
-
dst_local_port, pack_id = tund_info[ :resendings ].first
|
637
|
-
dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
|
623
|
+
ctl_num = data[ 8 ].unpack( 'C' ).first
|
638
624
|
|
639
|
-
|
640
|
-
|
625
|
+
case ctl_num
|
626
|
+
when A_NEW_SOURCE then
|
627
|
+
src_id = data[ 9, 8 ].unpack( 'Q>' ).first
|
628
|
+
dst_id = tund_info[ :dst_ids ][ src_id ]
|
641
629
|
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
end
|
630
|
+
if dst_id then
|
631
|
+
dst = tund_info[ :dsts ][ dst_id ]
|
632
|
+
return unless dst
|
646
633
|
|
647
|
-
|
634
|
+
if dst.closed? then
|
635
|
+
dst_id = 0
|
648
636
|
end
|
649
|
-
end
|
650
637
|
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
# 若写后达到上限,暂停取写前
|
655
|
-
if tund_info[ :dst_exts ].map{ | _, dst_ext | dst_ext[ :wmems ].size }.sum >= WMEMS_LIMIT
|
656
|
-
unless tund_info[ :paused ]
|
657
|
-
puts "p#{ Process.pid } #{ Time.new } pause tund #{ tund_info[ :port ] }"
|
658
|
-
tund_info[ :paused ] = true
|
659
|
-
end
|
660
|
-
|
661
|
-
@writes.delete( tund )
|
662
|
-
return
|
663
|
-
end
|
664
|
-
|
665
|
-
# 取写前
|
666
|
-
if tund_info[ :caches ].any?
|
667
|
-
datas = tund_info[ :caches ]
|
668
|
-
elsif tund_info[ :chunks ].any?
|
669
|
-
path = File.join( @tund_chunk_dir, tund_info[ :chunks ].shift )
|
670
|
-
|
671
|
-
begin
|
672
|
-
data = IO.binread( path )
|
673
|
-
File.delete( path )
|
674
|
-
rescue Errno::ENOENT => e
|
675
|
-
puts "p#{ Process.pid } #{ Time.new } read #{ path } #{ e.class }"
|
676
|
-
close_tund( tund )
|
638
|
+
# puts "debug1 resend paired #{ dst_id }"
|
639
|
+
data2 = [ 0, PAIRED, src_id, dst_id ].pack( 'Q>CQ>n' )
|
640
|
+
add_ctlmsg( tund, data2 )
|
677
641
|
return
|
678
642
|
end
|
679
643
|
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
datas = tund_info[ :caches ] = caches
|
689
|
-
elsif tund_info[ :wbuffs ].any?
|
690
|
-
datas = tund_info[ :wbuffs ]
|
691
|
-
else
|
692
|
-
@writes.delete( tund )
|
693
|
-
return
|
644
|
+
data = data[ 17..-1 ]
|
645
|
+
domain_port = @custom.decode( data )
|
646
|
+
# puts "debug1 a new source #{ src_id } #{ domain_port }"
|
647
|
+
resolve_domain( tund, src_id, domain_port )
|
648
|
+
when TUN_FIN then
|
649
|
+
puts "p#{ Process.pid } #{ Time.new } recv tun fin"
|
650
|
+
set_tund_closing( tund )
|
694
651
|
end
|
695
|
-
|
696
|
-
while datas.any?
|
697
|
-
dst_local_port, pack_id, data = datas.first
|
698
|
-
dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
|
699
|
-
|
700
|
-
if dst_ext
|
701
|
-
if pack_id <= CONFUSE_UNTIL
|
702
|
-
data = @custom.encode( data )
|
703
|
-
# puts "debug1 encoded pack #{ pack_id }"
|
704
|
-
end
|
705
|
-
|
706
|
-
data = [ [ pack_id, dst_local_port ].pack( 'Q>n' ), data ].join
|
707
|
-
|
708
|
-
unless send_data( tund, data, tund_info[ :tun_addr ] )
|
709
|
-
return
|
710
|
-
end
|
711
|
-
|
712
|
-
# puts "debug2 written pack #{ pack_id }"
|
713
|
-
dst_ext[ :relay_pack_id ] = pack_id
|
714
|
-
dst_ext[ :wmems ][ pack_id ] = data
|
715
|
-
dst_ext[ :send_ats ][ pack_id ] = now
|
716
|
-
dst_ext[ :last_continue_at ] = now
|
717
|
-
end
|
718
|
-
|
719
|
-
datas.shift
|
720
|
-
end
|
721
|
-
end
|
722
|
-
|
723
|
-
##
|
724
|
-
# read dotr
|
725
|
-
#
|
726
|
-
def read_dotr( dotr )
|
727
|
-
dotr.read( 1 )
|
728
652
|
end
|
729
653
|
|
730
654
|
##
|
731
|
-
# read
|
655
|
+
# read tcpd
|
732
656
|
#
|
733
|
-
def
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
result = @custom.check( data, addrinfo )
|
740
|
-
|
741
|
-
if result != :success
|
742
|
-
puts "p#{ Process.pid } #{ Time.new } #{ result }"
|
657
|
+
def read_tcpd( tcpd )
|
658
|
+
begin
|
659
|
+
streamd, addrinfo = tcpd.accept_nonblock
|
660
|
+
rescue IO::WaitReadable, Errno::EINTR
|
661
|
+
print 'r'
|
743
662
|
return
|
744
663
|
end
|
745
664
|
|
746
|
-
|
747
|
-
|
748
|
-
|
665
|
+
# puts "debug1 accept a streamd"
|
666
|
+
tcpd_info = @tcpd_infos[ tcpd ]
|
667
|
+
tund = tcpd_info[ :tund ]
|
749
668
|
|
750
|
-
@
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
ctlmsgs: [], # data
|
755
|
-
wbuffs: [], # 写前缓存 [ dst_local_port, pack_id, data ]
|
756
|
-
caches: [], # 块读出缓存 [ dst_local_port, pack_id, data ]
|
757
|
-
chunks: [], # 块队列 filename
|
758
|
-
spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
|
759
|
-
tun_addr: from_addr, # tun地址
|
760
|
-
dst_exts: {}, # dst额外信息 dst_local_port => {}
|
761
|
-
dst_local_ports: {}, # src_id => dst_local_port
|
762
|
-
paused: false, # 是否暂停写
|
763
|
-
resendings: [], # 重传队列 [ dst_local_port, pack_id ]
|
764
|
-
created_at: Time.new, # 创建时间
|
765
|
-
last_recv_at: nil, # 上一次收到流量的时间,过期关闭
|
766
|
-
is_closing: false, # 是否准备关闭
|
767
|
-
changed_tun_addr: nil # 记录到和tun addr不符的来源地址
|
669
|
+
@streamd_infos[ streamd ] = {
|
670
|
+
tund: tund, # 对应tund
|
671
|
+
dst: nil, # 对应dst
|
672
|
+
wbuff: '' # 写前,写往近端stream
|
768
673
|
}
|
769
674
|
|
770
|
-
add_read(
|
771
|
-
|
772
|
-
data = [ 0, TUND_PORT, port ].pack( 'Q>Cn' )
|
773
|
-
puts "p#{ Process.pid } #{ Time.new } a new tunnel #{ addrinfo.ip_unpack.inspect } - #{ port }, #{ @tunds.size } tunds"
|
774
|
-
add_proxyd_ctlmsg( data, from_addr )
|
675
|
+
add_read( streamd, :streamd )
|
775
676
|
end
|
776
677
|
|
777
678
|
##
|
@@ -779,211 +680,271 @@ module Girl
|
|
779
680
|
#
|
780
681
|
def read_dst( dst )
|
781
682
|
begin
|
782
|
-
data = dst.read_nonblock(
|
683
|
+
data = dst.read_nonblock( READ_SIZE )
|
783
684
|
rescue IO::WaitReadable, Errno::EINTR
|
685
|
+
print 'r'
|
784
686
|
return
|
785
687
|
rescue Exception => e
|
786
688
|
# puts "debug1 read dst #{ e.class }"
|
787
|
-
|
689
|
+
dst_info = close_read_dst( dst )
|
690
|
+
streamd = dst_info[ :streamd ]
|
691
|
+
set_streamd_closing_write( streamd ) if streamd
|
788
692
|
return
|
789
693
|
end
|
790
694
|
|
791
|
-
# puts "debug2 read dst #{ data.inspect }"
|
792
695
|
dst_info = @dst_infos[ dst ]
|
793
|
-
dst_info[ :
|
794
|
-
|
696
|
+
streamd = dst_info[ :streamd ]
|
697
|
+
|
698
|
+
if streamd then
|
699
|
+
unless streamd.closed? then
|
700
|
+
streamd_info = @streamd_infos[ streamd ]
|
701
|
+
data = @custom.encode( data )
|
702
|
+
# puts "debug2 add streamd.wbuff encoded #{ data.bytesize }"
|
703
|
+
streamd_info[ :wbuff ] << data
|
704
|
+
add_write( streamd )
|
705
|
+
|
706
|
+
if streamd_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
|
707
|
+
puts "p#{ Process.pid } #{ Time.new } pause dst #{ dst_info[ :id ] } #{ dst_info[ :domain_port ] }"
|
708
|
+
dst_info[ :paused ] = true
|
709
|
+
@reads.delete( dst )
|
710
|
+
end
|
711
|
+
end
|
712
|
+
else
|
713
|
+
dst_info[ :rbuff ] << data
|
795
714
|
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
715
|
+
if dst_info[ :rbuff ].bytesize >= WBUFF_LIMIT then
|
716
|
+
# puts "debug1 dst.rbuff full"
|
717
|
+
set_dst_closing( dst )
|
718
|
+
end
|
800
719
|
end
|
801
|
-
|
802
|
-
pack_id = dst_info[ :biggest_pack_id ] + 1
|
803
|
-
dst_info[ :biggest_pack_id ] = pack_id
|
804
|
-
add_tund_wbuff( tund, dst_info[ :local_port ], pack_id, data )
|
805
720
|
end
|
806
721
|
|
807
722
|
##
|
808
|
-
# read
|
723
|
+
# read streamd
|
809
724
|
#
|
810
|
-
def
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
#
|
818
|
-
|
819
|
-
|
820
|
-
|
725
|
+
def read_streamd( streamd )
|
726
|
+
begin
|
727
|
+
data = streamd.read_nonblock( READ_SIZE )
|
728
|
+
rescue IO::WaitReadable, Errno::EINTR
|
729
|
+
print 'r'
|
730
|
+
return
|
731
|
+
rescue Exception => e
|
732
|
+
# puts "debug1 read streamd #{ e.class }"
|
733
|
+
streamd_info = close_read_streamd( streamd )
|
734
|
+
dst = streamd_info[ :dst ]
|
735
|
+
set_dst_closing_write( dst ) if dst
|
821
736
|
return
|
822
737
|
end
|
823
738
|
|
824
|
-
|
825
|
-
|
739
|
+
streamd_info = @streamd_infos[ streamd ]
|
740
|
+
dst = streamd_info[ :dst ]
|
826
741
|
|
827
|
-
|
828
|
-
|
742
|
+
unless dst then
|
743
|
+
dst_id = data[ 0, 2 ].unpack( 'n' ).first
|
744
|
+
tund = streamd_info[ :tund ]
|
829
745
|
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
if dst_local_port
|
836
|
-
dst_ext = tund_info[ :dst_exts ][ dst_local_port ]
|
837
|
-
return unless dst_ext
|
838
|
-
|
839
|
-
if dst_ext[ :dst ].closed?
|
840
|
-
dst_local_port = 0
|
841
|
-
end
|
746
|
+
if tund.closed? then
|
747
|
+
set_streamd_closing( streamd )
|
748
|
+
return
|
749
|
+
end
|
842
750
|
|
843
|
-
|
844
|
-
|
845
|
-
add_tund_ctlmsg( tund, data2 )
|
846
|
-
return
|
847
|
-
end
|
751
|
+
tund_info = @tund_infos[ tund ]
|
752
|
+
dst = tund_info[ :dsts ][ dst_id ]
|
848
753
|
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
when SOURCE_STATUS
|
854
|
-
src_id, relay_src_pack_id, continue_dst_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
|
754
|
+
unless dst then
|
755
|
+
set_streamd_closing( streamd )
|
756
|
+
return
|
757
|
+
end
|
855
758
|
|
856
|
-
|
857
|
-
|
759
|
+
# puts "debug1 set streamd.dst #{ dst_id }"
|
760
|
+
streamd_info[ :dst ] = dst
|
761
|
+
dst_info = @dst_infos[ dst ]
|
858
762
|
|
859
|
-
|
860
|
-
|
763
|
+
unless dst_info[ :rbuff ].empty? then
|
764
|
+
# puts "debug1 encode and move dst.rbuff to streamd.wbuff"
|
765
|
+
streamd_info[ :wbuff ] << @custom.encode( dst_info[ :rbuff ] )
|
766
|
+
end
|
861
767
|
|
862
|
-
|
768
|
+
dst_info[ :streamd ] = streamd
|
769
|
+
data = data[ 2..-1 ]
|
863
770
|
|
864
|
-
|
771
|
+
return if data.empty?
|
772
|
+
end
|
865
773
|
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
774
|
+
unless dst.closed? then
|
775
|
+
dst_info = @dst_infos[ dst ]
|
776
|
+
data = @custom.decode( data )
|
777
|
+
# puts "debug2 add dst.wbuff decoded #{ data.bytesize }"
|
778
|
+
dst_info[ :wbuff ] << data
|
779
|
+
dst_info[ :last_recv_at ] = Time.new
|
780
|
+
add_write( dst )
|
781
|
+
end
|
782
|
+
end
|
871
783
|
|
872
|
-
|
873
|
-
|
874
|
-
|
784
|
+
##
|
785
|
+
# write proxyd
|
786
|
+
#
|
787
|
+
def write_proxyd( proxyd )
|
788
|
+
# 发ctlmsg
|
789
|
+
while @proxyd_info[ :ctlmsgs ].any? do
|
790
|
+
data, to_addr = @proxyd_info[ :ctlmsgs ].first
|
791
|
+
sent = send_data( proxyd, data, to_addr )
|
875
792
|
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
793
|
+
if sent == :wait then
|
794
|
+
puts "p#{ Process.pid } #{ Time.new } wait proxyd send ctlmsg, left #{ @proxyd_info[ :ctlmsgs ].size }"
|
795
|
+
return
|
796
|
+
else
|
797
|
+
@proxyd_info[ :ctlmsgs ].shift
|
798
|
+
end
|
799
|
+
end
|
882
800
|
|
883
|
-
|
884
|
-
|
801
|
+
@writes.delete( proxyd )
|
802
|
+
end
|
885
803
|
|
886
|
-
|
887
|
-
|
888
|
-
|
804
|
+
##
|
805
|
+
# write tund
|
806
|
+
#
|
807
|
+
def write_tund( tund )
|
808
|
+
tund_info = @tund_infos[ tund ]
|
889
809
|
|
890
|
-
|
810
|
+
# 处理关闭
|
811
|
+
if tund_info[ :closing ] then
|
812
|
+
if tund_info[ :changed_tun_addr ] then
|
813
|
+
data = [ 0, IP_CHANGED ].pack( 'Q>C' )
|
814
|
+
send_data( tund, data, tund_info[ :changed_tun_addr ] )
|
815
|
+
end
|
891
816
|
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
end
|
896
|
-
end
|
897
|
-
when MISS
|
898
|
-
return if tund_info[ :resendings ].size >= RESENDING_LIMIT
|
817
|
+
close_tund( tund )
|
818
|
+
return
|
819
|
+
end
|
899
820
|
|
900
|
-
|
821
|
+
now = Time.new
|
901
822
|
|
902
|
-
|
903
|
-
|
823
|
+
# 发ctlmsg
|
824
|
+
while tund_info[ :ctlmsgs ].any? do
|
825
|
+
data = tund_info[ :ctlmsgs ].first
|
826
|
+
sent = send_data( tund, data, tund_info[ :tun_addr ] )
|
904
827
|
|
905
|
-
|
906
|
-
|
828
|
+
if sent == :fatal then
|
829
|
+
close_tund( tund )
|
830
|
+
return
|
831
|
+
elsif sent == :wait then
|
832
|
+
puts "p#{ Process.pid } #{ Time.new } wait tund #{ tund_info[ :port ] } send ctlmsg, left #{ tund_info[ :ctlmsgs ].size }"
|
833
|
+
tund_info[ :last_sent_at ] = now
|
834
|
+
return
|
835
|
+
end
|
907
836
|
|
908
|
-
|
909
|
-
|
910
|
-
tund_info[ :resendings ] << [ dst_local_port, pack_id ]
|
911
|
-
end
|
912
|
-
end
|
837
|
+
tund_info[ :ctlmsgs ].shift
|
838
|
+
end
|
913
839
|
|
914
|
-
|
915
|
-
|
916
|
-
|
840
|
+
tund_info[ :last_sent_at ] = now
|
841
|
+
@writes.delete( tund )
|
842
|
+
end
|
917
843
|
|
918
|
-
|
919
|
-
|
844
|
+
##
|
845
|
+
# write dst
|
846
|
+
#
|
847
|
+
def write_dst( dst )
|
848
|
+
return if dst.closed?
|
849
|
+
dst_info = @dst_infos[ dst ]
|
850
|
+
streamd = dst_info[ :streamd ]
|
920
851
|
|
921
|
-
|
922
|
-
|
852
|
+
# 处理关闭
|
853
|
+
if dst_info[ :closing ] then
|
854
|
+
close_dst( dst )
|
923
855
|
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
856
|
+
if streamd then
|
857
|
+
close_read_streamd( streamd )
|
858
|
+
set_streamd_closing_write( streamd )
|
859
|
+
end
|
928
860
|
|
929
|
-
|
930
|
-
|
931
|
-
set_is_closing( dst_ext[ :dst ] )
|
932
|
-
end
|
933
|
-
when FIN2
|
934
|
-
src_id = data[ 9, 8 ].unpack( 'Q>' ).first
|
861
|
+
return
|
862
|
+
end
|
935
863
|
|
936
|
-
|
937
|
-
return unless dst_local_port
|
864
|
+
data = dst_info[ :wbuff ]
|
938
865
|
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
866
|
+
# 写前为空,处理关闭写
|
867
|
+
if data.empty? then
|
868
|
+
if dst_info[ :closing_write ] then
|
869
|
+
close_write_dst( dst )
|
870
|
+
else
|
871
|
+
@writes.delete( dst )
|
944
872
|
end
|
945
873
|
|
946
874
|
return
|
947
875
|
end
|
948
876
|
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
877
|
+
# 写入
|
878
|
+
begin
|
879
|
+
written = dst.write_nonblock( data )
|
880
|
+
rescue IO::WaitWritable, Errno::EINTR
|
881
|
+
print 'w'
|
882
|
+
return
|
883
|
+
rescue Exception => e
|
884
|
+
# puts "debug1 write dst #{ e.class }"
|
885
|
+
close_write_dst( dst )
|
886
|
+
close_read_streamd( streamd ) if streamd
|
887
|
+
return
|
888
|
+
end
|
953
889
|
|
954
|
-
|
955
|
-
|
956
|
-
|
890
|
+
# puts "debug2 written dst #{ written }"
|
891
|
+
data = data[ written..-1 ]
|
892
|
+
dst_info[ :wbuff ] = data
|
893
|
+
end
|
957
894
|
|
958
|
-
|
959
|
-
|
895
|
+
##
|
896
|
+
# write streamd
|
897
|
+
#
|
898
|
+
def write_streamd( streamd )
|
899
|
+
return if streamd.closed?
|
900
|
+
streamd_info = @streamd_infos[ streamd ]
|
901
|
+
dst = streamd_info[ :dst ]
|
902
|
+
|
903
|
+
# 处理关闭
|
904
|
+
if streamd_info[ :closing ] then
|
905
|
+
close_streamd( streamd )
|
906
|
+
|
907
|
+
if dst then
|
908
|
+
close_read_dst( dst )
|
909
|
+
set_dst_closing_write( dst )
|
910
|
+
end
|
960
911
|
|
961
|
-
|
962
|
-
# puts "debug2 #{ data.inspect }"
|
963
|
-
data = @custom.decode( data )
|
964
|
-
# puts "debug1 decoded pack #{ pack_id }"
|
912
|
+
return
|
965
913
|
end
|
966
914
|
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
915
|
+
data = streamd_info[ :wbuff ]
|
916
|
+
|
917
|
+
# 写前为空,处理关闭写
|
918
|
+
if data.empty? then
|
919
|
+
if streamd_info[ :closing_write ] then
|
920
|
+
close_write_streamd( streamd )
|
921
|
+
else
|
922
|
+
@writes.delete( streamd )
|
972
923
|
end
|
973
924
|
|
974
|
-
|
975
|
-
|
976
|
-
add_dst_wbuff( dst_ext[ :dst ], data )
|
977
|
-
# puts "debug2 update continue src pack #{ pack_id }"
|
925
|
+
return
|
926
|
+
end
|
978
927
|
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
928
|
+
# 写入
|
929
|
+
begin
|
930
|
+
written = streamd.write_nonblock( data )
|
931
|
+
rescue IO::WaitWritable, Errno::EINTR
|
932
|
+
print 'w'
|
933
|
+
return
|
934
|
+
rescue Exception => e
|
935
|
+
# puts "debug1 write streamd #{ e.class }"
|
936
|
+
close_write_streamd( streamd )
|
937
|
+
close_read_dst( dst ) if dst
|
938
|
+
return
|
939
|
+
end
|
940
|
+
|
941
|
+
# puts "debug2 written streamd #{ written }"
|
942
|
+
data = data[ written..-1 ]
|
943
|
+
streamd_info[ :wbuff ] = data
|
944
|
+
|
945
|
+
if dst && !dst.closed? then
|
946
|
+
dst_info = @dst_infos[ dst ]
|
947
|
+
dst_info[ :last_sent_at ] = Time.new
|
987
948
|
end
|
988
949
|
end
|
989
950
|
|