girl 0.69.0 → 0.72.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/girl.gemspec +0 -5
- data/lib/girl/head.rb +13 -16
- data/lib/girl/proxy.rb +24 -18
- data/lib/girl/proxy_worker.rb +63 -85
- data/lib/girl/proxyd.rb +2 -14
- data/lib/girl/proxyd_worker.rb +35 -64
- data/lib/girl/version.rb +1 -1
- metadata +2 -7
- data/lib/girl/hex.rb +0 -24
- data/lib/girl/resolv.rb +0 -200
- data/lib/girl/resolvd.rb +0 -169
- data/lib/girl/tun.rb +0 -997
- data/lib/girl/tund.rb +0 -897
data/lib/girl/resolvd.rb
DELETED
@@ -1,169 +0,0 @@
|
|
1
|
-
require 'girl/hex'
|
2
|
-
require 'girl/version'
|
3
|
-
require 'socket'
|
4
|
-
|
5
|
-
##
|
6
|
-
# Girl::Resolvd - dns查询得到正确的ip,远端。
|
7
|
-
#
|
8
|
-
module Girl
|
9
|
-
class Resolvd
|
10
|
-
|
11
|
-
def initialize( port = 7070, nameservers = [] )
|
12
|
-
@hex = Girl::Hex.new
|
13
|
-
@mutex = Mutex.new
|
14
|
-
@reads = []
|
15
|
-
@writes = []
|
16
|
-
@roles = {} # sock => :ctlr / :resolvd / :pub
|
17
|
-
@infos = {} # resolvd => {}
|
18
|
-
@socks = {} # sock => sock_id
|
19
|
-
@sock_ids = {} # sock_id => sock
|
20
|
-
|
21
|
-
resolvd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
22
|
-
resolvd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
23
|
-
resolvd.bind( Socket.sockaddr_in( port, '0.0.0.0' ) )
|
24
|
-
puts "resolvd bound on #{ port } #{ Time.new }"
|
25
|
-
|
26
|
-
nameservers = nameservers.select{ | ns | Addrinfo.udp( ns, 53 ).ipv4? }
|
27
|
-
|
28
|
-
resolvd_info = {
|
29
|
-
resolv_addrs: {}, # resolv_addr => pub
|
30
|
-
pubs: {}, # pub => src_addr
|
31
|
-
last_recv_ats: {}, # pub => now
|
32
|
-
pubd_addrs: nameservers.map{ | ns | Socket.sockaddr_in( 53, ns ) }
|
33
|
-
}
|
34
|
-
|
35
|
-
@resolvd = resolvd
|
36
|
-
@resolvd_info = resolvd_info
|
37
|
-
@roles[ resolvd ] = :resolvd
|
38
|
-
@infos[ resolvd ] = resolvd_info
|
39
|
-
@reads << resolvd
|
40
|
-
|
41
|
-
ctlr, ctlw = IO.pipe
|
42
|
-
@ctlw = ctlw
|
43
|
-
@roles[ ctlr ] = :ctlr
|
44
|
-
@reads << ctlr
|
45
|
-
end
|
46
|
-
|
47
|
-
def looping
|
48
|
-
loop_expire
|
49
|
-
|
50
|
-
loop do
|
51
|
-
rs, ws = IO.select( @reads, @writes )
|
52
|
-
|
53
|
-
@mutex.synchronize do
|
54
|
-
rs.each do | sock |
|
55
|
-
case @roles[ sock ]
|
56
|
-
when :ctlr
|
57
|
-
read_ctlr( sock )
|
58
|
-
when :resolvd
|
59
|
-
read_resolvd( sock )
|
60
|
-
when :pub
|
61
|
-
read_pub( sock )
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
ws.each do | sock |
|
66
|
-
close_sock( sock )
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def quit!
|
73
|
-
exit
|
74
|
-
end
|
75
|
-
|
76
|
-
private
|
77
|
-
|
78
|
-
def read_ctlr( ctlr )
|
79
|
-
sock_id = ctlr.read( 8 ).unpack( 'Q>' ).first
|
80
|
-
sock = @sock_ids[ sock_id ]
|
81
|
-
|
82
|
-
if sock
|
83
|
-
# puts "debug expire pub #{ sock_id } #{ Time.new }"
|
84
|
-
|
85
|
-
unless @writes.include?( sock )
|
86
|
-
@writes << sock
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def read_resolvd( resolvd )
|
92
|
-
data, addrinfo, rflags, *controls = resolvd.recvmsg
|
93
|
-
return if data.size <= 12
|
94
|
-
|
95
|
-
data = @hex.decode( data )
|
96
|
-
info = @infos[ resolvd ]
|
97
|
-
resolv_addr = addrinfo.to_sockaddr
|
98
|
-
pub = info[ :resolv_addrs ][ resolv_addr ]
|
99
|
-
|
100
|
-
unless pub
|
101
|
-
pub = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
102
|
-
pub.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
103
|
-
pub.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
104
|
-
# puts "debug a new pub bound on #{ pub.local_address.ip_unpack.last } #{ Time.new }"
|
105
|
-
|
106
|
-
@roles[ pub ] = :pub
|
107
|
-
pub_id = @hex.gen_random_num
|
108
|
-
@socks[ pub ] = pub_id
|
109
|
-
@sock_ids[ pub_id ] = pub
|
110
|
-
@reads << pub
|
111
|
-
|
112
|
-
info[ :resolv_addrs ][ resolv_addr ] = pub
|
113
|
-
info[ :pubs ][ pub ] = resolv_addr
|
114
|
-
info[ :last_recv_ats ][ pub ] = Time.new
|
115
|
-
end
|
116
|
-
|
117
|
-
info[ :pubd_addrs ].each do | pubd_addr |
|
118
|
-
pub.sendmsg( data, 0, pubd_addr )
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def read_pub( pub )
|
123
|
-
data, addrinfo, rflags, *controls = pub.recvmsg
|
124
|
-
return if data.size <= 12
|
125
|
-
|
126
|
-
resolv_addr = @resolvd_info[ :pubs ][ pub ]
|
127
|
-
return unless resolv_addr
|
128
|
-
|
129
|
-
# puts "debug pub recvmsg #{ data.inspect }"
|
130
|
-
@resolvd_info[ :last_recv_ats ][ pub ] = Time.new
|
131
|
-
data = @hex.encode( data )
|
132
|
-
# puts "debug resolvd sendmsg #{ data.inspect }"
|
133
|
-
@resolvd.sendmsg( data, 0, resolv_addr )
|
134
|
-
end
|
135
|
-
|
136
|
-
def close_sock( sock )
|
137
|
-
sock.close
|
138
|
-
@reads.delete( sock )
|
139
|
-
@writes.delete( sock )
|
140
|
-
@roles.delete( sock )
|
141
|
-
sock_id = @socks.delete( sock )
|
142
|
-
@sock_ids.delete( sock_id )
|
143
|
-
@resolvd_info[ :last_recv_ats ].delete( sock )
|
144
|
-
resolv_addr = @resolvd_info[ :pubs ].delete( sock )
|
145
|
-
@resolvd_info[ :resolv_addrs ].delete( resolv_addr )
|
146
|
-
end
|
147
|
-
|
148
|
-
def loop_expire
|
149
|
-
Thread.new do
|
150
|
-
loop do
|
151
|
-
sleep 60
|
152
|
-
|
153
|
-
@mutex.synchronize do
|
154
|
-
now = Time.new
|
155
|
-
pubs = @resolvd_info[ :pubs ].keys
|
156
|
-
|
157
|
-
pubs.each do | pub |
|
158
|
-
if now - @resolvd_info[ :last_recv_ats ][ pub ] > 5
|
159
|
-
pub_id = @socks[ pub ]
|
160
|
-
@ctlw.write( [ pub_id ].pack( 'Q>' ) )
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
end
|
169
|
-
end
|
data/lib/girl/tun.rb
DELETED
@@ -1,997 +0,0 @@
|
|
1
|
-
require 'girl/head'
|
2
|
-
require 'girl/hex'
|
3
|
-
require 'girl/version'
|
4
|
-
require 'socket'
|
5
|
-
|
6
|
-
##
|
7
|
-
# Girl::Tun - tcp透明转发,近端。
|
8
|
-
#
|
9
|
-
# usage
|
10
|
-
# =====
|
11
|
-
#
|
12
|
-
# Girl::Tund.new( 9090 ).looping # 远端
|
13
|
-
#
|
14
|
-
# Girl::Tun.new( 'your.server.ip', 9090, 1919 ).looping # 近端
|
15
|
-
#
|
16
|
-
# dig +short www.google.com @127.0.0.1 -p1717 # dig with girl/resolv, got 216.58.217.196
|
17
|
-
#
|
18
|
-
# iptables -t nat -A OUTPUT -p tcp -d 216.58.217.196 -j REDIRECT --to-ports 1919
|
19
|
-
#
|
20
|
-
# curl https://www.google.com/
|
21
|
-
#
|
22
|
-
# 包结构
|
23
|
-
# ======
|
24
|
-
#
|
25
|
-
# 流量打包成udp,在tun-tund之间传输,包结构:
|
26
|
-
#
|
27
|
-
# Q>: 1+ source/dest_id -> Q>: pack_id -> traffic
|
28
|
-
# 0 ctlmsg -> C: 1 tund port -> n: tund port
|
29
|
-
# 2 heartbeat -> C: random char
|
30
|
-
# 3 a new source -> Q>nnN: source_id dst_family dst_port dst_host
|
31
|
-
# 4 paired -> Q>Q>: source_id dest_id
|
32
|
-
# 5 dest status -> Q>Q>Q>: dest_id biggest_dest_pack_id continue_source_pack_id
|
33
|
-
# 6 source status -> Q>Q>Q>: source_id biggest_source_pack_id continue_dest_pack_id
|
34
|
-
# 7 miss -> Q>Q>Q>: source/dest_id pack_id_begin pack_id_end
|
35
|
-
# 8 fin1 -> Q>: source/dest_id
|
36
|
-
# 9 got fin1 -> Q>: source/dest_id
|
37
|
-
# 10 fin2 -> Q>: source/dest_id
|
38
|
-
# 11 got fin2 -> Q>: source/dest_id
|
39
|
-
# 12 tund fin
|
40
|
-
# 13 tun fin
|
41
|
-
#
|
42
|
-
module Girl
|
43
|
-
class Tun
|
44
|
-
##
|
45
|
-
# tund_ip 远端ip
|
46
|
-
# roomd_port roomd端口,roomd用于配对tun-tund
|
47
|
-
# redir_port 本地端口,请配置iptables把流量引向这个端口
|
48
|
-
# source_chunk_dir 文件缓存目录,缓存source写前
|
49
|
-
# tun_chunk_dir 文件缓存目录,缓存tun写前
|
50
|
-
# hex_block 外部传入自定义加解密
|
51
|
-
def initialize( tund_ip, roomd_port = 9090, redir_port = 1919, source_chunk_dir = '/tmp', tun_chunk_dir = '/tmp', hex_block = nil )
|
52
|
-
if hex_block
|
53
|
-
Girl::Hex.class_eval( hex_block )
|
54
|
-
end
|
55
|
-
|
56
|
-
@tund_ip = tund_ip
|
57
|
-
@roomd_addr = Socket.sockaddr_in( roomd_port, tund_ip )
|
58
|
-
@redir_port = redir_port
|
59
|
-
@source_chunk_dir = source_chunk_dir
|
60
|
-
@tun_chunk_dir = tun_chunk_dir
|
61
|
-
@hex = Girl::Hex.new
|
62
|
-
@mutex = Mutex.new
|
63
|
-
@reads = []
|
64
|
-
@writes = []
|
65
|
-
@closings = []
|
66
|
-
@roles = {} # sock => :ctlr / :redir / :source / :tun
|
67
|
-
@infos = {} # sock => {}
|
68
|
-
@socks = {} # sock => sock_id
|
69
|
-
@sock_ids = {} # sock_id => sock
|
70
|
-
|
71
|
-
ctlr, ctlw = IO.pipe
|
72
|
-
@ctlw = ctlw
|
73
|
-
@roles[ ctlr ] = :ctlr
|
74
|
-
@reads << ctlr
|
75
|
-
end
|
76
|
-
|
77
|
-
def looping
|
78
|
-
puts 'looping'
|
79
|
-
|
80
|
-
new_redir
|
81
|
-
new_tun
|
82
|
-
|
83
|
-
loop do
|
84
|
-
rs, ws = IO.select( @reads, @writes )
|
85
|
-
|
86
|
-
@mutex.synchronize do
|
87
|
-
ws.each do | sock |
|
88
|
-
case @roles[ sock ]
|
89
|
-
when :source
|
90
|
-
write_source( sock )
|
91
|
-
when :tun
|
92
|
-
write_tun( sock )
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
rs.each do | sock |
|
97
|
-
case @roles[ sock ]
|
98
|
-
when :ctlr
|
99
|
-
read_ctlr( sock )
|
100
|
-
when :redir
|
101
|
-
read_redir( sock )
|
102
|
-
when :source
|
103
|
-
read_source( sock )
|
104
|
-
when :tun
|
105
|
-
read_tun( sock )
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
rescue Interrupt => e
|
111
|
-
puts e.class
|
112
|
-
quit!
|
113
|
-
end
|
114
|
-
|
115
|
-
def quit!
|
116
|
-
if @tun && !@tun.closed? && @tun_info[ :tund_addr ]
|
117
|
-
ctlmsg = [ 0, TUN_FIN ].pack( 'Q>C' )
|
118
|
-
send_pack( @tun, ctlmsg, @tun_info[ :tund_addr ] )
|
119
|
-
end
|
120
|
-
|
121
|
-
exit
|
122
|
-
end
|
123
|
-
|
124
|
-
private
|
125
|
-
|
126
|
-
##
|
127
|
-
# read ctlr
|
128
|
-
#
|
129
|
-
def read_ctlr( ctlr )
|
130
|
-
case ctlr.read( 1 ).unpack( 'C' ).first
|
131
|
-
when CTL_CLOSE
|
132
|
-
sock_id = ctlr.read( 8 ).unpack( 'Q>' ).first
|
133
|
-
sock = @sock_ids[ sock_id ]
|
134
|
-
|
135
|
-
if sock
|
136
|
-
add_closing( sock )
|
137
|
-
end
|
138
|
-
when CTL_RESUME
|
139
|
-
sock_id = ctlr.read( 8 ).unpack( 'Q>' ).first
|
140
|
-
sock = @sock_ids[ sock_id ]
|
141
|
-
|
142
|
-
if sock
|
143
|
-
add_write( sock )
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
##
|
149
|
-
# read redir
|
150
|
-
#
|
151
|
-
def read_redir( redir )
|
152
|
-
begin
|
153
|
-
source, addrinfo = redir.accept_nonblock
|
154
|
-
rescue IO::WaitReadable, Errno::EINTR => e
|
155
|
-
puts "accept source #{ e.class } #{ Time.new } p#{ Process.pid }"
|
156
|
-
return
|
157
|
-
end
|
158
|
-
|
159
|
-
begin
|
160
|
-
# /usr/include/linux/netfilter_ipv4.h
|
161
|
-
option = source.getsockopt( Socket::SOL_IP, 80 )
|
162
|
-
rescue Exception => e
|
163
|
-
puts "get SO_ORIGINAL_DST #{ e.class } #{ Time.new } p#{ Process.pid }"
|
164
|
-
source.close
|
165
|
-
return
|
166
|
-
end
|
167
|
-
|
168
|
-
source_id = @hex.gen_random_num
|
169
|
-
@roles[ source ] = :source
|
170
|
-
@infos[ source ] = {
|
171
|
-
id: source_id,
|
172
|
-
tun: @tun
|
173
|
-
}
|
174
|
-
@socks[ source ] = source_id
|
175
|
-
@sock_ids[ source_id ] = source
|
176
|
-
|
177
|
-
@tun_info[ :waitings ][ source_id ] = []
|
178
|
-
@tun_info[ :source_exts ][ source_id ] = {
|
179
|
-
source: source,
|
180
|
-
created_at: Time.new,
|
181
|
-
last_recv_at: nil, # 上一次收到流量的时间
|
182
|
-
wbuff: '', # 写前缓存
|
183
|
-
cache: '', # 块读出缓存
|
184
|
-
chunks: [], # 块队列,写前达到块大小时结一个块 filename
|
185
|
-
spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
|
186
|
-
wmems: {}, # 写后缓存 pack_id => data
|
187
|
-
send_ats: {}, # 上一次发出时间 pack_id => send_at
|
188
|
-
biggest_pack_id: 0, # 发到几
|
189
|
-
continue_dest_pack_id: 0, # 收到几
|
190
|
-
pieces: {}, # 跳号包 dest_pack_id => data
|
191
|
-
is_dest_closed: false, # 对面是否已关闭
|
192
|
-
biggest_dest_pack_id: 0, # 对面发到几
|
193
|
-
completed_pack_id: 0, # 完成到几(对面收到几)
|
194
|
-
last_traffic_at: nil # 收到有效流量,或者发出流量的时间戳
|
195
|
-
}
|
196
|
-
|
197
|
-
add_read( source )
|
198
|
-
loop_send_a_new_source( source, option.data )
|
199
|
-
end
|
200
|
-
|
201
|
-
##
|
202
|
-
# read source
|
203
|
-
#
|
204
|
-
def read_source( source )
|
205
|
-
begin
|
206
|
-
data = source.read_nonblock( PACK_SIZE )
|
207
|
-
rescue IO::WaitReadable, Errno::EINTR => e
|
208
|
-
return
|
209
|
-
rescue Exception => e
|
210
|
-
add_closing( source )
|
211
|
-
return
|
212
|
-
end
|
213
|
-
|
214
|
-
# puts "debug read source #{ data.inspect } #{ Time.new } p#{ Process.pid }"
|
215
|
-
info = @infos[ source ]
|
216
|
-
tun = info[ :tun ]
|
217
|
-
|
218
|
-
if tun.closed?
|
219
|
-
add_closing( source )
|
220
|
-
return
|
221
|
-
end
|
222
|
-
|
223
|
-
source_id = @socks[ source ]
|
224
|
-
tun_info = @infos[ tun ]
|
225
|
-
dest_id = tun_info[ :source_ids ][ source_id ]
|
226
|
-
|
227
|
-
if tun_info[ :tund_addr ].nil? || dest_id.nil?
|
228
|
-
tun_info[ :waitings ][ source_id ] << data
|
229
|
-
return
|
230
|
-
end
|
231
|
-
|
232
|
-
tun_info[ :wbuffs ] << [ source_id, data ]
|
233
|
-
|
234
|
-
if tun_info[ :wbuffs ].size >= WBUFFS_LIMIT
|
235
|
-
tun_id = @socks[ tun ]
|
236
|
-
spring = tun_info[ :chunks ].size > 0 ? ( tun_info[ :spring ] + 1 ) : 0
|
237
|
-
filename = "#{ Process.pid }-#{ tun_id }.#{ spring }"
|
238
|
-
chunk_path = File.join( @tun_chunk_dir, filename )
|
239
|
-
IO.binwrite( chunk_path, tun_info[ :wbuffs ].map{ | source_id, data | "#{ [ source_id, data.bytesize ].pack( 'Q>n' ) }#{ data }" }.join )
|
240
|
-
tun_info[ :chunks ] << filename
|
241
|
-
tun_info[ :spring ] = spring
|
242
|
-
tun_info[ :wbuffs ].clear
|
243
|
-
end
|
244
|
-
|
245
|
-
unless tun_info[ :paused ]
|
246
|
-
add_write( tun )
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
##
|
251
|
-
# read tun
|
252
|
-
#
|
253
|
-
def read_tun( tun )
|
254
|
-
data, addrinfo, rflags, *controls = tun.recvmsg
|
255
|
-
sockaddr = addrinfo.to_sockaddr
|
256
|
-
now = Time.new
|
257
|
-
info = @infos[ tun ]
|
258
|
-
dest_id = data[ 0, 8 ].unpack( 'Q>' ).first
|
259
|
-
|
260
|
-
if dest_id == 0
|
261
|
-
case data[ 8 ].unpack( 'C' ).first
|
262
|
-
when TUND_PORT
|
263
|
-
return if sockaddr != @roomd_addr
|
264
|
-
|
265
|
-
unless info[ :tund_addr ]
|
266
|
-
tund_port = data[ 9, 2 ].unpack( 'n' ).first
|
267
|
-
# puts "debug got TUND_PORT #{ tund_port } #{ Time.new } p#{ Process.pid }"
|
268
|
-
info[ :tund_addr ] = Socket.sockaddr_in( tund_port, @tund_ip )
|
269
|
-
info[ :last_traffic_at ] = now
|
270
|
-
loop_send_heartbeat( tun )
|
271
|
-
loop_check_expire( tun )
|
272
|
-
loop_send_status( tun )
|
273
|
-
end
|
274
|
-
when PAIRED
|
275
|
-
return if sockaddr != info[ :tund_addr ]
|
276
|
-
|
277
|
-
source_id, dest_id = data[ 9, 16 ].unpack( 'Q>Q>' )
|
278
|
-
return unless info[ :source_exts ].include?( source_id )
|
279
|
-
|
280
|
-
return if info[ :source_ids ].include?( source_id )
|
281
|
-
|
282
|
-
# puts "debug got PAIRED #{ source_id } #{ dest_id } #{ Time.new } p#{ Process.pid }"
|
283
|
-
info[ :source_ids ][ source_id ] = dest_id
|
284
|
-
info[ :dest_ids ][ dest_id ] = source_id
|
285
|
-
buffs = info[ :waitings ][ source_id ]
|
286
|
-
|
287
|
-
if buffs.any?
|
288
|
-
# puts "debug move #{ buffs.size } waiting buffs to wbuffs #{ Time.new } p#{ Process.pid }"
|
289
|
-
|
290
|
-
buffs.each do | buff |
|
291
|
-
info[ :wbuffs ] << [ source_id, buff ]
|
292
|
-
end
|
293
|
-
|
294
|
-
buffs.clear
|
295
|
-
add_write( tun )
|
296
|
-
end
|
297
|
-
when DEST_STATUS
|
298
|
-
return if sockaddr != info[ :tund_addr ]
|
299
|
-
|
300
|
-
dest_id, biggest_dest_pack_id, continue_source_pack_id = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
|
301
|
-
source_id = info[ :dest_ids ][ dest_id ]
|
302
|
-
return unless source_id
|
303
|
-
|
304
|
-
ext = info[ :source_exts ][ source_id ]
|
305
|
-
return unless ext
|
306
|
-
|
307
|
-
# 更新对面发到几
|
308
|
-
if biggest_dest_pack_id > ext[ :biggest_dest_pack_id ]
|
309
|
-
ext[ :biggest_dest_pack_id ] = biggest_dest_pack_id
|
310
|
-
end
|
311
|
-
|
312
|
-
# 更新对面收到几,释放写后
|
313
|
-
if continue_source_pack_id > ext[ :completed_pack_id ]
|
314
|
-
pack_ids = ext[ :wmems ].keys.select { | pack_id | pack_id <= continue_source_pack_id }
|
315
|
-
|
316
|
-
pack_ids.each do | pack_id |
|
317
|
-
ext[ :wmems ].delete( pack_id )
|
318
|
-
ext[ :send_ats ].delete( pack_id )
|
319
|
-
end
|
320
|
-
|
321
|
-
# puts "debug completed #{ continue_source_pack_id }"
|
322
|
-
ext[ :completed_pack_id ] = continue_source_pack_id
|
323
|
-
end
|
324
|
-
|
325
|
-
if ext[ :is_dest_closed ] && ( ext[ :biggest_dest_pack_id ] == ext[ :continue_dest_pack_id ] )
|
326
|
-
add_write( ext[ :source ] )
|
327
|
-
return
|
328
|
-
end
|
329
|
-
|
330
|
-
# 发miss
|
331
|
-
if !ext[ :source ].closed? && ( ext[ :continue_dest_pack_id ] < ext[ :biggest_dest_pack_id ] )
|
332
|
-
ranges = []
|
333
|
-
curr_pack_id = ext[ :continue_dest_pack_id ] + 1
|
334
|
-
|
335
|
-
ext[ :pieces ].keys.sort.each do | pack_id |
|
336
|
-
if pack_id > curr_pack_id
|
337
|
-
ranges << [ curr_pack_id, pack_id - 1 ]
|
338
|
-
end
|
339
|
-
|
340
|
-
curr_pack_id = pack_id + 1
|
341
|
-
end
|
342
|
-
|
343
|
-
if curr_pack_id <= ext[ :biggest_dest_pack_id ]
|
344
|
-
ranges << [ curr_pack_id, ext[ :biggest_dest_pack_id ] ]
|
345
|
-
end
|
346
|
-
|
347
|
-
pack_count = 0
|
348
|
-
# puts "debug #{ ext[ :continue_dest_pack_id ] }/#{ ext[ :biggest_dest_pack_id ] } send MISS #{ ranges.size }"
|
349
|
-
ranges.each do | pack_id_begin, pack_id_end |
|
350
|
-
if pack_count >= BREAK_SEND_MISS
|
351
|
-
puts "break send miss at #{ pack_id_begin } #{ Time.new } p#{ Process.pid }"
|
352
|
-
break
|
353
|
-
end
|
354
|
-
|
355
|
-
ctlmsg = [
|
356
|
-
0,
|
357
|
-
MISS,
|
358
|
-
dest_id,
|
359
|
-
pack_id_begin,
|
360
|
-
pack_id_end
|
361
|
-
].pack( 'Q>CQ>Q>Q>' )
|
362
|
-
|
363
|
-
send_pack( tun, ctlmsg, info[ :tund_addr ] )
|
364
|
-
pack_count += ( pack_id_end - pack_id_begin + 1 )
|
365
|
-
end
|
366
|
-
end
|
367
|
-
when MISS
|
368
|
-
return if sockaddr != info[ :tund_addr ]
|
369
|
-
|
370
|
-
source_id, pack_id_begin, pack_id_end = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
|
371
|
-
ext = info[ :source_exts ][ source_id ]
|
372
|
-
return unless ext
|
373
|
-
|
374
|
-
( pack_id_begin..pack_id_end ).each do | pack_id |
|
375
|
-
send_at = ext[ :send_ats ][ pack_id ]
|
376
|
-
|
377
|
-
if send_at
|
378
|
-
break if now - send_at < STATUS_INTERVAL
|
379
|
-
|
380
|
-
info[ :resendings ] << [ source_id, pack_id ]
|
381
|
-
end
|
382
|
-
end
|
383
|
-
|
384
|
-
add_write( tun )
|
385
|
-
when FIN1
|
386
|
-
return if sockaddr != info[ :tund_addr ]
|
387
|
-
|
388
|
-
# puts "debug 2-1. recv fin1 -> send got_fin1 -> ext.is_dest_closed = true #{ Time.new } p#{ Process.pid }"
|
389
|
-
dest_id = data[ 9, 8 ].unpack( 'Q>' ).first
|
390
|
-
ctlmsg = [
|
391
|
-
0,
|
392
|
-
GOT_FIN1,
|
393
|
-
dest_id
|
394
|
-
].pack( 'Q>CQ>' )
|
395
|
-
|
396
|
-
send_pack( tun, ctlmsg, info[ :tund_addr ] )
|
397
|
-
|
398
|
-
source_id = info[ :dest_ids ][ dest_id ]
|
399
|
-
return unless source_id
|
400
|
-
|
401
|
-
ext = info[ :source_exts ][ source_id ]
|
402
|
-
return unless ext
|
403
|
-
|
404
|
-
ext[ :is_dest_closed ] = true
|
405
|
-
when GOT_FIN1
|
406
|
-
return if sockaddr != info[ :tund_addr ]
|
407
|
-
|
408
|
-
# puts "debug 1-2. recv got_fin1 -> break loop #{ Time.new } p#{ Process.pid }"
|
409
|
-
source_id = data[ 9, 8 ].unpack( 'Q>' ).first
|
410
|
-
info[ :fin1s ].delete( source_id )
|
411
|
-
when FIN2
|
412
|
-
return if sockaddr != info[ :tund_addr ]
|
413
|
-
|
414
|
-
# puts "debug 1-3. recv fin2 -> send got_fin2 -> del ext #{ Time.new } p#{ Process.pid }"
|
415
|
-
dest_id = data[ 9, 8 ].unpack( 'Q>' ).first
|
416
|
-
ctlmsg = [
|
417
|
-
0,
|
418
|
-
GOT_FIN2,
|
419
|
-
dest_id
|
420
|
-
].pack( 'Q>CQ>' )
|
421
|
-
|
422
|
-
send_pack( tun, ctlmsg, info[ :tund_addr ] )
|
423
|
-
|
424
|
-
source_id = info[ :dest_ids ][ dest_id ]
|
425
|
-
return unless source_id
|
426
|
-
|
427
|
-
del_source_ext( info, source_id )
|
428
|
-
when GOT_FIN2
|
429
|
-
return if sockaddr != info[ :tund_addr ]
|
430
|
-
|
431
|
-
# puts "debug 2-4. recv got_fin2 -> break loop #{ Time.new } p#{ Process.pid }"
|
432
|
-
source_id = data[ 9, 8 ].unpack( 'Q>' ).first
|
433
|
-
info[ :fin2s ].delete( source_id )
|
434
|
-
when TUND_FIN
|
435
|
-
return if sockaddr != info[ :tund_addr ]
|
436
|
-
|
437
|
-
puts "recv tund fin #{ Time.new } p#{ Process.pid }"
|
438
|
-
add_closing( tun )
|
439
|
-
end
|
440
|
-
|
441
|
-
return
|
442
|
-
end
|
443
|
-
|
444
|
-
return if sockaddr != info[ :tund_addr ]
|
445
|
-
|
446
|
-
source_id = info[ :dest_ids ][ dest_id ]
|
447
|
-
return unless source_id
|
448
|
-
|
449
|
-
ext = info[ :source_exts ][ source_id ]
|
450
|
-
return if ext.nil? || ext[ :source ].closed?
|
451
|
-
|
452
|
-
pack_id = data[ 8, 8 ].unpack( 'Q>' ).first
|
453
|
-
return if ( pack_id <= ext[ :continue_dest_pack_id ] ) || ext[ :pieces ].include?( pack_id )
|
454
|
-
|
455
|
-
data = data[ 16..-1 ]
|
456
|
-
|
457
|
-
# 解混淆
|
458
|
-
if pack_id == 1
|
459
|
-
data = @hex.decode( data )
|
460
|
-
end
|
461
|
-
|
462
|
-
# 放进source的写前缓存,跳号放碎片缓存
|
463
|
-
if pack_id - ext[ :continue_dest_pack_id ] == 1
|
464
|
-
while ext[ :pieces ].include?( pack_id + 1 )
|
465
|
-
data << ext[ :pieces ].delete( pack_id + 1 )
|
466
|
-
pack_id += 1
|
467
|
-
end
|
468
|
-
|
469
|
-
ext[ :continue_dest_pack_id ] = pack_id
|
470
|
-
ext[ :wbuff ] << data
|
471
|
-
|
472
|
-
if ext[ :wbuff ].bytesize >= CHUNK_SIZE
|
473
|
-
spring = ext[ :chunks ].size > 0 ? ( ext[ :spring ] + 1 ) : 0
|
474
|
-
filename = "#{ Process.pid }-#{ source_id }.#{ spring }"
|
475
|
-
chunk_path = File.join( @source_chunk_dir, filename )
|
476
|
-
IO.binwrite( chunk_path, ext[ :wbuff ] )
|
477
|
-
ext[ :chunks ] << filename
|
478
|
-
ext[ :spring ] = spring
|
479
|
-
ext[ :wbuff ].clear
|
480
|
-
end
|
481
|
-
|
482
|
-
ext[ :last_traffic_at ] = now
|
483
|
-
info[ :last_traffic_at ] = now
|
484
|
-
add_write( ext[ :source ] )
|
485
|
-
else
|
486
|
-
ext[ :pieces ][ pack_id ] = data
|
487
|
-
end
|
488
|
-
|
489
|
-
ext[ :last_recv_at ] = now
|
490
|
-
end
|
491
|
-
|
492
|
-
##
|
493
|
-
# write source
|
494
|
-
#
|
495
|
-
def write_source( source )
|
496
|
-
if @closings.include?( source )
|
497
|
-
close_source( source )
|
498
|
-
return
|
499
|
-
end
|
500
|
-
|
501
|
-
info = @infos[ source ]
|
502
|
-
tun = info[ :tun ]
|
503
|
-
|
504
|
-
if tun.closed?
|
505
|
-
add_closing( source )
|
506
|
-
return
|
507
|
-
end
|
508
|
-
|
509
|
-
tun_info = @infos[ tun ]
|
510
|
-
source_id = @socks[ source ]
|
511
|
-
ext = tun_info[ :source_exts ][ source_id ]
|
512
|
-
|
513
|
-
# 取写前
|
514
|
-
data = ext[ :cache ]
|
515
|
-
from = :cache
|
516
|
-
|
517
|
-
if data.empty?
|
518
|
-
if ext[ :chunks ].any?
|
519
|
-
path = File.join( @source_chunk_dir, ext[ :chunks ].shift )
|
520
|
-
|
521
|
-
begin
|
522
|
-
data = IO.binread( path )
|
523
|
-
File.delete( path )
|
524
|
-
rescue Errno::ENOENT
|
525
|
-
add_closing( source )
|
526
|
-
return
|
527
|
-
end
|
528
|
-
else
|
529
|
-
data = ext[ :wbuff ]
|
530
|
-
from = :wbuff
|
531
|
-
end
|
532
|
-
end
|
533
|
-
|
534
|
-
if data.empty?
|
535
|
-
if ext[ :is_dest_closed ] && ( ext[ :biggest_dest_pack_id ] == ext[ :continue_dest_pack_id ] )
|
536
|
-
# puts "debug 2-2. all sent && ext.biggest_dest_pack_id == ext.continue_dest_pack_id -> add closing source #{ Time.new } p#{ Process.pid }"
|
537
|
-
add_closing( source )
|
538
|
-
return
|
539
|
-
end
|
540
|
-
|
541
|
-
@writes.delete( source )
|
542
|
-
return
|
543
|
-
end
|
544
|
-
|
545
|
-
begin
|
546
|
-
written = source.write_nonblock( data )
|
547
|
-
rescue IO::WaitWritable, Errno::EINTR => e
|
548
|
-
ext[ from ] = data
|
549
|
-
return
|
550
|
-
rescue Exception => e
|
551
|
-
add_closing( source )
|
552
|
-
return
|
553
|
-
end
|
554
|
-
|
555
|
-
data = data[ written..-1 ]
|
556
|
-
ext[ from ] = data
|
557
|
-
end
|
558
|
-
|
559
|
-
##
|
560
|
-
# write tun
|
561
|
-
#
|
562
|
-
def write_tun( tun )
|
563
|
-
if @closings.include?( tun )
|
564
|
-
close_tun( tun )
|
565
|
-
new_tun
|
566
|
-
return
|
567
|
-
end
|
568
|
-
|
569
|
-
now = Time.new
|
570
|
-
info = @infos[ tun ]
|
571
|
-
|
572
|
-
# 重传
|
573
|
-
while info[ :resendings ].any?
|
574
|
-
source_id, pack_id = info[ :resendings ].shift
|
575
|
-
ext = info[ :source_exts ][ source_id ]
|
576
|
-
|
577
|
-
if ext
|
578
|
-
pack = ext[ :wmems ][ pack_id ]
|
579
|
-
|
580
|
-
if pack
|
581
|
-
send_pack( tun, pack, info[ :tund_addr ] )
|
582
|
-
ext[ :last_traffic_at ] = now
|
583
|
-
info[ :last_traffic_at ] = now
|
584
|
-
return
|
585
|
-
end
|
586
|
-
end
|
587
|
-
end
|
588
|
-
|
589
|
-
# 若写后达到上限,暂停取写前
|
590
|
-
if info[ :source_exts ].map{ | _, ext | ext[ :wmems ].size }.sum >= WMEMS_LIMIT
|
591
|
-
unless info[ :paused ]
|
592
|
-
puts "pause #{ @socks[ tun ] } #{ Time.new } p#{ Process.pid }"
|
593
|
-
info[ :paused ] = true
|
594
|
-
end
|
595
|
-
|
596
|
-
@writes.delete( tun )
|
597
|
-
return
|
598
|
-
end
|
599
|
-
|
600
|
-
# 取写前
|
601
|
-
if info[ :caches ].any?
|
602
|
-
source_id, data = info[ :caches ].shift
|
603
|
-
elsif info[ :chunks ].any?
|
604
|
-
path = File.join( @tun_chunk_dir, info[ :chunks ].shift )
|
605
|
-
|
606
|
-
begin
|
607
|
-
data = IO.binread( path )
|
608
|
-
File.delete( path )
|
609
|
-
rescue Errno::ENOENT
|
610
|
-
add_closing( tun )
|
611
|
-
return
|
612
|
-
end
|
613
|
-
|
614
|
-
caches = []
|
615
|
-
|
616
|
-
until data.empty?
|
617
|
-
source_id, pack_size = data[ 0, 10 ].unpack( 'Q>n' )
|
618
|
-
caches << [ source_id, data[ 10, pack_size ] ]
|
619
|
-
data = data[ ( 10 + pack_size )..-1 ]
|
620
|
-
end
|
621
|
-
|
622
|
-
source_id, data = caches.shift
|
623
|
-
info[ :caches ] = caches
|
624
|
-
elsif info[ :wbuffs ].any?
|
625
|
-
source_id, data = info[ :wbuffs ].shift
|
626
|
-
else
|
627
|
-
@writes.delete( tun )
|
628
|
-
return
|
629
|
-
end
|
630
|
-
|
631
|
-
ext = info[ :source_exts ][ source_id ]
|
632
|
-
|
633
|
-
if ext
|
634
|
-
pack_id = ext[ :biggest_pack_id ] + 1
|
635
|
-
|
636
|
-
if pack_id == 1
|
637
|
-
data = @hex.encode( data )
|
638
|
-
end
|
639
|
-
|
640
|
-
pack = "#{ [ source_id, pack_id ].pack( 'Q>Q>' ) }#{ data }"
|
641
|
-
send_pack( tun, pack, info[ :tund_addr ] )
|
642
|
-
ext[ :biggest_pack_id ] = pack_id
|
643
|
-
ext[ :wmems ][ pack_id ] = pack
|
644
|
-
ext[ :send_ats ][ pack_id ] = now
|
645
|
-
ext[ :last_traffic_at ] = now
|
646
|
-
info[ :last_traffic_at ] = now
|
647
|
-
end
|
648
|
-
end
|
649
|
-
|
650
|
-
def new_redir
|
651
|
-
redir = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
|
652
|
-
redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
|
653
|
-
redir.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
|
654
|
-
redir.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
|
655
|
-
redir.bind( Socket.sockaddr_in( @redir_port, '0.0.0.0' ) )
|
656
|
-
redir.listen( 511 )
|
657
|
-
|
658
|
-
@roles[ redir ] = :redir
|
659
|
-
@reads << redir
|
660
|
-
end
|
661
|
-
|
662
|
-
def new_tun
|
663
|
-
tun = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
664
|
-
tun.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
|
665
|
-
tun_id = @hex.gen_random_num
|
666
|
-
tun_info = {
|
667
|
-
id: tun_id,
|
668
|
-
waitings: {}, # 还没连上tund,或者还没配上dest,暂存流量 source_id => buffs[]
|
669
|
-
wbuffs: [], # 写前缓存 [ source_id, data ]
|
670
|
-
caches: [], # 块读出缓存 [ source_id, data ]
|
671
|
-
chunks: [], # 块队列 filename
|
672
|
-
spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
|
673
|
-
tund_addr: nil, # 远端地址
|
674
|
-
source_exts: {}, # 长命信息 source_id => {}
|
675
|
-
source_ids: {}, # source_id => dest_id
|
676
|
-
dest_ids: {}, # dest_id => source_id
|
677
|
-
fin1s: [], # fin1: source已关闭,等待对面收完流量 source_id
|
678
|
-
fin2s: [], # fin2: 流量已收完 source_id
|
679
|
-
paused: false, # 是否暂停写
|
680
|
-
resendings: [], # 重传队列 [ source_id, pack_id ]
|
681
|
-
last_traffic_at: nil # 收到有效流量,或者发出流量的时间戳
|
682
|
-
}
|
683
|
-
|
684
|
-
@tun = tun
|
685
|
-
@tun_info = tun_info
|
686
|
-
@roles[ tun ] = :tun
|
687
|
-
@infos[ tun ] = tun_info
|
688
|
-
@socks[ tun ] = tun_id
|
689
|
-
@sock_ids[ tun_id ] = tun
|
690
|
-
|
691
|
-
send_pack( tun, @hex.hello, @roomd_addr )
|
692
|
-
add_read( tun )
|
693
|
-
check_expire( tun )
|
694
|
-
end
|
695
|
-
|
696
|
-
def check_expire( tun )
|
697
|
-
Thread.new do
|
698
|
-
sleep 3
|
699
|
-
|
700
|
-
@mutex.synchronize do
|
701
|
-
unless tun.closed?
|
702
|
-
tun_info = @infos[ tun ]
|
703
|
-
|
704
|
-
unless tun_info[ :tund_addr ]
|
705
|
-
tun_id = @socks[ tun ]
|
706
|
-
@ctlw.write( [ CTL_CLOSE, tun_id ].pack( 'CQ>' ) )
|
707
|
-
end
|
708
|
-
end
|
709
|
-
end
|
710
|
-
end
|
711
|
-
end
|
712
|
-
|
713
|
-
def loop_send_heartbeat( tun )
|
714
|
-
Thread.new do
|
715
|
-
loop do
|
716
|
-
break if tun.closed?
|
717
|
-
|
718
|
-
@mutex.synchronize do
|
719
|
-
send_heartbeat( tun )
|
720
|
-
end
|
721
|
-
|
722
|
-
sleep HEARTBEAT_INTERVAL
|
723
|
-
end
|
724
|
-
end
|
725
|
-
end
|
726
|
-
|
727
|
-
def loop_check_expire( tun )
|
728
|
-
Thread.new do
|
729
|
-
loop do
|
730
|
-
sleep CHECK_EXPIRE_INTERVAL
|
731
|
-
|
732
|
-
break if tun.closed?
|
733
|
-
|
734
|
-
@mutex.synchronize do
|
735
|
-
now = Time.new
|
736
|
-
tun_info = @infos[ tun ]
|
737
|
-
|
738
|
-
if now - tun_info[ :last_traffic_at ] > EXPIRE_AFTER
|
739
|
-
tun_id = @socks[ tun ]
|
740
|
-
# puts "debug ctlw close tun #{ tun_id } #{ Time.new } p#{ Process.pid }"
|
741
|
-
@ctlw.write( [ CTL_CLOSE, tun_id ].pack( 'CQ>' ) )
|
742
|
-
end
|
743
|
-
|
744
|
-
exts = tun_info[ :source_exts ].select{ | _, ext | now - ext[ :created_at ] > 5 }
|
745
|
-
|
746
|
-
if exts.any?
|
747
|
-
exts.each do | source_id, ext |
|
748
|
-
if ext[ :last_recv_at ].nil? || ( now - ext[ :last_recv_at ] > EXPIRE_AFTER )
|
749
|
-
# puts "debug ctlw close source #{ source_id } #{ Time.new } p#{ Process.pid }"
|
750
|
-
@ctlw.write( [ CTL_CLOSE, source_id ].pack( 'CQ>' ) )
|
751
|
-
end
|
752
|
-
end
|
753
|
-
end
|
754
|
-
end
|
755
|
-
end
|
756
|
-
end
|
757
|
-
end
|
758
|
-
|
759
|
-
def loop_send_status( tun )
|
760
|
-
Thread.new do
|
761
|
-
loop do
|
762
|
-
sleep STATUS_INTERVAL
|
763
|
-
|
764
|
-
if tun.closed?
|
765
|
-
# puts "debug tun is closed, break send status loop #{ Time.new }"
|
766
|
-
break
|
767
|
-
end
|
768
|
-
|
769
|
-
@mutex.synchronize do
|
770
|
-
tun_info = @infos[ tun ]
|
771
|
-
|
772
|
-
if tun_info[ :source_exts ].any?
|
773
|
-
now = Time.new
|
774
|
-
|
775
|
-
tun_info[ :source_exts ].each do | source_id, ext |
|
776
|
-
if ext[ :last_traffic_at ] && ( now - ext[ :last_traffic_at ] < SEND_STATUS_UNTIL )
|
777
|
-
ctlmsg = [
|
778
|
-
0,
|
779
|
-
SOURCE_STATUS,
|
780
|
-
source_id,
|
781
|
-
ext[ :biggest_pack_id ],
|
782
|
-
ext[ :continue_dest_pack_id ]
|
783
|
-
].pack( 'Q>CQ>Q>Q>' )
|
784
|
-
|
785
|
-
send_pack( tun, ctlmsg, tun_info[ :tund_addr ] )
|
786
|
-
end
|
787
|
-
end
|
788
|
-
end
|
789
|
-
|
790
|
-
if tun_info[ :paused ] && ( tun_info[ :source_exts ].map{ | _, ext | ext[ :wmems ].size }.sum < RESUME_BELOW )
|
791
|
-
tun_id = @socks[ tun ]
|
792
|
-
puts "ctlw resume #{ tun_id } #{ Time.new } p#{ Process.pid }"
|
793
|
-
@ctlw.write( [ CTL_RESUME, tun_id ].pack( 'CQ>' ) )
|
794
|
-
tun_info[ :paused ] = false
|
795
|
-
end
|
796
|
-
end
|
797
|
-
end
|
798
|
-
end
|
799
|
-
end
|
800
|
-
|
801
|
-
def loop_send_a_new_source( source, original_dst )
|
802
|
-
Thread.new do
|
803
|
-
30.times do
|
804
|
-
break if source.closed?
|
805
|
-
|
806
|
-
source_info = @infos[ source ]
|
807
|
-
tun = source_info[ :tun ]
|
808
|
-
break if tun.closed?
|
809
|
-
|
810
|
-
tun_info = @infos[ tun ]
|
811
|
-
|
812
|
-
if tun_info[ :tund_addr ]
|
813
|
-
source_id = @socks[ source ]
|
814
|
-
dest_id = tun_info[ :source_ids ][ source_id ]
|
815
|
-
|
816
|
-
if dest_id
|
817
|
-
# puts "debug break a new source loop #{ Time.new } p#{ Process.pid }"
|
818
|
-
break
|
819
|
-
end
|
820
|
-
end
|
821
|
-
|
822
|
-
@mutex.synchronize do
|
823
|
-
ctlmsg = "#{ [ 0, A_NEW_SOURCE, source_id ].pack( 'Q>CQ>' ) }#{ original_dst }"
|
824
|
-
# puts "debug send a new source #{ Time.new } p#{ Process.pid }"
|
825
|
-
send_pack( tun, ctlmsg, tun_info[ :tund_addr ] )
|
826
|
-
end
|
827
|
-
|
828
|
-
sleep 1
|
829
|
-
end
|
830
|
-
end
|
831
|
-
end
|
832
|
-
|
833
|
-
def loop_send_fin1( tun, source_id )
|
834
|
-
Thread.new do
|
835
|
-
30.times do
|
836
|
-
break if tun.closed?
|
837
|
-
|
838
|
-
tun_info = @infos[ tun ]
|
839
|
-
break unless tun_info[ :tund_addr ]
|
840
|
-
|
841
|
-
unless tun_info[ :fin1s ].include?( source_id )
|
842
|
-
# puts "debug break send fin1 loop #{ Time.new } p#{ Process.pid }"
|
843
|
-
break
|
844
|
-
end
|
845
|
-
|
846
|
-
@mutex.synchronize do
|
847
|
-
ctlmsg = [
|
848
|
-
0,
|
849
|
-
FIN1,
|
850
|
-
source_id
|
851
|
-
].pack( 'Q>CQ>' )
|
852
|
-
|
853
|
-
# puts "debug send FIN1 #{ source_id } #{ Time.new } p#{ Process.pid }"
|
854
|
-
send_pack( tun, ctlmsg, tun_info[ :tund_addr ] )
|
855
|
-
end
|
856
|
-
|
857
|
-
sleep 1
|
858
|
-
end
|
859
|
-
end
|
860
|
-
end
|
861
|
-
|
862
|
-
def loop_send_fin2( tun, source_id )
|
863
|
-
Thread.new do
|
864
|
-
30.times do
|
865
|
-
break if tun.closed?
|
866
|
-
|
867
|
-
tun_info = @infos[ tun ]
|
868
|
-
break unless tun_info[ :tund_addr ]
|
869
|
-
|
870
|
-
unless tun_info[ :fin2s ].include?( source_id )
|
871
|
-
# puts "debug break send fin2 loop #{ Time.new } p#{ Process.pid }"
|
872
|
-
break
|
873
|
-
end
|
874
|
-
|
875
|
-
@mutex.synchronize do
|
876
|
-
ctlmsg = [
|
877
|
-
0,
|
878
|
-
FIN2,
|
879
|
-
source_id
|
880
|
-
].pack( 'Q>CQ>' )
|
881
|
-
|
882
|
-
# puts "debug send FIN2 #{ source_id } #{ Time.new } p#{ Process.pid }"
|
883
|
-
send_pack( tun, ctlmsg, tun_info[ :tund_addr ] )
|
884
|
-
end
|
885
|
-
|
886
|
-
sleep 1
|
887
|
-
end
|
888
|
-
end
|
889
|
-
end
|
890
|
-
|
891
|
-
def send_heartbeat( tun )
|
892
|
-
info = @infos[ tun ]
|
893
|
-
ctlmsg = [ 0, HEARTBEAT, rand( 128 ) ].pack( 'Q>CC' )
|
894
|
-
send_pack( tun, ctlmsg, info[ :tund_addr ] )
|
895
|
-
end
|
896
|
-
|
897
|
-
def send_pack( sock, data, target_sockaddr )
|
898
|
-
begin
|
899
|
-
sock.sendmsg( data, 0, target_sockaddr )
|
900
|
-
rescue IO::WaitWritable, Errno::EINTR => e
|
901
|
-
puts "sendmsg #{ e.class } #{ Time.new } p#{ Process.pid }"
|
902
|
-
end
|
903
|
-
end
|
904
|
-
|
905
|
-
def add_read( sock )
|
906
|
-
return if sock.closed? || @reads.include?( sock )
|
907
|
-
|
908
|
-
@reads << sock
|
909
|
-
end
|
910
|
-
|
911
|
-
def add_write( sock )
|
912
|
-
return if sock.closed? || @writes.include?( sock )
|
913
|
-
|
914
|
-
@writes << sock
|
915
|
-
end
|
916
|
-
|
917
|
-
def add_closing( sock )
|
918
|
-
return if sock.closed? || @closings.include?( sock )
|
919
|
-
|
920
|
-
@reads.delete( sock )
|
921
|
-
@closings << sock
|
922
|
-
add_write( sock )
|
923
|
-
end
|
924
|
-
|
925
|
-
def close_tun( tun )
|
926
|
-
info = close_sock( tun )
|
927
|
-
|
928
|
-
info[ :chunks ].each do | filename |
|
929
|
-
begin
|
930
|
-
File.delete( File.join( @tun_chunk_dir, filename ) )
|
931
|
-
rescue Errno::ENOENT
|
932
|
-
end
|
933
|
-
end
|
934
|
-
|
935
|
-
info[ :source_exts ].each{ | _, ext | add_closing( ext[ :source ] ) }
|
936
|
-
end
|
937
|
-
|
938
|
-
def close_source( source )
|
939
|
-
info = close_sock( source )
|
940
|
-
tun = info[ :tun ]
|
941
|
-
return if tun.closed?
|
942
|
-
|
943
|
-
source_id = info[ :id ]
|
944
|
-
tun_info = @infos[ tun ]
|
945
|
-
ext = tun_info[ :source_exts ][ source_id ]
|
946
|
-
return unless ext
|
947
|
-
|
948
|
-
if ext[ :is_dest_closed ]
|
949
|
-
del_source_ext( tun_info, source_id )
|
950
|
-
|
951
|
-
unless tun_info[ :fin2s ].include?( source_id )
|
952
|
-
# puts "debug 2-3. source.close -> ext.is_dest_closed ? yes -> del ext -> loop send fin2 #{ Time.new } p#{ Process.pid }"
|
953
|
-
tun_info[ :fin2s ] << source_id
|
954
|
-
loop_send_fin2( tun, source_id )
|
955
|
-
end
|
956
|
-
elsif !tun_info[ :fin1s ].include?( source_id )
|
957
|
-
# puts "debug 1-1. source.close -> ext.is_dest_closed ? no -> send fin1 loop #{ Time.new } p#{ Process.pid }"
|
958
|
-
tun_info[ :fin1s ] << source_id
|
959
|
-
loop_send_fin1( tun, source_id )
|
960
|
-
end
|
961
|
-
end
|
962
|
-
|
963
|
-
def close_sock( sock )
|
964
|
-
sock.close
|
965
|
-
@reads.delete( sock )
|
966
|
-
@writes.delete( sock )
|
967
|
-
@closings.delete( sock )
|
968
|
-
@roles.delete( sock )
|
969
|
-
info = @infos.delete( sock )
|
970
|
-
sock_id = @socks.delete( sock )
|
971
|
-
@sock_ids.delete( sock_id )
|
972
|
-
|
973
|
-
info
|
974
|
-
end
|
975
|
-
|
976
|
-
def del_source_ext( tun_info, source_id )
|
977
|
-
tun_info[ :waitings ].delete( source_id )
|
978
|
-
ext = tun_info[ :source_exts ].delete( source_id )
|
979
|
-
|
980
|
-
if ext
|
981
|
-
ext[ :chunks ].each do | filename |
|
982
|
-
begin
|
983
|
-
File.delete( File.join( @source_chunk_dir, filename ) )
|
984
|
-
rescue Errno::ENOENT
|
985
|
-
end
|
986
|
-
end
|
987
|
-
end
|
988
|
-
|
989
|
-
dest_id = tun_info[ :source_ids ].delete( source_id )
|
990
|
-
|
991
|
-
if dest_id
|
992
|
-
tun_info[ :dest_ids ].delete( dest_id )
|
993
|
-
end
|
994
|
-
end
|
995
|
-
|
996
|
-
end
|
997
|
-
end
|