p2p2 0.22.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 - 内网里的任意应用,访问另一个内网里的应用服务端。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,980 +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 ]
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 #{ src_id }"
104
- del_src_ext( src_id )
105
- end
106
- end
107
- end
108
-
109
- @src_infos.each do | src, src_info |
110
- if src_info[ :last_recv_at ].nil? && ( now - src_info[ :created_at ] > EXPIRE_NEW )
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[ :created_at ] > EXPIRE_NEW
123
- # no tund addr
124
- puts "#{ Time.new } expire new tun"
125
- set_is_closing( @tun )
126
- next_tick
127
- end
128
- end
129
- end
130
- end
131
- end
132
- end
133
-
134
- ##
135
- # loop check status
136
- #
137
- def loop_check_status
138
- Thread.new do
139
- loop do
140
- sleep STATUS_INTERVAL
141
-
142
- @mutex.synchronize do
143
- if @tun && !@tun.closed? && @tun_info[ :tund_addr ]
144
- need_trigger = false
145
-
146
- if @tun_info[ :src_exts ].any?
147
- now = Time.new
148
-
149
- @tun_info[ :src_exts ].each do | src_id, src_ext |
150
- if now - src_ext[ :last_continue_at ] < SEND_STATUS_UNTIL
151
- data = [ 0, SOURCE_STATUS, src_id, src_ext[ :relay_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
152
- add_tun_ctlmsg( data )
153
- need_trigger = true
154
- end
155
- end
156
- end
157
-
158
- if @tun_info[ :paused ] && ( @tun_info[ :src_exts ].map{ | _, src_ext | src_ext[ :wmems ].size }.sum < RESUME_BELOW )
159
- puts "#{ Time.new } resume tun"
160
- @tun_info[ :paused ] = false
161
- add_write( @tun )
162
- need_trigger = true
163
- end
164
-
165
- if need_trigger
166
- next_tick
167
- end
168
- end
169
- end
170
- end
171
- end
172
- end
173
-
174
- ##
175
- # loop punch peer
176
- #
177
- def loop_punch_peer
178
- Thread.new do
179
- EXPIRE_NEW.times do
180
- if @tun.closed?
181
- # puts "debug1 break loop punch peer"
182
- break
183
- end
184
-
185
- @mutex.synchronize do
186
- # puts "debug1 punch peer"
187
- add_tun_ctlmsg( pack_a_heartbeat, @tun_info[ :peer_addr ] )
188
- next_tick
189
- end
190
-
191
- sleep 1
192
- end
193
- end
194
- end
195
-
196
- ##
197
- # loop send a new source
198
- #
199
- def loop_send_a_new_source( src_ext, data )
200
- Thread.new do
201
- EXPIRE_NEW.times do
202
- if src_ext[ :src ].closed? || src_ext[ :dst_port ]
203
- # puts "debug1 break loop send a new source #{ src_ext[ :dst_port ] }"
204
- break
205
- end
206
-
207
- @mutex.synchronize do
208
- # puts "debug1 send a new source #{ data.inspect }"
209
- add_tun_ctlmsg( data )
210
- next_tick
211
- end
212
-
213
- sleep 1
214
- end
215
- end
216
- end
217
-
218
- ##
219
- # new a sdwd
220
- #
221
- def new_a_sdwd
222
- sdwd = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
223
- sdwd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
224
-
225
- if RUBY_PLATFORM.include?( 'linux' )
226
- sdwd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1 )
227
- sdwd.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
228
- end
229
-
230
- sdwd.bind( @sdwd_addr )
231
- sdwd.listen( 511 )
232
- puts "#{ Time.new } sdwd listen on #{ sdwd.local_address.ip_port }"
233
- add_read( sdwd, :sdwd )
234
- end
235
-
236
- ##
237
- # new a tun
238
- #
239
- def new_a_tun
240
- tun = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
241
- tun.bind( Socket.sockaddr_in( 0, '0.0.0.0' ) )
242
- port = tun.local_address.ip_port
243
- puts "#{ Time.new } tun bind on #{ port }"
244
-
245
- tun_info = {
246
- port: port, # 端口
247
- ctlmsgs: [], # [ to_addr, data ]
248
- wbuffs: [], # 写前缓存 [ src_id, pack_id, data ]
249
- caches: [], # 块读出缓存 [ src_id, pack_id, data ]
250
- chunks: [], # 块队列 filename
251
- spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
252
- peer_addr: 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( @room, @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
- # close src
407
- #
408
- def close_src( src )
409
- # puts "debug1 close src"
410
- close_sock( src )
411
- src_info = @src_infos.delete( src )
412
-
413
- src_info[ :chunks ].each do | filename |
414
- begin
415
- File.delete( File.join( @src_chunk_dir, filename ) )
416
- rescue Errno::ENOENT
417
- end
418
- end
419
-
420
- return if @tun.closed?
421
-
422
- src_id = src_info[ :id ]
423
- src_ext = @tun_info[ :src_exts ][ src_id ]
424
- return unless src_ext
425
-
426
- if src_ext[ :is_dst_closed ]
427
- # puts "debug1 2-3. after close src -> dst closed ? yes -> del src ext -> send fin2"
428
- del_src_ext( src_id )
429
- data = [ 0, FIN2, src_id ].pack( 'Q>CQ>' )
430
- add_tun_ctlmsg( data )
431
- else
432
- # puts "debug1 1-1. after close src -> dst closed ? no -> send fin1"
433
- data = [ 0, FIN1, src_id, src_info[ :biggest_pack_id ], src_ext[ :continue_dst_pack_id ] ].pack( 'Q>CQ>Q>Q>' )
434
- add_tun_ctlmsg( data )
435
- end
436
- end
437
-
438
- ##
439
- # close tun
440
- #
441
- def close_tun( tun )
442
- # puts "debug1 close tun"
443
- close_sock( tun )
444
-
445
- @tun_info[ :chunks ].each do | filename |
446
- begin
447
- File.delete( File.join( @tun_chunk_dir, filename ) )
448
- rescue Errno::ENOENT
449
- end
450
- end
451
-
452
- @tun_info[ :src_exts ].each{ | _, src_ext | set_is_closing( src_ext[ :src ] ) }
453
- end
454
-
455
- ##
456
- # close sock
457
- #
458
- def close_sock( sock )
459
- sock.close
460
- @reads.delete( sock )
461
- @writes.delete( sock )
462
- @roles.delete( sock )
463
- end
464
-
465
- ##
466
- # del src ext
467
- #
468
- def del_src_ext( src_id )
469
- src_ext = @tun_info[ :src_exts ].delete( src_id )
470
-
471
- if src_ext
472
- @tun_info[ :src_ids ].delete( src_ext[ :dst_port ] )
473
- end
474
- end
475
-
476
- ##
477
- # release wmems
478
- #
479
- def release_wmems( src_ext, completed_pack_id )
480
- if completed_pack_id > src_ext[ :completed_pack_id ]
481
- # puts "debug2 update completed pack #{ completed_pack_id }"
482
-
483
- pack_ids = src_ext[ :wmems ].keys.select { | pack_id | pack_id <= completed_pack_id }
484
-
485
- pack_ids.each do | pack_id |
486
- src_ext[ :wmems ].delete( pack_id )
487
- src_ext[ :send_ats ].delete( pack_id )
488
- end
489
-
490
- src_ext[ :completed_pack_id ] = completed_pack_id
491
- end
492
- end
493
-
494
- ##
495
- # next tick
496
- #
497
- def next_tick
498
- @dotw.write( '.' )
499
- end
500
-
501
- ##
502
- # write src
503
- #
504
- def write_src( src )
505
- src_info = @src_infos[ src ]
506
- data = src_info[ :cache ]
507
- from = :cache
508
-
509
- if data.empty?
510
- if src_info[ :chunks ].any?
511
- path = File.join( @src_chunk_dir, src_info[ :chunks ].shift )
512
-
513
- begin
514
- src_info[ :cache ] = data = IO.binread( path )
515
- File.delete( path )
516
- rescue Errno::ENOENT => e
517
- puts "#{ Time.new } read #{ path } #{ e.class }"
518
- close_src( src )
519
- return
520
- end
521
- else
522
- data = src_info[ :wbuff ]
523
- from = :wbuff
524
- end
525
- end
526
-
527
- if data.empty?
528
- if src_info[ :is_closing ]
529
- close_src( src )
530
- else
531
- @writes.delete( src )
532
- end
533
-
534
- return
535
- end
536
-
537
- begin
538
- written = src.write_nonblock( data )
539
- rescue IO::WaitWritable, Errno::EINTR
540
- return
541
- rescue Exception => e
542
- close_src( src )
543
- return
544
- end
545
-
546
- # puts "debug2 write src #{ written }"
547
- data = data[ written..-1 ]
548
- src_info[ from ] = data
549
- end
550
-
551
- ##
552
- # write tun
553
- #
554
- def write_tun( tun )
555
- if @tun_info[ :is_closing ]
556
- close_tun( tun )
557
- return
558
- end
559
-
560
- # 传ctlmsg
561
- while @tun_info[ :ctlmsgs ].any?
562
- to_addr, data = @tun_info[ :ctlmsgs ].first
563
-
564
- begin
565
- tun.sendmsg( data, 0, to_addr )
566
- rescue IO::WaitWritable, Errno::EINTR
567
- return
568
- rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH => e
569
- puts "#{ Time.new } #{ e.class }, close tun"
570
- close_tun( tun )
571
- return
572
- end
573
-
574
- @tun_info[ :ctlmsgs ].shift
575
- end
576
-
577
- # 重传
578
- while @tun_info[ :resendings ].any?
579
- src_id, pack_id = @tun_info[ :resendings ].first
580
- src_ext = @tun_info[ :src_exts ][ src_id ]
581
-
582
- if src_ext
583
- data = src_ext[ :wmems ][ pack_id ]
584
-
585
- if data
586
- begin
587
- tun.sendmsg( data, 0, @tun_info[ :tund_addr ] )
588
- rescue IO::WaitWritable, Errno::EINTR
589
- return
590
- rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH => e
591
- puts "#{ Time.new } #{ e.class }, close tun"
592
- close_tun( tun )
593
- return
594
- end
595
- end
596
- end
597
-
598
- @tun_info[ :resendings ].shift
599
- return
600
- end
601
-
602
- # 若写后达到上限,暂停取写前
603
- if @tun_info[ :src_exts ].map{ | _, src_ext | src_ext[ :wmems ].size }.sum >= WMEMS_LIMIT
604
- unless @tun_info[ :paused ]
605
- puts "#{ Time.new } pause tun #{ @tun_info[ :port ] }"
606
- @tun_info[ :paused ] = true
607
- end
608
-
609
- @writes.delete( tun )
610
- return
611
- end
612
-
613
- # 取写前
614
- if @tun_info[ :caches ].any?
615
- src_id, pack_id, data = @tun_info[ :caches ].first
616
- from = :caches
617
- elsif @tun_info[ :chunks ].any?
618
- path = File.join( @tun_chunk_dir, @tun_info[ :chunks ].shift )
619
-
620
- begin
621
- data = IO.binread( path )
622
- File.delete( path )
623
- rescue Errno::ENOENT => e
624
- puts "#{ Time.new } read #{ path } #{ e.class }"
625
- close_tun( tun )
626
- return
627
- end
628
-
629
- caches = []
630
-
631
- until data.empty?
632
- _src_id, _pack_id, pack_size = data[ 0, 18 ].unpack( 'Q>Q>n' )
633
- caches << [ _src_id, _pack_id, data[ 18, pack_size ] ]
634
- data = data[ ( 18 + pack_size )..-1 ]
635
- end
636
-
637
- @tun_info[ :caches ] = caches
638
- src_id, pack_id, data = caches.first
639
- from = :caches
640
- elsif @tun_info[ :wbuffs ].any?
641
- src_id, pack_id, data = @tun_info[ :wbuffs ].first
642
- from = :wbuffs
643
- else
644
- @writes.delete( tun )
645
- return
646
- end
647
-
648
- src_ext = @tun_info[ :src_exts ][ src_id ]
649
-
650
- if src_ext
651
- if pack_id <= CONFUSE_UNTIL
652
- data = @custom.encode( data )
653
- # puts "debug1 encoded pack #{ pack_id }"
654
- end
655
-
656
- data = [ [ pack_id, src_id ].pack( 'Q>Q>' ), data ].join
657
-
658
- begin
659
- tun.sendmsg( data, 0, @tun_info[ :tund_addr ] )
660
- rescue IO::WaitWritable, Errno::EINTR
661
- return
662
- rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH => e
663
- puts "#{ Time.new } #{ e.class }, close tun"
664
- close_tun( tun )
665
- return
666
- end
667
-
668
- # puts "debug2 written pack #{ pack_id }"
669
- now = Time.new
670
- src_ext[ :relay_pack_id ] = pack_id
671
- src_ext[ :wmems ][ pack_id ] = data
672
- src_ext[ :send_ats ][ pack_id ] = now
673
- src_ext[ :last_continue_at ] = now
674
- end
675
-
676
- @tun_info[ from ].shift
677
- end
678
-
679
- ##
680
- # read dotr
681
- #
682
- def read_dotr( dotr )
683
- dotr.read( 1 )
684
- end
685
-
686
- ##
687
- # read sdwd
688
- #
689
- def read_sdwd( sdwd )
690
- begin
691
- src, addrinfo = sdwd.accept_nonblock
692
- rescue IO::WaitReadable, Errno::EINTR
693
- return
694
- end
695
-
696
- id = rand( ( 2 ** 64 ) - 1 ) + 1
697
- # puts "debug1 accept a src #{ addrinfo.inspect } #{ id }"
698
-
699
- @src_infos[ src ] = {
700
- id: id, # id
701
- biggest_pack_id: 0, # 最大包号码
702
- rbuffs: [], # p1端dst未准备好,暂存流量 [ pack_id, data ]
703
- wbuff: '', # 写前
704
- cache: '', # 块读出缓存
705
- chunks: [], # 块队列,写前达到块大小时结一个块 filename
706
- spring: 0, # 块后缀,结块时,如果块队列不为空,则自增,为空,则置为0
707
- created_at: Time.new, # 创建时间
708
- last_recv_at: nil, # 上一次收到流量的时间,过期关闭
709
- is_closing: false # 是否准备关闭
710
- }
711
-
712
- add_read( src, :src )
713
-
714
- if @tun.nil? || @tun.closed?
715
- new_a_tun
716
- end
717
-
718
- src_ext = {
719
- src: src, # src
720
- dst_port: nil, # p1端dst端口
721
- wmems: {}, # 写后 pack_id => data
722
- send_ats: {}, # 上一次发出时间 pack_id => send_at
723
- relay_pack_id: 0, # 转发到几
724
- continue_dst_pack_id: 0, # 收到几
725
- pieces: {}, # 跳号包 dst_pack_id => data
726
- is_dst_closed: false, # dst是否已关闭
727
- biggest_dst_pack_id: 0, # dst最大包号码
728
- completed_pack_id: 0, # 完成到几(对面收到几)
729
- last_continue_at: Time.new # 创建,或者上一次收到连续流量,或者发出新包的时间
730
- }
731
-
732
- @tun_info[ :src_exts ][ id ] = src_ext
733
- data = [ 0, A_NEW_SOURCE, id ].pack( 'Q>CQ>' )
734
- loop_send_a_new_source( src_ext, data )
735
- end
736
-
737
- ##
738
- # read src
739
- #
740
- def read_src( src )
741
- begin
742
- data = src.read_nonblock( PACK_SIZE )
743
- rescue IO::WaitReadable, Errno::EINTR
744
- return
745
- rescue Exception => e
746
- # puts "debug1 read src #{ e.class }"
747
- set_is_closing( src )
748
- return
749
- end
750
-
751
- # puts "debug2 read src #{ data.inspect }"
752
- src_info = @src_infos[ src ]
753
- src_info[ :last_recv_at ] = Time.new
754
- src_id = src_info[ :id ]
755
- src_ext = @tun_info[ :src_exts ][ src_id ]
756
-
757
- unless src_ext
758
- # puts "debug1 not found src ext"
759
- set_is_closing( src )
760
- return
761
- end
762
-
763
- if @tun.closed?
764
- puts "#{ Time.new } tun closed, close src"
765
- set_is_closing( src )
766
- return
767
- end
768
-
769
- pack_id = src_info[ :biggest_pack_id ] + 1
770
- src_info[ :biggest_pack_id ] = pack_id
771
-
772
- if src_ext[ :dst_port ]
773
- add_tun_wbuff( src_info[ :id ], pack_id, data )
774
- else
775
- # puts "debug1 p1 dst not ready, save data to src rbuff"
776
- src_info[ :rbuffs ] << [ pack_id, data ]
777
- end
778
- end
779
-
780
- ##
781
- # read tun
782
- #
783
- def read_tun( tun )
784
- data, addrinfo, rflags, *controls = tun.recvmsg
785
- now = Time.new
786
- pack_id = data[ 0, 8 ].unpack( 'Q>' ).first
787
-
788
- if pack_id == 0
789
- ctl_num = data[ 8 ].unpack( 'C' ).first
790
-
791
- case ctl_num
792
- when PEER_ADDR
793
- return if @tun_info[ :peer_addr ] || ( addrinfo.to_sockaddr != @p2pd_addr )
794
-
795
- peer_addr = data[ 9..-1 ]
796
- puts "#{ Time.new } got peer addr #{ Addrinfo.new( peer_addr ).inspect }"
797
-
798
- @tun_info[ :peer_addr ] = peer_addr
799
- loop_punch_peer
800
- when HEARTBEAT
801
- from_addr = addrinfo.to_sockaddr
802
- return if from_addr != @tun_info[ :peer_addr ]
803
-
804
- # puts "debug1 set tun addr #{ Addrinfo.new( from_addr ).inspect }"
805
- @tun_info[ :tund_addr ] = from_addr
806
- @tun_info[ :last_recv_at ] = now
807
- when PAIRED
808
- return unless is_match_tund_addr( addrinfo )
809
-
810
- src_id, dst_port = data[ 9, 10 ].unpack( 'Q>n' )
811
-
812
- src_ext = @tun_info[ :src_exts ][ src_id ]
813
- return if src_ext.nil? || src_ext[ :dst_port ]
814
-
815
- src = src_ext[ :src ]
816
- return if src.closed?
817
-
818
- # puts "debug1 got paired #{ src_id } #{ dst_port }"
819
-
820
- if dst_port == 0
821
- set_is_closing( src )
822
- return
823
- end
824
-
825
- src_ext[ :dst_port ] = dst_port
826
- @tun_info[ :src_ids ][ dst_port ] = src_id
827
-
828
- src_info = @src_infos[ src ]
829
-
830
- src_info[ :rbuffs ].each do | _pack_id, _data |
831
- add_tun_wbuff( src_id, _pack_id, _data )
832
- end
833
- when DEST_STATUS
834
- return unless is_match_tund_addr( addrinfo )
835
-
836
- dst_port, relay_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
837
-
838
- src_id = @tun_info[ :src_ids ][ dst_port ]
839
- return unless src_id
840
-
841
- src_ext = @tun_info[ :src_exts ][ src_id ]
842
- return unless src_ext
843
-
844
- # puts "debug2 got dest status"
845
-
846
- release_wmems( src_ext, continue_src_pack_id )
847
-
848
- # 发miss
849
- if !src_ext[ :src ].closed? && ( src_ext[ :continue_dst_pack_id ] < relay_dst_pack_id )
850
- ranges = []
851
- curr_pack_id = src_ext[ :continue_dst_pack_id ] + 1
852
-
853
- src_ext[ :pieces ].keys.sort.each do | pack_id |
854
- if pack_id > curr_pack_id
855
- ranges << [ curr_pack_id, pack_id - 1 ]
856
- end
857
-
858
- curr_pack_id = pack_id + 1
859
- end
860
-
861
- if curr_pack_id <= relay_dst_pack_id
862
- ranges << [ curr_pack_id, relay_dst_pack_id ]
863
- end
864
-
865
- pack_count = 0
866
- # puts "debug1 continue/relay #{ src_ext[ :continue_dst_pack_id ] }/#{ relay_dst_pack_id } send MISS #{ ranges.size }"
867
-
868
- ranges.each do | pack_id_begin, pack_id_end |
869
- if pack_count >= BREAK_SEND_MISS
870
- puts "#{ Time.new } break send miss at #{ pack_id_begin }"
871
- break
872
- end
873
-
874
- data2 = [ 0, MISS, dst_port, pack_id_begin, pack_id_end ].pack( 'Q>CnQ>Q>' )
875
- add_tun_ctlmsg( data2 )
876
- pack_count += ( pack_id_end - pack_id_begin + 1 )
877
- end
878
- end
879
- when MISS
880
- return unless is_match_tund_addr( addrinfo )
881
-
882
- src_id, pack_id_begin, pack_id_end = data[ 9, 24 ].unpack( 'Q>Q>Q>' )
883
-
884
- src_ext = @tun_info[ :src_exts ][ src_id ]
885
- return unless src_ext
886
-
887
- ( pack_id_begin..pack_id_end ).each do | pack_id |
888
- send_at = src_ext[ :send_ats ][ pack_id ]
889
-
890
- if send_at
891
- break if now - send_at < STATUS_INTERVAL
892
- @tun_info[ :resendings ] << [ src_id, pack_id ]
893
- end
894
- end
895
-
896
- add_write( tun )
897
- when FIN1
898
- return unless is_match_tund_addr( addrinfo )
899
-
900
- dst_port, biggest_dst_pack_id, continue_src_pack_id = data[ 9, 18 ].unpack( 'nQ>Q>' )
901
-
902
- src_id = @tun_info[ :src_ids ][ dst_port ]
903
- return unless src_id
904
-
905
- src_ext = @tun_info[ :src_exts ][ src_id ]
906
- return unless src_ext
907
-
908
- # puts "debug1 got fin1 #{ dst_port } biggest dst pack #{ biggest_dst_pack_id } completed src pack #{ continue_src_pack_id }"
909
- src_ext[ :is_dst_closed ] = true
910
- src_ext[ :biggest_dst_pack_id ] = biggest_dst_pack_id
911
- release_wmems( src_ext, continue_src_pack_id )
912
-
913
- if ( biggest_dst_pack_id == src_ext[ :continue_dst_pack_id ] )
914
- # puts "debug1 2-1. tun recv fin1 -> all traffic received ? -> close src after write"
915
- set_is_closing( src_ext[ :src ] )
916
- end
917
- when FIN2
918
- return unless is_match_tund_addr( addrinfo )
919
-
920
- dst_port = data[ 9, 2 ].unpack( 'n' ).first
921
-
922
- src_id = @tun_info[ :src_ids ][ dst_port ]
923
- return unless src_id
924
-
925
- # puts "debug1 1-2. tun recv fin2 -> del src ext"
926
- del_src_ext( src_id )
927
- when TUND_FIN
928
- return unless is_match_tund_addr( addrinfo )
929
-
930
- puts "#{ Time.new } recv tund fin"
931
- set_is_closing( tun )
932
- end
933
-
934
- return
935
- end
936
-
937
- return unless is_match_tund_addr( addrinfo )
938
-
939
- dst_port = data[ 8, 2 ].unpack( 'n' ).first
940
-
941
- src_id = @tun_info[ :src_ids ][ dst_port ]
942
- return unless src_id
943
-
944
- src_ext = @tun_info[ :src_exts ][ src_id ]
945
- return if src_ext.nil? || src_ext[ :src ].closed?
946
- return if ( pack_id <= src_ext[ :continue_dst_pack_id ] ) || src_ext[ :pieces ].include?( pack_id )
947
-
948
- data = data[ 10..-1 ]
949
- # puts "debug2 got pack #{ pack_id }"
950
-
951
- if pack_id <= CONFUSE_UNTIL
952
- # puts "debug2 #{ data.inspect }"
953
- data = @custom.decode( data )
954
- # puts "debug1 decoded pack #{ pack_id }"
955
- end
956
-
957
- # 放进写前,跳号放碎片缓存
958
- if pack_id - src_ext[ :continue_dst_pack_id ] == 1
959
- while src_ext[ :pieces ].include?( pack_id + 1 )
960
- data << src_ext[ :pieces ].delete( pack_id + 1 )
961
- pack_id += 1
962
- end
963
-
964
- src_ext[ :continue_dst_pack_id ] = pack_id
965
- src_ext[ :last_continue_at ] = now
966
- add_src_wbuff( src_ext[ :src ], data )
967
- # puts "debug2 update continue dst pack #{ pack_id }"
968
-
969
- # 接到流量,若对面已关闭,且流量正好收全,关闭src
970
- if src_ext[ :is_dst_closed ] && ( pack_id == src_ext[ :biggest_dst_pack_id ] )
971
- # puts "debug1 2-2. tun recv traffic -> dst closed and all traffic received ? -> close src after write"
972
- set_is_closing( src_ext[ :src ] )
973
- end
974
- else
975
- src_ext[ :pieces ][ pack_id ] = data
976
- end
977
- end
978
-
979
- end
980
- 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