girl 0.69.0 → 0.70.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.

@@ -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
@@ -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