p2p2 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/p2p2/p2.rb CHANGED
@@ -1,114 +1,57 @@
1
- require 'json'
2
- require 'p2p2/head'
3
- require 'p2p2/p2_custom'
4
- require 'p2p2/p2_worker'
5
- require 'p2p2/version'
6
- require 'socket'
7
-
8
- ##
9
- # P2p2::P2 - p2p通道,p2端。
10
- #
11
- module P2p2
12
- class P2
13
-
14
- def initialize( config_path = nil )
15
- unless config_path
16
- config_path = File.expand_path( '../p2p2.conf.json', __FILE__ )
17
- end
18
-
19
- unless File.exist?( config_path )
20
- raise "missing config file #{ config_path }"
21
- end
22
-
23
- conf = JSON.parse( IO.binread( config_path ), symbolize_names: true )
24
- p2pd_host = conf[ :p2pd_host ]
25
- p2pd_port = conf[ :p2pd_port ]
26
- room = conf[ :room ]
27
- sdwd_host = conf[ :sdwd_host ]
28
- sdwd_port = conf[ :sdwd_port ]
29
- p2_tmp_dir = conf[ :p2_tmp_dir ]
30
-
31
- unless p2pd_host
32
- raise "missing p2pd host"
33
- end
34
-
35
- unless room
36
- raise "missing room"
37
- end
38
-
39
- unless p2pd_port
40
- p2pd_port = 2020
41
- end
42
-
43
- unless sdwd_host
44
- sdwd_host = '0.0.0.0'
45
- end
46
-
47
- unless sdwd_port
48
- sdwd_port = 2222
49
- end
50
-
51
- unless p2_tmp_dir
52
- p2_tmp_dir = '/tmp/p2p2.p2'
53
- end
54
-
55
- unless File.exist?( p2_tmp_dir )
56
- Dir.mkdir( p2_tmp_dir )
57
- end
58
-
59
- src_chunk_dir = File.join( p2_tmp_dir, 'src.chunk' )
60
-
61
- unless Dir.exist?( src_chunk_dir )
62
- Dir.mkdir( src_chunk_dir )
63
- end
64
-
65
- tun_chunk_dir = File.join( p2_tmp_dir, 'tun.chunk' )
66
-
67
- unless Dir.exist?( tun_chunk_dir )
68
- Dir.mkdir( tun_chunk_dir )
69
- end
70
-
71
- title = "p2p2 p2 #{ P2p2::VERSION }"
72
- puts title
73
- puts "p2pd host #{ p2pd_host }"
74
- puts "p2pd port #{ p2pd_port }"
75
- puts "room #{ room }"
76
- puts "sdwd host #{ sdwd_host }"
77
- puts "sdwd port #{ sdwd_port }"
78
- puts "p2 tmp dir #{ p2_tmp_dir }"
79
- puts "src chunk dir #{ src_chunk_dir }"
80
- puts "tun chunk dir #{ tun_chunk_dir }"
81
-
82
- if RUBY_PLATFORM.include?( 'linux' )
83
- $0 = title
84
-
85
- pid = fork do
86
- $0 = 'p2p2 p2 worker'
87
- worker = P2p2::P2Worker.new( p2pd_host, p2pd_port, room, sdwd_host, sdwd_port, src_chunk_dir, tun_chunk_dir )
88
-
89
- Signal.trap( :TERM ) do
90
- puts 'exit'
91
- worker.quit!
92
- end
93
-
94
- worker.looping
95
- end
96
-
97
- Signal.trap( :TERM ) do
98
- puts 'trap TERM'
99
-
100
- begin
101
- Process.kill( :TERM, pid )
102
- rescue Errno::ESRCH => e
103
- puts e.class
104
- end
105
- end
106
-
107
- Process.waitall
108
- else
109
- P2p2::P2Worker.new( p2pd_host, p2pd_port, room, sdwd_host, sdwd_port, src_chunk_dir, tun_chunk_dir ).looping
110
- end
111
- end
112
-
113
- end
114
- end
1
+ require 'json'
2
+ require 'p2p2/concurrent_hash'
3
+ require 'p2p2/head'
4
+ require 'p2p2/p2_worker'
5
+ require 'p2p2/version'
6
+ require 'socket'
7
+
8
+ ##
9
+ # P2p2::P2 - p2
10
+ #
11
+ module P2p2
12
+ class P2
13
+
14
+ def initialize( config_path = nil )
15
+ unless config_path then
16
+ config_path = File.expand_path( '../p2p2.conf.json', __FILE__ )
17
+ end
18
+
19
+ raise "missing config file #{ config_path }" unless File.exist?( config_path )
20
+
21
+ conf = JSON.parse( IO.binread( config_path ), symbolize_names: true )
22
+ paird_host = conf[ :paird_host ]
23
+ paird_port = conf[ :paird_port ]
24
+ room = conf[ :room ]
25
+ shadow_host = conf[ :shadow_host ]
26
+ shadow_port = conf[ :shadow_port ]
27
+
28
+ raise 'missing paird host' unless paird_host
29
+ raise 'missing room' unless room
30
+
31
+ unless paird_port then
32
+ paird_port = 4040
33
+ end
34
+
35
+ unless shadow_host then
36
+ shadow_host = '0.0.0.0'
37
+ end
38
+
39
+ unless shadow_port then
40
+ shadow_port = 4444
41
+ end
42
+
43
+ puts "p2p2 p2 #{ P2p2::VERSION }"
44
+ puts "paird #{ paird_host } #{ paird_port } room #{ room } shadow #{ shadow_host } #{ shadow_port }"
45
+
46
+ worker = P2p2::P2Worker.new( paird_host, paird_port, room, shadow_host, shadow_port )
47
+
48
+ Signal.trap( :TERM ) do
49
+ puts 'exit'
50
+ worker.quit!
51
+ end
52
+
53
+ worker.looping
54
+ end
55
+
56
+ end
57
+ end
@@ -1,979 +1,682 @@
1
- module P2p2
2
- class P2Worker
3
-
4
- ##
5
- # initialize
6
- #
7
- def initialize( p2pd_host, p2pd_port, room, sdwd_host, sdwd_port, src_chunk_dir, tun_chunk_dir )
8
- @p2pd_addr = Socket.sockaddr_in( p2pd_port, p2pd_host )
9
- @room = room
10
- @sdwd_addr = Socket.sockaddr_in( sdwd_port, sdwd_host )
11
- @src_chunk_dir = src_chunk_dir
12
- @tun_chunk_dir = tun_chunk_dir
13
- @custom = P2p2::P2Custom.new
14
- @mutex = Mutex.new
15
- @reads = []
16
- @writes = []
17
- @roles = {} # sock => :dotr / :sdwd / :src / :tun
18
- @src_infos = {} # src => {}
19
-
20
- dotr, dotw = IO.pipe
21
- @dotw = dotw
22
- add_read( dotr, :dotr )
23
- new_a_sdwd
24
- end
25
-
26
- ##
27
- # looping
28
- #
29
- def looping
30
- puts "#{ Time.new } looping"
31
- loop_heartbeat
32
- loop_check_status
33
-
34
- loop do
35
- rs, ws = IO.select( @reads, @writes )
36
-
37
- @mutex.synchronize do
38
- # 先写,再读
39
- ws.each do | sock |
40
- case @roles[ sock ]
41
- when :src
42
- write_src( sock )
43
- when :tun
44
- write_tun( sock )
45
- end
46
- end
47
-
48
- rs.each do | sock |
49
- case @roles[ sock ]
50
- when :dotr
51
- read_dotr( sock )
52
- when :sdwd
53
- read_sdwd( sock )
54
- when :src
55
- read_src( sock )
56
- when :tun
57
- read_tun( sock )
58
- end
59
- end
60
- end
61
- end
62
- rescue Interrupt => e
63
- puts e.class
64
- quit!
65
- end
66
-
67
- ##
68
- # quit!
69
- #
70
- def quit!
71
- if @tun && !@tun.closed? && @tun_info[ :tund_addr ]
72
- # puts "debug1 send tun fin"
73
- data = [ 0, TUN_FIN ].pack( 'Q>C' )
74
- @tun.sendmsg( data, 0, @tun_info[ :tund_addr ] )
75
- end
76
-
77
- # puts "debug1 exit"
78
- exit
79
- end
80
-
81
- private
82
-
83
- ##
84
- # loop heartbeat
85
- #
86
- def loop_heartbeat( check_at = Time.new )
87
- Thread.new do
88
- loop do
89
- sleep HEARTBEAT_INTERVAL
90
-
91
- @mutex.synchronize do
92
- now = Time.new
93
-
94
- if @tun && !@tun.closed? && @tun_info[ :peer_addr ] && @tun_info[ :peer_at ]
95
- if @tun_info[ :tund_addr ]
96
- if now - check_at >= CHECK_EXPIRE_INTERVAL
97
- if now - @tun_info[ :last_recv_at ] > EXPIRE_AFTER
98
- puts "#{ Time.new } expire tun"
99
- set_is_closing( @tun )
100
- else
101
- @tun_info[ :src_exts ].each do | src_id, src_ext |
102
- if src_ext[ :src ].closed? && ( now - src_ext[ :last_continue_at ] > EXPIRE_AFTER )
103
- puts "#{ Time.new } expire src ext"
104
- del_src_ext( src_id )
105
- end
106
- end
107
- end
108
-
109
- @src_infos.each do | src, src_info |
110
- if now - src_info[ :last_continue_at ] > EXPIRE_AFTER
111
- puts "#{ Time.new } expire src"
112
- set_is_closing( src )
113
- end
114
- end
115
-
116
- check_at = now
117
- end
118
-
119
- # puts "debug2 heartbeat"
120
- add_tun_ctlmsg( pack_a_heartbeat )
121
- next_tick
122
- elsif now - @tun_info[ :peer_at ] > EXPIRE_NEW
123
- puts "#{ Time.new } expire new tun"
124
- set_is_closing( @tun )
125
- next_tick
126
- end
127
- end
128
- end
129
- end
130
- end
131
- end
132
-
133
- ##
134
- # loop check status
135
- #
136
- def loop_check_status
137
- Thread.new do
138
- loop do
139
- sleep STATUS_INTERVAL
140
-
141
- @mutex.synchronize do
142
- if @tun && !@tun.closed? && @tun_info[ :tund_addr ]
143
- need_trigger = false
144
-
145
- if @tun_info[ :src_exts ].any?
146
- now = Time.new
147
-
148
- @tun_info[ :src_exts ].each do | src_id, src_ext |
149
- if now - src_ext[ :last_continue_at ] < SEND_STATUS_UNTIL
150
- data = [ 0, SOURCE_STATUS, src_id, src_ext[ :relay_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
151
- add_tun_ctlmsg( data )
152
- need_trigger = true
153
- end
154
- end
155
- end
156
-
157
- if @tun_info[ :paused ] && ( @tun_info[ :src_exts ].map{ | _, src_ext | src_ext[ :wmems ].size }.sum < RESUME_BELOW )
158
- puts "#{ Time.new } resume tun"
159
- @tun_info[ :paused ] = false
160
- add_write( @tun )
161
- need_trigger = true
162
- end
163
-
164
- if need_trigger
165
- next_tick
166
- end
167
- end
168
- end
169
- end
170
- end
171
- end
172
-
173
- ##
174
- # loop punch peer
175
- #
176
- def loop_punch_peer
177
- Thread.new do
178
- EXPIRE_NEW.times do
179
- if @tun.closed?
180
- # puts "debug1 break loop punch peer"
181
- break
182
- end
183
-
184
- @mutex.synchronize do
185
- # puts "debug1 punch peer"
186
- add_tun_ctlmsg( pack_a_heartbeat, @tun_info[ :peer_addr ] )
187
- next_tick
188
- end
189
-
190
- sleep 1
191
- end
192
- end
193
- end
194
-
195
- ##
196
- # loop send a new source
197
- #
198
- def loop_send_a_new_source( src_ext, data )
199
- Thread.new do
200
- EXPIRE_NEW.times do
201
- if src_ext[ :src ].closed? || src_ext[ :dst_port ]
202
- # puts "debug1 break loop send a new source #{ src_ext[ :dst_port ] }"
203
- break
204
- end
205
-
206
- @mutex.synchronize do
207
- # puts "debug1 send a new source #{ data.inspect }"
208
- add_tun_ctlmsg( data )
209
- next_tick
210
- end
211
-
212
- sleep 1
213
- end
214
- end
215
- end
216
-
217
- ##
218
- # new a sdwd
219
- #
220
- def new_a_sdwd
221
- sdwd = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
222
- sdwd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
223
-
224
- if RUBY_PLATFORM.include?( 'linux' )
225
- sdwd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
226
- sdwd.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
227
- end
228
-
229
- sdwd.bind( @sdwd_addr )
230
- sdwd.listen( 511 )
231
- puts "#{ Time.new } sdwd listen on #{ sdwd.local_address.ip_port }"
232
- add_read( sdwd, :sdwd )
233
- end
234
-
235
- ##
236
- # new a tun
237
- #
238
- def new_a_tun
239
- tun = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
240
- tun.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
241
- port = tun.local_address.ip_port
242
- puts "#{ Time.new } tun bind on #{ port }"
243
-
244
- tun_info = {
245
- port: port, # 端口
246
- ctlmsgs: [], # [ to_addr, data ]
247
- wbuffs: [], # 写前缓存 [ src_id, pack_id, data ]
248
- caches: [], # 块读出缓存 [ src_id, pack_id, data ]
249
- chunks: [], # 块队列 filename
250
- spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
251
- peer_addr: nil, # 配对地址
252
- peer_at: nil, # 收到配对地址时间
253
- tund_addr: nil, # 连通后的tund地址
254
- src_exts: {}, # src额外信息 src_id => {}
255
- src_ids: {}, # dst_port => src_id
256
- paused: false, # 是否暂停写
257
- resendings: [], # 重传队列 [ src_id, pack_id ]
258
- created_at: Time.new, # 创建时间
259
- last_recv_at: nil, # 上一次收到流量的时间,过期关闭
260
- is_closing: false # 是否准备关闭
261
- }
262
-
263
- @tun = tun
264
- @tun_info = tun_info
265
- add_read( tun, :tun )
266
- add_tun_ctlmsg( [ '2', @room ].join, @p2pd_addr )
267
- end
268
-
269
- ##
270
- # pack a heartbeat
271
- #
272
- def pack_a_heartbeat
273
- [ 0, HEARTBEAT, rand( 128 ) ].pack( 'Q>CC' )
274
- end
275
-
276
- ##
277
- # is match tund addr
278
- #
279
- def is_match_tund_addr( addrinfo )
280
- return false unless @tun_info[ :tund_addr ]
281
-
282
- from_addr = addrinfo.to_sockaddr
283
-
284
- if from_addr != @tun_info[ :tund_addr ]
285
- puts "#{ Time.new } #{ addrinfo.inspect } not match #{ Addrinfo.new( @tun_info[ :tund_addr ] ).inspect }"
286
- return false
287
- end
288
-
289
- @tun_info[ :last_recv_at ] = Time.new
290
-
291
- true
292
- end
293
-
294
- ##
295
- # add tun ctlmsg
296
- #
297
- def add_tun_ctlmsg( data, to_addr = nil )
298
- unless to_addr
299
- to_addr = @tun_info[ :tund_addr ]
300
- end
301
-
302
- if to_addr
303
- @tun_info[ :ctlmsgs ] << [ to_addr, data ]
304
- add_write( @tun )
305
- end
306
- end
307
-
308
- ##
309
- # add tun wbuff
310
- #
311
- def add_tun_wbuff( src_id, pack_id, data )
312
- @tun_info[ :wbuffs ] << [ src_id, pack_id, data ]
313
-
314
- if @tun_info[ :wbuffs ].size >= WBUFFS_LIMIT
315
- spring = @tun_info[ :chunks ].size > 0 ? ( @tun_info[ :spring ] + 1 ) : 0
316
- filename = "#{ Process.pid }-#{ @tun_info[ :port ] }.#{ spring }"
317
- chunk_path = File.join( @tun_chunk_dir, filename )
318
- datas = @tun_info[ :wbuffs ].map{ | _src_id, _pack_id, _data | [ [ _src_id, _pack_id, _data.bytesize ].pack( 'Q>Q>n' ), _data ].join }
319
-
320
- begin
321
- IO.binwrite( chunk_path, datas.join )
322
- rescue Errno::ENOSPC => e
323
- puts "#{ Time.new } #{ e.class }, close tun"
324
- set_is_closing( @tun )
325
- return
326
- end
327
-
328
- @tun_info[ :chunks ] << filename
329
- @tun_info[ :spring ] = spring
330
- @tun_info[ :wbuffs ].clear
331
- end
332
-
333
- add_write( @tun )
334
- end
335
-
336
- ##
337
- # add src wbuff
338
- #
339
- def add_src_wbuff( src, data )
340
- src_info = @src_infos[ src ]
341
- src_info[ :wbuff ] << data
342
-
343
- if src_info[ :wbuff ].bytesize >= CHUNK_SIZE
344
- spring = src_info[ :chunks ].size > 0 ? ( src_info[ :spring ] + 1 ) : 0
345
- filename = "#{ Process.pid }-#{ src_info[ :id ] }.#{ spring }"
346
- chunk_path = File.join( @src_chunk_dir, filename )
347
-
348
- begin
349
- IO.binwrite( chunk_path, src_info[ :wbuff ] )
350
- rescue Errno::ENOSPC => e
351
- puts "#{ Time.new } #{ e.class }, close src"
352
- set_is_closing( src )
353
- return
354
- end
355
-
356
- src_info[ :chunks ] << filename
357
- src_info[ :spring ] = spring
358
- src_info[ :wbuff ].clear
359
- end
360
-
361
- add_write( src )
362
- end
363
-
364
- ##
365
- # add read
366
- #
367
- def add_read( sock, role )
368
- unless @reads.include?( sock )
369
- @reads << sock
370
- end
371
-
372
- @roles[ sock ] = role
373
- end
374
-
375
- ##
376
- # add write
377
- #
378
- def add_write( sock )
379
- if sock && !sock.closed? && !@writes.include?( sock )
380
- @writes << sock
381
- end
382
- end
383
-
384
- ##
385
- # set is closing
386
- #
387
- def set_is_closing( sock )
388
- if sock && !sock.closed?
389
- role = @roles[ sock ]
390
- # puts "debug1 set #{ role.to_s } is closing"
391
-
392
- case role
393
- when :src
394
- src_info = @src_infos[ sock ]
395
- src_info[ :is_closing ] = true
396
- when :tun
397
- @tun_info[ :is_closing ] = true
398
- end
399
-
400
- @reads.delete( sock )
401
- add_write( sock )
402
- end
403
- end
404
-
405
- ##
406
- # send data
407
- #
408
- def send_data( tun, data, to_addr )
409
- begin
410
- tun.sendmsg( data, 0, to_addr )
411
- rescue IO::WaitWritable, Errno::EINTR
412
- return false
413
- rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN => e
414
- puts "#{ Time.new } #{ e.class }, close tun"
415
- close_tun( tun )
416
- return false
417
- end
418
-
419
- true
420
- end
421
-
422
- ##
423
- # close src
424
- #
425
- def close_src( src )
426
- # puts "debug1 close src"
427
- close_sock( src )
428
- src_info = @src_infos.delete( src )
429
-
430
- src_info[ :chunks ].each do | filename |
431
- begin
432
- File.delete( File.join( @src_chunk_dir, filename ) )
433
- rescue Errno::ENOENT
434
- end
435
- end
436
-
437
- return if @tun.closed?
438
-
439
- src_id = src_info[ :id ]
440
- src_ext = @tun_info[ :src_exts ][ src_id ]
441
- return unless src_ext
442
-
443
- if src_ext[ :is_dst_closed ]
444
- # puts "debug1 2-3. after close src -> dst closed ? yes -> del src ext -> send fin2"
445
- del_src_ext( src_id )
446
- data = [ 0, FIN2, src_id ].pack( 'Q>CQ>' )
447
- add_tun_ctlmsg( data )
448
- else
449
- # puts "debug1 1-1. after close src -> dst closed ? no -> send fin1"
450
- data = [ 0, FIN1, src_id, src_info[ :biggest_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
451
- add_tun_ctlmsg( data )
452
- end
453
- end
454
-
455
- ##
456
- # close tun
457
- #
458
- def close_tun( tun )
459
- # puts "debug1 close tun"
460
- close_sock( tun )
461
-
462
- @tun_info[ :chunks ].each do | filename |
463
- begin
464
- File.delete( File.join( @tun_chunk_dir, filename ) )
465
- rescue Errno::ENOENT
466
- end
467
- end
468
-
469
- @tun_info[ :src_exts ].each{ | _, src_ext | set_is_closing( src_ext[ :src ] ) }
470
- end
471
-
472
- ##
473
- # close sock
474
- #
475
- def close_sock( sock )
476
- sock.close
477
- @reads.delete( sock )
478
- @writes.delete( sock )
479
- @roles.delete( sock )
480
- end
481
-
482
- ##
483
- # del src ext
484
- #
485
- def del_src_ext( src_id )
486
- src_ext = @tun_info[ :src_exts ].delete( src_id )
487
-
488
- if src_ext
489
- @tun_info[ :src_ids ].delete( src_ext[ :dst_port ] )
490
- end
491
- end
492
-
493
- ##
494
- # release wmems
495
- #
496
- def release_wmems( src_ext, completed_pack_id )
497
- if completed_pack_id > src_ext[ :completed_pack_id ]
498
- # puts "debug2 update completed pack #{ completed_pack_id }"
499
-
500
- pack_ids = src_ext[ :wmems ].keys.select { | pack_id | pack_id <= completed_pack_id }
501
-
502
- pack_ids.each do | pack_id |
503
- src_ext[ :wmems ].delete( pack_id )
504
- src_ext[ :send_ats ].delete( pack_id )
505
- end
506
-
507
- src_ext[ :completed_pack_id ] = completed_pack_id
508
- end
509
- end
510
-
511
- ##
512
- # next tick
513
- #
514
- def next_tick
515
- @dotw.write( '.' )
516
- end
517
-
518
- ##
519
- # write src
520
- #
521
- def write_src( src )
522
- src_info = @src_infos[ src ]
523
- from, data = :cache, src_info[ :cache ]
524
-
525
- if data.empty?
526
- if src_info[ :chunks ].any?
527
- path = File.join( @src_chunk_dir, src_info[ :chunks ].shift )
528
-
529
- begin
530
- data = src_info[ :cache ] = IO.binread( path )
531
- File.delete( path )
532
- rescue Errno::ENOENT => e
533
- puts "#{ Time.new } read #{ path } #{ e.class }"
534
- close_src( src )
535
- return
536
- end
537
- else
538
- from, data = :wbuff, src_info[ :wbuff ]
539
- end
540
- end
541
-
542
- if data.empty?
543
- if src_info[ :is_closing ]
544
- close_src( src )
545
- else
546
- @writes.delete( src )
547
- end
548
-
549
- return
550
- end
551
-
552
- begin
553
- written = src.write_nonblock( data )
554
- rescue IO::WaitWritable, Errno::EINTR
555
- return
556
- rescue Exception => e
557
- close_src( src )
558
- return
559
- end
560
-
561
- # puts "debug2 write src #{ written }"
562
- data = data[ written..-1 ]
563
- src_info[ from ] = data
564
- src_info[ :last_continue_at ] = Time.new
565
- end
566
-
567
- ##
568
- # write tun
569
- #
570
- def write_tun( tun )
571
- if @tun_info[ :is_closing ]
572
- close_tun( tun )
573
- return
574
- end
575
-
576
- now = Time.new
577
-
578
- # 传ctlmsg
579
- while @tun_info[ :ctlmsgs ].any?
580
- to_addr, data = @tun_info[ :ctlmsgs ].first
581
-
582
- unless send_data( tun, data, to_addr )
583
- return
584
- end
585
-
586
- @tun_info[ :ctlmsgs ].shift
587
- end
588
-
589
- # 重传
590
- while @tun_info[ :resendings ].any?
591
- src_id, pack_id = @tun_info[ :resendings ].first
592
- src_ext = @tun_info[ :src_exts ][ src_id ]
593
-
594
- if src_ext
595
- data = src_ext[ :wmems ][ pack_id ]
596
-
597
- if data
598
- unless send_data( tun, data, @tun_info[ :tund_addr ] )
599
- return
600
- end
601
-
602
- src_ext[ :last_continue_at ] = now
603
- end
604
- end
605
-
606
- @tun_info[ :resendings ].shift
607
- end
608
-
609
- # 若写后达到上限,暂停取写前
610
- if @tun_info[ :src_exts ].map{ | _, src_ext | src_ext[ :wmems ].size }.sum >= WMEMS_LIMIT
611
- unless @tun_info[ :paused ]
612
- puts "#{ Time.new } pause tun #{ @tun_info[ :port ] }"
613
- @tun_info[ :paused ] = true
614
- end
615
-
616
- @writes.delete( tun )
617
- return
618
- end
619
-
620
- # 取写前
621
- if @tun_info[ :caches ].any?
622
- datas = @tun_info[ :caches ]
623
- elsif @tun_info[ :chunks ].any?
624
- path = File.join( @tun_chunk_dir, @tun_info[ :chunks ].shift )
625
-
626
- begin
627
- data = IO.binread( path )
628
- File.delete( path )
629
- rescue Errno::ENOENT => e
630
- puts "#{ Time.new } read #{ path } #{ e.class }"
631
- close_tun( tun )
632
- return
633
- end
634
-
635
- caches = []
636
-
637
- until data.empty?
638
- _src_id, _pack_id, pack_size = data[ 0, 18 ].unpack( 'Q>Q>n' )
639
- caches << [ _src_id, _pack_id, data[ 18, pack_size ] ]
640
- data = data[ ( 18 + pack_size )..-1 ]
641
- end
642
-
643
- datas = @tun_info[ :caches ] = caches
644
- elsif @tun_info[ :wbuffs ].any?
645
- datas = @tun_info[ :wbuffs ]
646
- else
647
- @writes.delete( tun )
648
- return
649
- end
650
-
651
- while datas.any?
652
- src_id, pack_id, data = datas.first
653
- src_ext = @tun_info[ :src_exts ][ src_id ]
654
-
655
- if src_ext
656
- if pack_id <= CONFUSE_UNTIL
657
- data = @custom.encode( data )
658
- # puts "debug1 encoded pack #{ pack_id }"
659
- end
660
-
661
- data = [ [ pack_id, src_id ].pack( 'Q>Q>' ), data ].join
662
-
663
- unless send_data( tun, data, @tun_info[ :tund_addr ] )
664
- return
665
- end
666
-
667
- # puts "debug2 written pack #{ pack_id }"
668
- src_ext[ :relay_pack_id ] = pack_id
669
- src_ext[ :wmems ][ pack_id ] = data
670
- src_ext[ :send_ats ][ pack_id ] = now
671
- src_ext[ :last_continue_at ] = now
672
- end
673
-
674
- datas.shift
675
- end
676
- end
677
-
678
- ##
679
- # read dotr
680
- #
681
- def read_dotr( dotr )
682
- dotr.read( 1 )
683
- end
684
-
685
- ##
686
- # read sdwd
687
- #
688
- def read_sdwd( sdwd )
689
- begin
690
- src, addrinfo = sdwd.accept_nonblock
691
- rescue IO::WaitReadable, Errno::EINTR
692
- return
693
- end
694
-
695
- id = rand( ( 2 ** 64 ) - 1 ) + 1
696
- # puts "debug1 accept a src #{ addrinfo.inspect } #{ id }"
697
-
698
- @src_infos[ src ] = {
699
- id: id, # id
700
- biggest_pack_id: 0, # 最大包号码
701
- rbuffs: [], # p1端dst未准备好,暂存流量 [ pack_id, data ]
702
- wbuff: '', # 写前
703
- cache: '', # 块读出缓存
704
- chunks: [], # 块队列,写前达到块大小时结一个块 filename
705
- spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
706
- last_continue_at: Time.new, # 上一次发生流量的时间
707
- is_closing: false # 是否准备关闭
708
- }
709
-
710
- add_read( src, :src )
711
-
712
- if @tun.nil? || @tun.closed?
713
- new_a_tun
714
- end
715
-
716
- src_ext = {
717
- src: src, # src
718
- dst_port: nil, # p1端dst端口
719
- wmems: {}, # 写后 pack_id => data
720
- send_ats: {}, # 上一次发出时间 pack_id => send_at
721
- relay_pack_id: 0, # 转发到几
722
- continue_dst_pack_id: 0, # 收到几
723
- pieces: {}, # 跳号包 dst_pack_id => data
724
- is_dst_closed: false, # dst是否已关闭
725
- biggest_dst_pack_id: 0, # dst最大包号码
726
- completed_pack_id: 0, # 完成到几(对面收到几)
727
- last_continue_at: Time.new # 上一次发生流量的时间
728
- }
729
-
730
- @tun_info[ :src_exts ][ id ] = src_ext
731
- data = [ 0, A_NEW_SOURCE, id ].pack( 'Q>CQ>' )
732
- loop_send_a_new_source( src_ext, data )
733
- end
734
-
735
- ##
736
- # read src
737
- #
738
- def read_src( src )
739
- begin
740
- data = src.read_nonblock( PACK_SIZE )
741
- rescue IO::WaitReadable, Errno::EINTR
742
- return
743
- rescue Exception => e
744
- # puts "debug1 read src #{ e.class }"
745
- set_is_closing( src )
746
- return
747
- end
748
-
749
- # puts "debug2 read src #{ data.inspect }"
750
- src_info = @src_infos[ src ]
751
- src_info[ :last_continue_at ] = Time.new
752
- src_id = src_info[ :id ]
753
- src_ext = @tun_info[ :src_exts ][ src_id ]
754
-
755
- unless src_ext
756
- # puts "debug1 not found src ext"
757
- set_is_closing( src )
758
- return
759
- end
760
-
761
- if @tun.closed?
762
- puts "#{ Time.new } tun closed, close src"
763
- set_is_closing( src )
764
- return
765
- end
766
-
767
- pack_id = src_info[ :biggest_pack_id ] + 1
768
- src_info[ :biggest_pack_id ] = pack_id
769
-
770
- if src_ext[ :dst_port ]
771
- add_tun_wbuff( src_info[ :id ], pack_id, data )
772
- else
773
- # puts "debug1 p1 dst not ready, save data to src rbuff"
774
- src_info[ :rbuffs ] << [ pack_id, data ]
775
- end
776
- end
777
-
778
- ##
779
- # read tun
780
- #
781
- def read_tun( tun )
782
- data, addrinfo, rflags, *controls = tun.recvmsg
783
- now = Time.new
784
- pack_id = data[ 0, 8 ].unpack( 'Q>' ).first
785
-
786
- if pack_id == 0
787
- ctl_num = data[ 8 ].unpack( 'C' ).first
788
-
789
- case ctl_num
790
- when PEER_ADDR
791
- return if @tun_info[ :peer_addr ] || ( addrinfo.to_sockaddr != @p2pd_addr )
792
-
793
- peer_addr = data[ 9..-1 ]
794
- puts "#{ Time.new } got peer addr #{ Addrinfo.new( peer_addr ).inspect }"
795
-
796
- @tun_info[ :peer_addr ] = peer_addr
797
- @tun_info[ :peer_at ] = now
798
- loop_punch_peer
799
- when HEARTBEAT
800
- from_addr = addrinfo.to_sockaddr
801
- return if from_addr != @tun_info[ :peer_addr ]
802
-
803
- # puts "debug1 set tun addr #{ Addrinfo.new( from_addr ).inspect }"
804
- @tun_info[ :tund_addr ] = from_addr
805
- @tun_info[ :last_recv_at ] = now
806
- when PAIRED
807
- return unless is_match_tund_addr( addrinfo )
808
-
809
- src_id, dst_port = data[ 9, 10 ].unpack( 'Q>n' )
810
-
811
- src_ext = @tun_info[ :src_exts ][ src_id ]
812
- return if src_ext.nil? || src_ext[ :dst_port ]
813
-
814
- src = src_ext[ :src ]
815
- return if src.closed?
816
-
817
- # puts "debug1 got paired #{ src_id } #{ dst_port }"
818
-
819
- if dst_port == 0
820
- set_is_closing( src )
821
- return
822
- end
823
-
824
- src_ext[ :dst_port ] = dst_port
825
- @tun_info[ :src_ids ][ dst_port ] = src_id
826
-
827
- src_info = @src_infos[ src ]
828
-
829
- src_info[ :rbuffs ].each do | _pack_id, _data |
830
- add_tun_wbuff( src_id, _pack_id, _data )
831
- end
832
- when DEST_STATUS
833
- return unless is_match_tund_addr( addrinfo )
834
-
835
- dst_port, relay_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
836
-
837
- src_id = @tun_info[ :src_ids ][ dst_port ]
838
- return unless src_id
839
-
840
- src_ext = @tun_info[ :src_exts ][ src_id ]
841
- return unless src_ext
842
-
843
- # puts "debug2 got dest status"
844
-
845
- release_wmems( src_ext, continue_src_pack_id )
846
-
847
- # 发miss
848
- if !src_ext[ :src ].closed? && ( src_ext[ :continue_dst_pack_id ] < relay_dst_pack_id )
849
- ranges = []
850
- curr_pack_id = src_ext[ :continue_dst_pack_id ] + 1
851
-
852
- src_ext[ :pieces ].keys.sort.each do | pack_id |
853
- if pack_id > curr_pack_id
854
- ranges << [ curr_pack_id, pack_id - 1 ]
855
- end
856
-
857
- curr_pack_id = pack_id + 1
858
- end
859
-
860
- if curr_pack_id <= relay_dst_pack_id
861
- ranges << [ curr_pack_id, relay_dst_pack_id ]
862
- end
863
-
864
- pack_count = 0
865
- # puts "debug1 continue/relay #{ src_ext[ :continue_dst_pack_id ] }/#{ relay_dst_pack_id } send MISS #{ ranges.size }"
866
-
867
- ranges.each do | pack_id_begin, pack_id_end |
868
- if pack_count >= BREAK_SEND_MISS
869
- puts "#{ Time.new } break send miss at #{ pack_id_begin }"
870
- break
871
- end
872
-
873
- data2 = [ 0, MISS, dst_port, pack_id_begin, pack_id_end ].pack( 'Q>CnQ>Q>' )
874
- add_tun_ctlmsg( data2 )
875
- pack_count += ( pack_id_end - pack_id_begin + 1 )
876
- end
877
- end
878
- when MISS
879
- return unless is_match_tund_addr( addrinfo )
880
-
881
- src_id, pack_id_begin, pack_id_end = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
882
-
883
- src_ext = @tun_info[ :src_exts ][ src_id ]
884
- return unless src_ext
885
-
886
- ( pack_id_begin..pack_id_end ).each do | pack_id |
887
- send_at = src_ext[ :send_ats ][ pack_id ]
888
-
889
- if send_at
890
- break if now - send_at < STATUS_INTERVAL
891
- @tun_info[ :resendings ] << [ src_id, pack_id ]
892
- end
893
- end
894
-
895
- add_write( tun )
896
- when FIN1
897
- return unless is_match_tund_addr( addrinfo )
898
-
899
- dst_port, biggest_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
900
-
901
- src_id = @tun_info[ :src_ids ][ dst_port ]
902
- return unless src_id
903
-
904
- src_ext = @tun_info[ :src_exts ][ src_id ]
905
- return unless src_ext
906
-
907
- # puts "debug1 got fin1 #{ dst_port } biggest dst pack #{ biggest_dst_pack_id } completed src pack #{ continue_src_pack_id }"
908
- src_ext[ :is_dst_closed ] = true
909
- src_ext[ :biggest_dst_pack_id ] = biggest_dst_pack_id
910
- release_wmems( src_ext, continue_src_pack_id )
911
-
912
- if ( biggest_dst_pack_id == src_ext[ :continue_dst_pack_id ] )
913
- # puts "debug1 2-1. tun recv fin1 -> all traffic received ? -> close src after write"
914
- set_is_closing( src_ext[ :src ] )
915
- end
916
- when FIN2
917
- return unless is_match_tund_addr( addrinfo )
918
-
919
- dst_port = data[ 9, 2 ].unpack( 'n' ).first
920
-
921
- src_id = @tun_info[ :src_ids ][ dst_port ]
922
- return unless src_id
923
-
924
- # puts "debug1 1-2. tun recv fin2 -> del src ext"
925
- del_src_ext( src_id )
926
- when TUND_FIN
927
- return unless is_match_tund_addr( addrinfo )
928
-
929
- puts "#{ Time.new } recv tund fin"
930
- set_is_closing( tun )
931
- end
932
-
933
- return
934
- end
935
-
936
- return unless is_match_tund_addr( addrinfo )
937
-
938
- dst_port = data[ 8, 2 ].unpack( 'n' ).first
939
-
940
- src_id = @tun_info[ :src_ids ][ dst_port ]
941
- return unless src_id
942
-
943
- src_ext = @tun_info[ :src_exts ][ src_id ]
944
- return if src_ext.nil? || src_ext[ :src ].closed?
945
- return if ( pack_id <= src_ext[ :continue_dst_pack_id ] ) || src_ext[ :pieces ].include?( pack_id )
946
-
947
- data = data[ 10..-1 ]
948
- # puts "debug2 got pack #{ pack_id }"
949
-
950
- if pack_id <= CONFUSE_UNTIL
951
- # puts "debug2 #{ data.inspect }"
952
- data = @custom.decode( data )
953
- # puts "debug1 decoded pack #{ pack_id }"
954
- end
955
-
956
- # 放进写前,跳号放碎片缓存
957
- if pack_id - src_ext[ :continue_dst_pack_id ] == 1
958
- while src_ext[ :pieces ].include?( pack_id + 1 )
959
- data << src_ext[ :pieces ].delete( pack_id + 1 )
960
- pack_id += 1
961
- end
962
-
963
- src_ext[ :continue_dst_pack_id ] = pack_id
964
- src_ext[ :last_continue_at ] = now
965
- add_src_wbuff( src_ext[ :src ], data )
966
- # puts "debug2 update continue dst pack #{ pack_id }"
967
-
968
- # 接到流量,若对面已关闭,且流量正好收全,关闭src
969
- if src_ext[ :is_dst_closed ] && ( pack_id == src_ext[ :biggest_dst_pack_id ] )
970
- # puts "debug1 2-2. tun recv traffic -> dst closed and all traffic received ? -> close src after write"
971
- set_is_closing( src_ext[ :src ] )
972
- end
973
- else
974
- src_ext[ :pieces ][ pack_id ] = data
975
- end
976
- end
977
-
978
- end
979
- end
1
+ module P2p2
2
+ class P2Worker
3
+
4
+ ##
5
+ # initialize
6
+ #
7
+ def initialize( paird_host, paird_port, title, shadow_host, shadow_port )
8
+ @paird_host = paird_host
9
+ @paird_port = paird_port
10
+ @title = title
11
+ @shadow_addr = Socket.sockaddr_in( shadow_port, shadow_host )
12
+ @reads = []
13
+ @writes = []
14
+ @roles = {} # sock => :dotr / :shadow / :ctl / :tun / :src
15
+ @src_infos = ConcurrentHash.new
16
+ @tun_infos = ConcurrentHash.new
17
+
18
+ new_a_pipe
19
+ new_a_shadow
20
+ end
21
+
22
+ ##
23
+ # looping
24
+ #
25
+ def looping
26
+ puts "#{ Time.new } looping"
27
+ loop_check_state
28
+
29
+ loop do
30
+ rs, ws = IO.select( @reads, @writes )
31
+
32
+ rs.each do | sock |
33
+ role = @roles[ sock ]
34
+
35
+ case role
36
+ when :dotr then
37
+ read_dotr( sock )
38
+ when :shadow then
39
+ read_shadow( sock )
40
+ when :src then
41
+ read_src( sock )
42
+ when :ctl then
43
+ read_ctl( sock )
44
+ when :tun then
45
+ read_tun( sock )
46
+ else
47
+ puts "#{ Time.new } read unknown role #{ role }"
48
+ close_sock( sock )
49
+ end
50
+ end
51
+
52
+ ws.each do | sock |
53
+ role = @roles[ sock ]
54
+
55
+ case role
56
+ when :tun then
57
+ write_tun( sock )
58
+ when :src then
59
+ write_src( sock )
60
+ else
61
+ puts "#{ Time.new } write unknown role #{ role }"
62
+ close_sock( sock )
63
+ end
64
+ end
65
+ end
66
+ rescue Interrupt => e
67
+ puts e.class
68
+ quit!
69
+ end
70
+
71
+ ##
72
+ # quit!
73
+ #
74
+ def quit!
75
+ # puts "debug exit"
76
+ exit
77
+ end
78
+
79
+ private
80
+
81
+ ##
82
+ # add read
83
+ #
84
+ def add_read( sock, role = nil )
85
+ return if sock.nil? || sock.closed? || @reads.include?( sock )
86
+ @reads << sock
87
+
88
+ if role then
89
+ @roles[ sock ] = role
90
+ end
91
+ end
92
+
93
+ ##
94
+ # add src rbuff
95
+ #
96
+ def add_src_rbuff( src, data )
97
+ return if src.nil? || src.closed?
98
+ src_info = @src_infos[ src ]
99
+ src_info[ :rbuff ] << data
100
+
101
+ if src_info[ :rbuff ].bytesize >= WBUFF_LIMIT then
102
+ puts "#{ Time.new } src.rbuff full"
103
+ close_src( src )
104
+ end
105
+ end
106
+
107
+ ##
108
+ # add src wbuff
109
+ #
110
+ def add_src_wbuff( src, data )
111
+ return if src.nil? || src.closed?
112
+ src_info = @src_infos[ src ]
113
+ src_info[ :wbuff ] << data
114
+ src_info[ :last_recv_at ] = Time.new
115
+ add_write( src )
116
+
117
+ if src_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
118
+ tun = src_info[ :tun ]
119
+
120
+ if tun && !tun.closed? then
121
+ puts "#{ Time.new } pause tun"
122
+ @reads.delete( tun )
123
+ tun_info = @tun_infos[ tun ]
124
+ tun_info[ :paused ] = true
125
+ end
126
+ end
127
+ end
128
+
129
+ ##
130
+ # add tun wbuff
131
+ #
132
+ def add_tun_wbuff( tun, data )
133
+ return if tun.nil? || tun.closed?
134
+ tun_info = @tun_infos[ tun ]
135
+ tun_info[ :wbuff ] << data
136
+ add_write( tun )
137
+
138
+ if tun_info[ :wbuff ].bytesize >= WBUFF_LIMIT then
139
+ src = tun_info[ :src ]
140
+
141
+ if src && !src.closed? then
142
+ puts "#{ Time.new } pause src"
143
+ @reads.delete( src )
144
+ src_info = @src_infos[ src ]
145
+ src_info[ :paused ] = true
146
+ end
147
+ end
148
+ end
149
+
150
+ ##
151
+ # add write
152
+ #
153
+ def add_write( sock )
154
+ return if sock.nil? || sock.closed? || @writes.include?( sock )
155
+ @writes << sock
156
+ end
157
+
158
+ ##
159
+ # close ctl
160
+ #
161
+ def close_ctl
162
+ return if @ctl.nil? || @ctl.closed?
163
+ close_sock( @ctl )
164
+ end
165
+
166
+ ##
167
+ # close read src
168
+ #
169
+ def close_read_src( src )
170
+ return if src.nil? || src.closed?
171
+ # puts "debug close read src"
172
+ src.close_read
173
+ @reads.delete( src )
174
+
175
+ if src.closed? then
176
+ # puts "debug src closed"
177
+ @writes.delete( src )
178
+ @roles.delete( src )
179
+ @src_infos.delete( src )
180
+ end
181
+ end
182
+
183
+ ##
184
+ # close read tun
185
+ #
186
+ def close_read_tun( tun )
187
+ return if tun.nil? || tun.closed?
188
+ # puts "debug close read tun"
189
+ tun.close_read
190
+ @reads.delete( tun )
191
+
192
+ if tun.closed? then
193
+ # puts "debug tun closed"
194
+ @writes.delete( tun )
195
+ @roles.delete( tun )
196
+ @tun_infos.delete( tun )
197
+ end
198
+ end
199
+
200
+ ##
201
+ # close sock
202
+ #
203
+ def close_sock( sock )
204
+ return if sock.nil? || sock.closed?
205
+ sock.close
206
+ @reads.delete( sock )
207
+ @writes.delete( sock )
208
+ @roles.delete( sock )
209
+ end
210
+
211
+ ##
212
+ # close src
213
+ #
214
+ def close_src( src )
215
+ return if src.nil? || src.closed?
216
+ puts "#{ Time.new } close src"
217
+ close_sock( src )
218
+ @src_infos.delete( src )
219
+ end
220
+
221
+ ##
222
+ # close tun
223
+ #
224
+ def close_tun( tun )
225
+ return if tun.nil? || tun.closed?
226
+ puts "#{ Time.new } close tun"
227
+ close_sock( tun )
228
+ @tun_infos.delete( tun )
229
+ end
230
+
231
+ ##
232
+ # close write src
233
+ #
234
+ def close_write_src( src )
235
+ return if src.nil? || src.closed?
236
+ # puts "debug close write src"
237
+ src.close_write
238
+ @writes.delete( src )
239
+
240
+ if src.closed? then
241
+ # puts "debug src closed"
242
+ @reads.delete( src )
243
+ @roles.delete( src )
244
+ @src_infos.delete( src )
245
+ end
246
+ end
247
+
248
+ ##
249
+ # close write tun
250
+ #
251
+ def close_write_tun( tun )
252
+ return if tun.nil? || tun.closed?
253
+ # puts "debug close write tun"
254
+ tun.close_write
255
+ @writes.delete( tun )
256
+
257
+ if tun.closed? then
258
+ # puts "debug tun closed"
259
+ @reads.delete( tun )
260
+ @roles.delete( tun )
261
+ @tun_infos.delete( tun )
262
+ end
263
+ end
264
+
265
+ ##
266
+ # loop check state
267
+ #
268
+ def loop_check_state
269
+ Thread.new do
270
+ loop do
271
+ sleep CHECK_STATE_INTERVAL
272
+ now = Time.new
273
+
274
+ @src_infos.select{ | src, _ | !src.closed? }.each do | src, src_info |
275
+ last_recv_at = src_info[ :last_recv_at ] || src_info[ :created_at ]
276
+ last_sent_at = src_info[ :last_sent_at ] || src_info[ :created_at ]
277
+ is_expire = ( now - last_recv_at >= EXPIRE_AFTER ) && ( now - last_sent_at >= EXPIRE_AFTER )
278
+
279
+ if is_expire then
280
+ puts "#{ Time.new } expire src"
281
+ src_info[ :closing ] = true
282
+ next_tick
283
+ elsif src_info[ :paused ] then
284
+ tun = src_info[ :tun ]
285
+
286
+ if tun && !tun.closed? then
287
+ tun_info = @tun_infos[ tun ]
288
+
289
+ if tun_info[ :wbuff ].bytesize < RESUME_BELOW then
290
+ puts "#{ Time.new } resume src"
291
+ add_read( src )
292
+ src_info[ :paused ] = false
293
+ next_tick
294
+ end
295
+ end
296
+ end
297
+ end
298
+
299
+ @tun_infos.select{ | tun, info | !tun.closed? && info[ :paused ] }.each do | tun, tun_info |
300
+ src = tun_info[ :src ]
301
+
302
+ if src && !src.closed? then
303
+ src_info = @src_infos[ src ]
304
+
305
+ if src_info[ :wbuff ].bytesize < RESUME_BELOW then
306
+ puts "#{ Time.new } resume tun"
307
+ add_read( tun )
308
+ tun_info[ :paused ] = false
309
+ next_tick
310
+ end
311
+ end
312
+ end
313
+ end
314
+ end
315
+ end
316
+
317
+ ##
318
+ # new a ctl
319
+ #
320
+ def new_a_ctl( src )
321
+ ctl = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
322
+ ctl.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
323
+
324
+ if RUBY_PLATFORM.include?( 'linux' ) then
325
+ ctl.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
326
+ end
327
+
328
+ paird_port = @paird_port + 10.times.to_a.sample
329
+ paird_addr = Socket.sockaddr_in( paird_port, @paird_host )
330
+
331
+ @ctl = ctl
332
+ @ctl_info = {
333
+ paird_addr: paird_addr,
334
+ peer_addr: nil,
335
+ src: src
336
+ }
337
+
338
+ add_read( ctl, :ctl )
339
+
340
+ puts "#{ Time.new } find #{ @title.inspect } #{ Addrinfo.new( @ctl_info[ :paird_addr ] ).inspect }"
341
+ send_title
342
+ end
343
+
344
+ ##
345
+ # new a pipe
346
+ #
347
+ def new_a_pipe
348
+ dotr, dotw = IO.pipe
349
+ @dotw = dotw
350
+ add_read( dotr, :dotr )
351
+ end
352
+
353
+ ##
354
+ # new a shadow
355
+ #
356
+ def new_a_shadow
357
+ shadow = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
358
+ shadow.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
359
+ shadow.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
360
+
361
+ if RUBY_PLATFORM.include?( 'linux' )
362
+ shadow.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
363
+ end
364
+
365
+ shadow.bind( @shadow_addr )
366
+ shadow.listen( 127 )
367
+ puts "#{ Time.new } shadow listen on #{ shadow.local_address.ip_port }"
368
+ add_read( shadow, :shadow )
369
+ end
370
+
371
+ ##
372
+ # new a tun
373
+ #
374
+ def new_a_tun
375
+ return if @ctl.nil? || @ctl.closed? || @ctl_info[ :peer_addr ].nil?
376
+ src = @ctl_info[ :src ]
377
+ return if src.nil? || src.closed?
378
+ tun = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
379
+ tun.setsockopt( Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 )
380
+ tun.bind( @ctl.local_address )
381
+
382
+ begin
383
+ tun.connect_nonblock( @ctl_info[ :peer_addr ] )
384
+ rescue IO::WaitWritable
385
+ rescue Exception => e
386
+ puts "#{ Time.new } connect peer addr #{ e.class }"
387
+ tun.close
388
+ close_ctl
389
+ return nil
390
+ end
391
+
392
+ @tun_infos[ tun ] = {
393
+ connected: false,
394
+ wbuff: '',
395
+ closing_write: false,
396
+ paused: false,
397
+ src: src
398
+ }
399
+
400
+ add_read( tun, :tun )
401
+ add_write( tun )
402
+ src_info = @src_infos[ src ]
403
+ src_info[ :tun ] = tun
404
+ src_info[ :punch_times ] += 1
405
+ puts "#{ Time.new } #{ tun.local_address.inspect } connect #{ Addrinfo.new( @ctl_info[ :peer_addr ] ).inspect } tun infos #{ @tun_infos.size }"
406
+ tun
407
+ end
408
+
409
+ ##
410
+ # next tick
411
+ #
412
+ def next_tick
413
+ @dotw.write( '.' )
414
+ end
415
+
416
+ ##
417
+ # send title
418
+ #
419
+ def send_title
420
+ begin
421
+ @ctl.sendmsg( "#{ TO }#{ @title }", 0, @ctl_info[ :paird_addr ] )
422
+ rescue Exception => e
423
+ puts "#{ Time.new } ctl sendmsg #{ e.class }"
424
+ close_ctl
425
+ end
426
+ end
427
+
428
+ ##
429
+ # set src closing write
430
+ #
431
+ def set_src_closing_write( src )
432
+ return if src.nil? || src.closed?
433
+ src_info = @src_infos[ src ]
434
+ return if src_info[ :closing_write ]
435
+ src_info[ :closing_write ] = true
436
+ add_write( src )
437
+ end
438
+
439
+ ##
440
+ # set tun closing write
441
+ #
442
+ def set_tun_closing_write( tun )
443
+ return if tun.nil? || tun.closed?
444
+ tun_info = @tun_infos[ tun ]
445
+ return if tun_info[ :closing_write ]
446
+ tun_info[ :closing_write ] = true
447
+ add_write( tun )
448
+ end
449
+
450
+ ##
451
+ # read dotr
452
+ #
453
+ def read_dotr( dotr )
454
+ dotr.read_nonblock( READ_SIZE )
455
+
456
+ @src_infos.select{ | _, info | info[ :closing ] }.keys.each do | src |
457
+ src_info = close_src( src )
458
+
459
+ if src_info then
460
+ close_tun( src_info[ :tun ] )
461
+ end
462
+ end
463
+ end
464
+
465
+ ##
466
+ # read shadow
467
+ #
468
+ def read_shadow( shadow )
469
+ begin
470
+ src, addrinfo = shadow.accept_nonblock
471
+ rescue IO::WaitReadable, Errno::EINTR => e
472
+ puts "accept #{ e.class }"
473
+ return
474
+ end
475
+
476
+ @src_infos[ src ] = {
477
+ rbuff: '',
478
+ wbuff: '',
479
+ closing_write: false,
480
+ closing: false,
481
+ paused: false,
482
+ created_at: Time.new,
483
+ last_recv_at: nil,
484
+ last_sent_at: nil,
485
+ tun: nil,
486
+ punch_times: 0
487
+ }
488
+
489
+ puts "#{ Time.new } accept a src #{ addrinfo.inspect } src infos #{ @src_infos.size }"
490
+ add_read( src, :src )
491
+ close_ctl
492
+ new_a_ctl( src )
493
+ end
494
+
495
+ ##
496
+ # read src
497
+ #
498
+ def read_src( src )
499
+ if src.closed? then
500
+ puts "#{ Time.new } read src but src closed?"
501
+ return
502
+ end
503
+
504
+ src_info = @src_infos[ src ]
505
+ tun = src_info[ :tun ]
506
+
507
+ begin
508
+ data = src.read_nonblock( READ_SIZE )
509
+ rescue Exception => e
510
+ puts "#{ Time.new } read src #{ e.class }"
511
+ close_read_src( src )
512
+ set_tun_closing_write( tun )
513
+ return
514
+ end
515
+
516
+ if tun && !tun.closed? && @tun_infos[ tun ][ :connected ] then
517
+ add_tun_wbuff( tun, data )
518
+ else
519
+ puts "#{ Time.new } tun not connected, save data to src.rbuff #{ data.inspect }"
520
+ add_src_rbuff( src, data )
521
+ end
522
+ end
523
+
524
+ ##
525
+ # read ctl
526
+ #
527
+ def read_ctl( ctl )
528
+ if ctl.closed? then
529
+ puts "#{ Time.new } read ctl but ctl closed?"
530
+ return
531
+ end
532
+
533
+ data, addrinfo, rflags, *controls = ctl.recvmsg
534
+
535
+ if @ctl_info[ :peer_addr ] then
536
+ puts "#{ Time.new } peer addr already exist"
537
+ return
538
+ end
539
+
540
+ if addrinfo.to_sockaddr != @ctl_info[ :paird_addr ] then
541
+ puts "#{ Time.new } paird addr not match #{ addrinfo.inspect } #{ Addrinfo.new( @ctl_info[ :paird_addr ] ).inspect }"
542
+ return
543
+ end
544
+
545
+ puts "#{ Time.new } read ctl #{ data.inspect }"
546
+ @ctl_info[ :peer_addr ] = data
547
+ new_a_tun
548
+ end
549
+
550
+ ##
551
+ # read tun
552
+ #
553
+ def read_tun( tun )
554
+ if tun.closed? then
555
+ puts "#{ Time.new } read tun but tun closed?"
556
+ return
557
+ end
558
+
559
+ tun_info = @tun_infos[ tun ]
560
+ src = tun_info[ :src ]
561
+
562
+ begin
563
+ data = tun.read_nonblock( READ_SIZE )
564
+ rescue Errno::ECONNREFUSED => e
565
+ src_info = @src_infos[ src ]
566
+
567
+ if src_info[ :punch_times ] >= PUNCH_LIMIT then
568
+ puts "#{ Time.new } out of limit"
569
+ close_tun( tun )
570
+ close_src( src )
571
+ return
572
+ end
573
+
574
+ puts "#{ Time.new } read tun #{ e.class } #{ src_info[ :punch_times ] }"
575
+ close_tun( tun )
576
+
577
+ unless new_a_tun then
578
+ close_src( src )
579
+ end
580
+
581
+ return
582
+ rescue Exception => e
583
+ puts "#{ Time.new } read tun #{ e.class }"
584
+ close_read_tun( tun )
585
+ set_src_closing_write( src )
586
+ return
587
+ end
588
+
589
+ add_src_wbuff( src, data )
590
+ end
591
+
592
+ ##
593
+ # write tun
594
+ #
595
+ def write_tun( tun )
596
+ if tun.closed? then
597
+ puts "#{ Time.new } write tun but tun closed?"
598
+ return
599
+ end
600
+
601
+ tun_info = @tun_infos[ tun ]
602
+ src = tun_info[ :src ]
603
+ src_info = @src_infos[ src ]
604
+
605
+ unless tun_info[ :connected ] then
606
+ puts "#{ Time.new } connected"
607
+ tun_info[ :connected ] = true
608
+
609
+ if src && !src.closed? then
610
+ tun_info[ :wbuff ] << src_info[ :rbuff ]
611
+ end
612
+ end
613
+
614
+ data = tun_info[ :wbuff ]
615
+
616
+ # 写前为空,处理关闭写
617
+ if data.empty? then
618
+ if tun_info[ :closing_write ] then
619
+ close_write_tun( tun )
620
+ else
621
+ @writes.delete( tun )
622
+ end
623
+
624
+ return
625
+ end
626
+
627
+ # 写入
628
+ begin
629
+ written = tun.write_nonblock( data )
630
+ rescue Exception => e
631
+ puts "#{ Time.new } write tun #{ e.class }"
632
+ close_write_tun( tun )
633
+ close_read_src( src )
634
+ return
635
+ end
636
+
637
+ data = data[ written..-1 ]
638
+ tun_info[ :wbuff ] = data
639
+
640
+ if src && !src.closed? then
641
+ src_info[ :last_sent_at ] = Time.new
642
+ end
643
+ end
644
+
645
+ ##
646
+ # write src
647
+ #
648
+ def write_src( src )
649
+ if src.closed? then
650
+ puts "#{ Time.new } write src but src closed?"
651
+ return
652
+ end
653
+
654
+ src_info = @src_infos[ src ]
655
+ data = src_info[ :wbuff ]
656
+
657
+ # 写前为空,处理关闭写
658
+ if data.empty? then
659
+ if src_info[ :closing_write ] then
660
+ close_write_src( src )
661
+ else
662
+ @writes.delete( src )
663
+ end
664
+
665
+ return
666
+ end
667
+
668
+ # 写入
669
+ begin
670
+ written = src.write_nonblock( data )
671
+ rescue Exception => e
672
+ puts "#{ Time.new } write src #{ e.class }"
673
+ close_write_src( src )
674
+ close_read_tun( src_info[ :tun ] )
675
+ return
676
+ end
677
+
678
+ data = data[ written..-1 ]
679
+ src_info[ :wbuff ] = data
680
+ end
681
+ end
682
+ end