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