p2p2 0.6.7 → 0.6.8

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a2f86bbf773a9d8c58099c2eecfb6d97ef0de25269a864d0566285ddd716d3a
4
- data.tar.gz: d1ead80d1fbbecf687ddd0e47eb68ba44813134f52a23ee0ed135fe14c13a899
3
+ metadata.gz: c2ea64b1b56f96705f33185cd1d3453aa7dca90201c959a58c945d37a8b93de6
4
+ data.tar.gz: 1531971c59bfbb7733b90fdcc6bd0360c7515bde0feabeb1f11e54a91247e90c
5
5
  SHA512:
6
- metadata.gz: 02af82e8959a69458fa5fb709386b2f4e283de4a71ccea60a0ddd2a1caf75801313f104140abe2b0394c5fdd7db46c8bbd6d7c745418e765b82c28a931221b44
7
- data.tar.gz: 632689f40841f9bf7f75cc4dd111bba6bd619b4a4c24afbbd6e28828e5ed71772c0726474db082b26e129e067f679ef8a26686280c1f7dd657b05e550d833c51
6
+ metadata.gz: 2019e957258fccf58435115404570f2d82168ca2c1edc2a5236ada506ecc3fc194353b1729d42b231f79ab61d7321dfe1c23e888484df4fd4299abc97e9a620c
7
+ data.tar.gz: 7bc57270d19f9cf5bf40c2bb460eb091ea8212302d844d3589ef10ba3853b8d22495380580b841bc0f0a72a4179acc2e8d7d1e2afcdba93f5e0b9409463cf467
@@ -2,10 +2,8 @@ module P2p2
2
2
  PACK_SIZE = 1448 # 包大小
3
3
  CHUNK_SIZE = PACK_SIZE * 1000 # 块大小
4
4
  REP2P_LIMIT = 5 # p2p重试次数。到早了另一头还没从洞里出来,会吃ECONNREFUSED,不慌,再来一发。
5
- HEARTBEAT = 1
6
- SET_TITLE = 2
7
- PAIRING = 3
8
- NEED_CHUNK = true
5
+ SET_TITLE = 1
6
+ PAIRING = 2
9
7
  CTL_CLOSE_ROOM = [ 1 ].pack( 'C' )
10
- CTL_RENEW_ROOM = [ 2 ].pack( 'C' )
8
+ CTL_CLOSE_APP = [ 2 ].pack( 'C' )
11
9
  end
@@ -17,6 +17,7 @@ module P2p2
17
17
  # title 约定的房间名
18
18
  # app_chunk_dir 文件缓存目录,缓存app来不及写的流量
19
19
  # p1_chunk_dir 文件缓存目录,缓存p1来不及写的流量
20
+ #
20
21
  def initialize( roomd_host, roomd_port, appd_host, appd_port, title, app_chunk_dir = '/tmp', p1_chunk_dir = '/tmp' )
21
22
  @roomd_sockaddr = Socket.sockaddr_in( roomd_port, roomd_host )
22
23
  @appd_sockaddr = Socket.sockaddr_in( appd_port, appd_host )
@@ -28,10 +29,9 @@ module P2p2
28
29
  @reads = []
29
30
  @writes = []
30
31
  @closings = []
31
- @renewings = []
32
32
  @roles = {} # sock => :ctlr / :room / :p1 / :app
33
33
  @infos = {}
34
- @retries = 0
34
+ @reconn_room = false
35
35
 
36
36
  ctlr, ctlw = IO.pipe
37
37
  @ctlw = ctlw
@@ -44,7 +44,7 @@ module P2p2
44
44
  def looping
45
45
  puts 'looping'
46
46
 
47
- loop_renew_room
47
+ loop_expire
48
48
 
49
49
  loop do
50
50
  rs, ws = IO.select( @reads, @writes )
@@ -86,73 +86,90 @@ module P2p2
86
86
 
87
87
  private
88
88
 
89
- def loop_renew_room
89
+ def loop_expire
90
90
  Thread.new do
91
91
  loop do
92
92
  sleep 60
93
93
 
94
94
  if Time.new - @room_info[ :updated_at ] > 600
95
95
  @mutex.synchronize do
96
- @ctlw.write( CTL_RENEW_ROOM )
96
+ @ctlw.write( CTL_CLOSE_ROOM )
97
97
  end
98
98
  end
99
99
  end
100
100
  end
101
101
  end
102
102
 
103
- def read_ctlr( sock )
104
- case sock.read( 1 )
105
- when CTL_RENEW_ROOM
106
- add_renewing( @room )
103
+ ##
104
+ # read ctlr
105
+ #
106
+ def read_ctlr( ctlr )
107
+ case ctlr.read( 1 )
108
+ when CTL_CLOSE_ROOM
109
+ unless @room.closed?
110
+ add_closing( @room )
111
+ end
107
112
  end
108
113
  end
109
114
 
110
- def read_room( sock )
115
+ ##
116
+ # read room
117
+ #
118
+ def read_room( room )
111
119
  begin
112
- data = sock.read_nonblock( PACK_SIZE )
120
+ data = room.read_nonblock( PACK_SIZE )
113
121
  rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable
114
122
  return
115
123
  rescue Errno::ECONNREFUSED, EOFError, Errno::ECONNRESET => e
116
124
  puts "read room #{ e.class } #{ Time.new }"
117
125
 
118
- if @retries >= 2
126
+ if @reconn_room
119
127
  raise e
120
128
  end
121
129
 
122
130
  sleep 5
123
- add_renewing( sock )
124
- @retries += 1
131
+ add_closing( room )
132
+ @reconn_room = true
125
133
  return
126
134
  end
127
135
 
128
- @retries = 0
129
- info = @infos[ sock ]
136
+ @reconn_room = false
137
+ info = @infos[ room ]
130
138
  info[ :p2_sockaddr ] = data
131
139
  info[ :updated_at ] = Time.new
132
140
  new_p1
133
141
  end
134
142
 
135
- def read_p1( sock )
143
+ ##
144
+ # read p1
145
+ #
146
+ def read_p1( p1 )
136
147
  begin
137
- data = sock.read_nonblock( PACK_SIZE )
148
+ data = p1.read_nonblock( PACK_SIZE )
138
149
  rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable
139
150
  return
140
151
  rescue Errno::ECONNREFUSED => e
141
- if @room_info[ :rep2p ] >= REP2P_LIMIT
152
+ if @room_info[ :renew_p1_times ] >= REP2P_LIMIT
142
153
  raise e
143
154
  end
144
155
 
145
156
  sleep 1
146
- add_renewing( sock )
147
- @room_info[ :rep2p ] += 1
157
+ add_closing( p1 )
158
+ info = @infos[ p1 ]
159
+ info[ :need_renew ] = true
160
+ @room_info[ :renew_p1_times ] += 1
148
161
  return
149
162
  rescue Exception => e
150
- add_closing( sock )
163
+ add_closing( p1 )
151
164
  return
152
165
  end
153
166
 
154
- @room_info[ :rep2p ] = 0
155
- info = @infos[ sock ]
167
+ info = @infos[ p1 ]
168
+
169
+ if info[ :app ].nil? || info[ :app ].closed?
170
+ add_closing( p1 )
171
+ return
172
+ end
156
173
 
157
174
  if info[ :need_decode ]
158
175
  len = data[ 0, 2 ].unpack( 'n' ).first
@@ -161,20 +178,29 @@ module P2p2
161
178
  info[ :need_decode ] = false
162
179
  end
163
180
 
164
- add_write( @app, data, NEED_CHUNK )
181
+ add_write( info[ :app ], data )
182
+ @room_info[ :updated_at ] = Time.new
165
183
  end
166
184
 
167
- def read_app( sock )
185
+ ##
186
+ # read app
187
+ #
188
+ def read_app( app )
168
189
  begin
169
- data = sock.read_nonblock( PACK_SIZE )
190
+ data = app.read_nonblock( PACK_SIZE )
170
191
  rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable
171
192
  return
172
193
  rescue Exception => e
173
- add_closing( sock )
194
+ add_closing( app )
174
195
  return
175
196
  end
176
197
 
177
- info = @infos[ sock ]
198
+ info = @infos[ app ]
199
+
200
+ if info[ :p1 ].nil? || info[ :p1 ].closed?
201
+ add_closing( app )
202
+ return
203
+ end
178
204
 
179
205
  if info[ :need_encode ]
180
206
  data = @hex.encode( data )
@@ -182,54 +208,62 @@ module P2p2
182
208
  info[ :need_encode ] = false
183
209
  end
184
210
 
185
- add_write( @p1, data, NEED_CHUNK )
211
+ add_write( info[ :p1 ], data )
212
+ @room_info[ :updated_at ] = Time.new
186
213
  end
187
214
 
188
- def write_room( sock )
189
- if @renewings.include?( sock )
190
- close_sock( sock )
215
+ ##
216
+ # write room
217
+ #
218
+ def write_room( room )
219
+ if @closings.include?( room )
220
+ close_sock( room )
191
221
  new_room
192
222
  return
193
223
  end
194
224
 
195
- info = @infos[ sock ]
196
- data = info[ :wbuff ]
225
+ info = @infos[ room ]
226
+ room.write( info[ :wbuff ] )
227
+ @writes.delete( room )
228
+ end
197
229
 
198
- if data.empty?
199
- @writes.delete( sock )
200
- return
201
- end
230
+ ##
231
+ # write p1
232
+ #
233
+ def write_p1( p1 )
234
+ if @closings.include?( p1 )
235
+ info = close_sock( p1 )
236
+
237
+ if info[ :need_renew ]
238
+ new_p1
239
+ return
240
+ end
202
241
 
203
- sock.write( data )
204
- info[ :wbuff ].clear
205
- end
242
+ unless info[ :app ].closed?
243
+ add_closing( info[ :app ] )
244
+ end
206
245
 
207
- def write_p1( sock )
208
- if @closings.include?( sock )
209
- close_p1
210
- return
211
- end
246
+ unless @room.closed?
247
+ add_closing( @room )
248
+ end
212
249
 
213
- if @renewings.include?( sock )
214
- close_p1
215
- new_p1
216
250
  return
217
251
  end
218
252
 
219
- info = @infos[ sock ]
253
+ info = @infos[ p1 ]
220
254
  data, from = get_buff( info )
221
255
 
222
256
  if data.empty?
223
- @writes.delete( sock )
257
+ @writes.delete( p1 )
224
258
  return
225
259
  end
226
260
 
227
261
  begin
228
- written = sock.write_nonblock( data )
262
+ written = p1.write_nonblock( data )
229
263
  rescue IO::WaitWritable, Errno::EINTR, IO::WaitReadable
230
264
  return
231
265
  rescue Exception => e
232
- add_closing( sock )
266
+ add_closing( p1 )
233
267
  return
234
268
  end
235
269
 
@@ -237,31 +271,34 @@ module P2p2
237
271
  info[ from ] = data
238
272
  end
239
273
 
240
- def write_app( sock )
241
- if @closings.include?( sock )
242
- close_sock( sock )
243
-
244
- unless @p1.closed?
245
- add_closing( @p1 )
274
+ ##
275
+ # write app
276
+ #
277
+ def write_app( app )
278
+ if @closings.include?( app )
279
+ info = close_sock( app )
280
+
281
+ unless info[ :p1 ].closed?
282
+ add_closing( info[ :p1 ] )
246
283
  end
247
284
 
248
285
  return
249
286
  end
250
287
 
251
- info = @infos[ sock ]
288
+ info = @infos[ app ]
252
289
  data, from = get_buff( info )
253
290
 
254
291
  if data.empty?
255
- @writes.delete( sock )
292
+ @writes.delete( app )
256
293
  return
257
294
  end
258
295
 
259
296
  begin
260
- written = sock.write_nonblock( data )
297
+ written = app.write_nonblock( data )
261
298
  rescue IO::WaitWritable, Errno::EINTR, IO::WaitReadable
262
299
  return
263
300
  rescue Exception => e
264
- add_closing( sock )
301
+ add_closing( app )
265
302
  return
266
303
  end
267
304
 
@@ -292,27 +329,18 @@ module P2p2
292
329
  def add_closing( sock )
293
330
  unless @closings.include?( sock )
294
331
  @reads.delete( sock )
295
- @closings << sock
332
+ @closings << sock
296
333
  end
297
334
 
298
335
  add_write( sock )
299
336
  end
300
337
 
301
- def add_renewing( sock )
302
- unless @renewings.include?( sock )
303
- @reads.delete( sock )
304
- @renewings << sock
305
- end
306
-
307
- add_write( sock )
308
- end
309
-
310
- def add_write( sock, data = nil, need_chunk = false )
338
+ def add_write( sock, data = nil )
311
339
  if data
312
340
  info = @infos[ sock ]
313
341
  info[ :wbuff ] << data
314
342
 
315
- if need_chunk && info[ :wbuff ].size >= CHUNK_SIZE
343
+ if info[ :wbuff ].size >= CHUNK_SIZE
316
344
  filename = [ info[ :filename ], info[ :chunk_seed ] ].join( '.' )
317
345
  chunk_path = File.join( info[ :chunk_dir ], filename )
318
346
  IO.binwrite( chunk_path, info[ :wbuff ] )
@@ -332,7 +360,6 @@ module P2p2
332
360
  @reads.delete( sock )
333
361
  @writes.delete( sock )
334
362
  @closings.delete( sock )
335
- @renewings.delete( sock )
336
363
  @roles.delete( sock )
337
364
  info = @infos.delete( sock )
338
365
 
@@ -348,14 +375,6 @@ module P2p2
348
375
  info
349
376
  end
350
377
 
351
- def close_p1
352
- close_sock( @p1 )
353
-
354
- unless @app.closed?
355
- add_closing( @app )
356
- end
357
- end
358
-
359
378
  def new_room
360
379
  room = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
361
380
  room.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
@@ -366,11 +385,11 @@ module P2p2
366
385
  rescue IO::WaitWritable, Errno::EINTR
367
386
  end
368
387
 
369
- bytes = @title.unpack( "C*" ).map{ | c | c.chr }.join
388
+ title = @title.unpack( "C*" ).map{ | c | c.chr }.join
370
389
  room_info = {
371
- wbuff: [ [ SET_TITLE, bytes.size ].pack( 'Cn' ), bytes ].join,
390
+ wbuff: [ [ SET_TITLE ].pack( 'C' ), title ].join,
372
391
  p2_sockaddr: nil,
373
- rep2p: 0,
392
+ renew_p1_times: 0,
374
393
  updated_at: Time.new
375
394
  }
376
395
  @room = room
@@ -393,9 +412,18 @@ module P2p2
393
412
  rescue Exception => e
394
413
  puts "connect p2 #{ e.class } #{ Time.new }"
395
414
  p1.close
415
+ add_closing( @room )
396
416
  return
397
417
  end
398
418
 
419
+ app = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
420
+ app.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
421
+
422
+ begin
423
+ app.connect_nonblock( @appd_sockaddr )
424
+ rescue IO::WaitWritable, Errno::EINTR
425
+ end
426
+
399
427
  p1_info = {
400
428
  wbuff: '',
401
429
  cache: '',
@@ -403,21 +431,10 @@ module P2p2
403
431
  chunk_dir: @p1_chunk_dir,
404
432
  chunks: [],
405
433
  chunk_seed: 0,
406
- need_decode: true
434
+ need_decode: true,
435
+ need_renew: false,
436
+ app: app
407
437
  }
408
- @p1 = p1
409
- @p1_info = p1_info
410
- @roles[ p1 ] = :p1
411
- @infos[ p1 ] = p1_info
412
- @reads << p1
413
-
414
- app = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
415
- app.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
416
-
417
- begin
418
- app.connect_nonblock( @appd_sockaddr )
419
- rescue IO::WaitWritable, Errno::EINTR
420
- end
421
438
 
422
439
  app_info = {
423
440
  wbuff: '',
@@ -426,11 +443,13 @@ module P2p2
426
443
  chunk_dir: @app_chunk_dir,
427
444
  chunks: [],
428
445
  chunk_seed: 0,
429
- need_encode: true
446
+ need_encode: true,
447
+ p1: p1
430
448
  }
431
449
 
432
- @app = app
433
- @app_info = app_info
450
+ @roles[ p1 ] = :p1
451
+ @infos[ p1 ] = p1_info
452
+ @reads << p1
434
453
  @roles[ app ] = :app
435
454
  @infos[ app ] = app_info
436
455
  @reads << app
@@ -17,6 +17,7 @@ module P2p2
17
17
  # title 约定的房间名
18
18
  # app_chunk_dir 文件缓存目录,缓存app来不及写的流量
19
19
  # p2_chunk_dir 文件缓存目录,缓存p2来不及写的流量
20
+ #
20
21
  def initialize( roomd_host, roomd_port, appd_host, appd_port, title, app_chunk_dir = '/tmp', p2_chunk_dir = '/tmp' )
21
22
  @roomd_sockaddr = Socket.sockaddr_in( roomd_port, roomd_host )
22
23
  @appd_sockaddr = Socket.sockaddr_in( appd_port, appd_host )
@@ -28,10 +29,13 @@ module P2p2
28
29
  @reads = []
29
30
  @writes = []
30
31
  @closings = []
31
- @renewings = []
32
32
  @roles = {} # sock => :appd / :app / :room / :p2
33
33
  @infos = {}
34
- @retries = 0
34
+
35
+ ctlr, ctlw = IO.pipe
36
+ @ctlw = ctlw
37
+ @roles[ ctlr ] = :ctlr
38
+ @reads << ctlr
35
39
 
36
40
  new_appd
37
41
  end
@@ -39,12 +43,16 @@ module P2p2
39
43
  def looping
40
44
  puts 'looping'
41
45
 
46
+ loop_expire
47
+
42
48
  loop do
43
49
  rs, ws = IO.select( @reads, @writes )
44
50
 
45
51
  @mutex.synchronize do
46
52
  rs.each do | sock |
47
53
  case @roles[ sock ]
54
+ when :ctlr
55
+ read_ctlr( sock )
48
56
  when :appd
49
57
  read_appd( sock )
50
58
  when :app
@@ -58,12 +66,12 @@ module P2p2
58
66
 
59
67
  ws.each do | sock |
60
68
  case @roles[ sock ]
69
+ when :app
70
+ write_app( sock )
61
71
  when :room
62
72
  write_room( sock )
63
73
  when :p2
64
74
  write_p2( sock )
65
- when :app
66
- write_app( sock )
67
75
  end
68
76
  end
69
77
  end
@@ -79,9 +87,38 @@ module P2p2
79
87
 
80
88
  private
81
89
 
82
- def read_appd( sock )
90
+ def loop_expire
91
+ Thread.new do
92
+ loop do
93
+ sleep 60
94
+
95
+ if @app && ( Time.new - @app_info[ :updated_at ] > 600 )
96
+ @mutex.synchronize do
97
+ @ctlw.write( CTL_CLOSE_APP )
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ ##
105
+ # read ctlr
106
+ #
107
+ def read_ctlr( ctlr )
108
+ case ctlr.read( 1 )
109
+ when CTL_CLOSE_APP
110
+ unless @app.closed?
111
+ add_closing( @app )
112
+ end
113
+ end
114
+ end
115
+
116
+ ##
117
+ # read appd
118
+ #
119
+ def read_appd( appd )
83
120
  begin
84
- app, addr = sock.accept_nonblock
121
+ app, _ = appd.accept_nonblock
85
122
  rescue IO::WaitReadable, Errno::EINTR
86
123
  return
87
124
  end
@@ -100,7 +137,12 @@ module P2p2
100
137
  chunks: [],
101
138
  chunk_seed: 0,
102
139
  need_encode: true,
103
- rbuff: ''
140
+ rbuff: '',
141
+ room: nil,
142
+ reconn_room: false,
143
+ p1_sockaddr: nil,
144
+ p2: nil,
145
+ renew_p2_times: 0
104
146
  }
105
147
  @app = app
106
148
  @app_info = app_info
@@ -111,17 +153,20 @@ module P2p2
111
153
  new_room
112
154
  end
113
155
 
114
- def read_app( sock )
156
+ ##
157
+ # read app
158
+ #
159
+ def read_app( app )
115
160
  begin
116
- data = sock.read_nonblock( PACK_SIZE )
161
+ data = app.read_nonblock( PACK_SIZE )
117
162
  rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable
118
163
  return
119
164
  rescue Exception => e
120
- add_closing( sock )
165
+ add_closing( app )
121
166
  return
122
167
  end
123
168
 
124
- info = @infos[ sock ]
169
+ info = @infos[ app ]
125
170
 
126
171
  if info[ :need_encode ]
127
172
  data = @hex.encode( data )
@@ -129,61 +174,75 @@ module P2p2
129
174
  info[ :need_encode ] = false
130
175
  end
131
176
 
132
- if @p2.nil?
133
- info[ :rbuff ] << data
134
- elsif @p2.closed?
135
- info[ :rbuff ] << data
136
- add_renewing( @room )
177
+ if info[ :p2 ]
178
+ add_write( info[ :p2 ], data )
137
179
  else
138
- add_write( @p2, data, NEED_CHUNK )
180
+ info[ :rbuff ] << data
139
181
  end
182
+
183
+ info[ :updated_at ] = Time.new
140
184
  end
141
185
 
142
- def read_room( sock )
186
+ ##
187
+ # read room
188
+ #
189
+ def read_room( room )
143
190
  begin
144
- data = sock.read_nonblock( PACK_SIZE )
191
+ data = room.read_nonblock( PACK_SIZE )
145
192
  rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable
146
193
  return
147
194
  rescue Errno::ECONNREFUSED, EOFError, Errno::ECONNRESET => e
148
195
  puts "read room #{ e.class } #{ Time.new }"
149
196
 
150
- if @retries >= 2
197
+ if @app_info[ :reconn_room ]
151
198
  raise e
152
199
  end
153
200
 
154
201
  sleep 5
155
- add_renewing( sock )
156
- @retries += 1
202
+ add_closing( room )
203
+ @app_info[ :reconn_room ] = true
157
204
  return
158
205
  end
159
206
 
160
- @retries = 0
161
- info = @infos[ sock ]
162
- info[ :p1_sockaddr ] = data
207
+ @app_info[ :reconn_room ] = false
208
+ @app_info[ :p1_sockaddr ] = data
209
+ @app_info[ :updated_at ] = Time.new
163
210
  new_p2
164
211
  end
165
212
 
166
- def read_p2( sock )
213
+ ##
214
+ # read p2
215
+ #
216
+ def read_p2( p2 )
167
217
  begin
168
- data = sock.read_nonblock( PACK_SIZE )
218
+ data = p2.read_nonblock( PACK_SIZE )
169
219
  rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable
170
220
  return
171
221
  rescue Errno::ECONNREFUSED => e
172
- if @room_info[ :rep2p ] >= REP2P_LIMIT
222
+ puts "read p2 #{ e.class } #{ Time.new }"
223
+
224
+ if @app_info[ :renew_p2_times ] >= REP2P_LIMIT
173
225
  raise e
174
226
  end
175
227
 
176
228
  sleep 1
177
- add_renewing( sock )
178
- @room_info[ :rep2p ] += 1
229
+ add_closing( p2 )
230
+ info = @infos[ p2 ]
231
+ info[ :need_renew ] = true
232
+ @app_info[ :renew_p2_times ] += 1
179
233
  return
180
234
  rescue Exception => e
181
- add_closing( sock )
235
+ puts "read p2 #{ e.class } #{ Time.new }"
236
+ add_closing( p2 )
237
+ return
238
+ end
239
+
240
+ if @app.nil? || @app.closed?
241
+ add_closing( p2 )
182
242
  return
183
243
  end
184
244
 
185
- @room_info[ :rep2p ] = 0
186
- info = @infos[ sock ]
245
+ info = @infos[ p2 ]
187
246
 
188
247
  if info[ :need_decode ]
189
248
  len = data[ 0, 2 ].unpack( 'n' ).first
@@ -192,54 +251,42 @@ module P2p2
192
251
  info[ :need_decode ] = false
193
252
  end
194
253
 
195
- add_write( @app, data, NEED_CHUNK )
254
+ add_write( @app, data )
255
+ @app_info[ :updated_at ] = Time.new
196
256
  end
197
257
 
198
- def write_room( sock )
199
- if @renewings.include?( sock )
200
- close_sock( sock )
201
- new_room
202
- return
203
- end
204
-
205
- info = @infos[ sock ]
206
- data = info[ :wbuff ]
207
-
208
- if data.empty?
209
- @writes.delete( sock )
210
- return
211
- end
212
-
213
- sock.write( data )
214
- info[ :wbuff ].clear
215
- end
258
+ ##
259
+ # write app
260
+ #
261
+ def write_app( app )
262
+ if @closings.include?( app )
263
+ info = close_sock( app )
264
+
265
+ if info[ :room ] && !info[ :room ].closed?
266
+ add_closing( info[ :room ] )
267
+ end
216
268
 
217
- def write_p2( sock )
218
- if @closings.include?( sock )
219
- close_p2
220
- return
221
- end
269
+ if info[ :p2 ] && !info[ :p2 ].closed?
270
+ add_closing( info[ :p2 ] )
271
+ end
222
272
 
223
- if @renewings.include?( sock )
224
- close_p2
225
- new_p2
226
273
  return
227
274
  end
228
275
 
229
- info = @infos[ sock ]
276
+ info = @infos[ app ]
230
277
  data, from = get_buff( info )
231
278
 
232
279
  if data.empty?
233
- @writes.delete( sock )
280
+ @writes.delete( app )
234
281
  return
235
282
  end
236
283
 
237
284
  begin
238
- written = sock.write_nonblock( data )
285
+ written = app.write_nonblock( data )
239
286
  rescue IO::WaitWritable, Errno::EINTR, IO::WaitReadable
240
287
  return
241
288
  rescue Exception => e
242
- add_closing( sock )
289
+ add_closing( app )
243
290
  return
244
291
  end
245
292
 
@@ -247,31 +294,58 @@ module P2p2
247
294
  info[ from ] = data
248
295
  end
249
296
 
250
- def write_app( sock )
251
- if @closings.include?( sock )
252
- close_sock( sock )
297
+ ##
298
+ # write room
299
+ #
300
+ def write_room( room )
301
+ if @closings.include?( room )
302
+ close_sock( room )
303
+
304
+ unless @app.closed?
305
+ add_closing( @app )
306
+ end
307
+
308
+ return
309
+ end
310
+
311
+ info = @infos[ room ]
312
+ room.write( info[ :wbuff ] )
313
+ @writes.delete( room )
314
+ end
315
+
316
+ ##
317
+ # write p2
318
+ #
319
+ def write_p2( p2 )
320
+ if @closings.include?( p2 )
321
+ info = close_sock( p2 )
322
+
323
+ if info[ :need_renew ]
324
+ new_p2
325
+ return
326
+ end
253
327
 
254
- unless @p2.closed?
255
- add_closing( @p2 )
328
+ unless @app_info[ :room ].closed?
329
+ add_closing( @app_info[ :room ] )
256
330
  end
257
331
 
258
332
  return
259
333
  end
260
334
 
261
- info = @infos[ sock ]
335
+ info = @infos[ p2 ]
262
336
  data, from = get_buff( info )
263
337
 
264
338
  if data.empty?
265
- @writes.delete( sock )
339
+ @writes.delete( p2 )
266
340
  return
267
341
  end
268
342
 
269
343
  begin
270
- written = sock.write_nonblock( data )
344
+ written = p2.write_nonblock( data )
271
345
  rescue IO::WaitWritable, Errno::EINTR, IO::WaitReadable
272
346
  return
273
347
  rescue Exception => e
274
- add_closing( sock )
348
+ add_closing( p2 )
275
349
  return
276
350
  end
277
351
 
@@ -302,27 +376,18 @@ module P2p2
302
376
  def add_closing( sock )
303
377
  unless @closings.include?( sock )
304
378
  @reads.delete( sock )
305
- @closings << sock
306
- end
307
-
308
- add_write( sock )
309
- end
310
-
311
- def add_renewing( sock )
312
- unless @renewings.include?( sock )
313
- @reads.delete( sock )
314
- @renewings << sock
379
+ @closings << sock
315
380
  end
316
381
 
317
382
  add_write( sock )
318
383
  end
319
384
 
320
- def add_write( sock, data = nil, need_chunk = false )
385
+ def add_write( sock, data = nil )
321
386
  if data
322
387
  info = @infos[ sock ]
323
388
  info[ :wbuff ] << data
324
389
 
325
- if need_chunk && info[ :wbuff ].size >= CHUNK_SIZE
390
+ if info[ :wbuff ].size >= CHUNK_SIZE
326
391
  filename = [ info[ :filename ], info[ :chunk_seed ] ].join( '.' )
327
392
  chunk_path = File.join( info[ :chunk_dir ], filename )
328
393
  IO.binwrite( chunk_path, info[ :wbuff ] )
@@ -342,7 +407,6 @@ module P2p2
342
407
  @reads.delete( sock )
343
408
  @writes.delete( sock )
344
409
  @closings.delete( sock )
345
- @renewings.delete( sock )
346
410
  @roles.delete( sock )
347
411
  info = @infos.delete( sock )
348
412
 
@@ -358,10 +422,6 @@ module P2p2
358
422
  info
359
423
  end
360
424
 
361
- def close_p2
362
- close_sock( @p2 )
363
- end
364
-
365
425
  def new_appd
366
426
  appd = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
367
427
  appd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
@@ -369,7 +429,6 @@ module P2p2
369
429
  appd.bind( @appd_sockaddr )
370
430
  appd.listen( 511 )
371
431
 
372
- @appd = appd
373
432
  @roles[ appd ] = :appd
374
433
  @reads << appd
375
434
  end
@@ -386,30 +445,29 @@ module P2p2
386
445
 
387
446
  bytes = @title.unpack( "C*" ).map{ | c | c.chr }.join
388
447
  room_info = {
389
- wbuff: [ [ PAIRING, bytes.size ].pack( 'Cn' ), bytes ].join,
390
- p1_sockaddr: nil,
391
- rep2p: 0
448
+ wbuff: [ [ PAIRING ].pack( 'C' ), bytes ].join
392
449
  }
393
- @room = room
394
- @room_info = room_info
395
450
  @roles[ room ] = :room
396
451
  @infos[ room ] = room_info
397
452
  @reads << room
398
453
  @writes << room
454
+ @app_info[ :room ] = room
455
+ @app_info[ :updated_at ] = Time.new
399
456
  end
400
457
 
401
458
  def new_p2
402
459
  p2 = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
403
460
  p2.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
404
461
  p2.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
405
- p2.bind( @room.local_address ) # use the hole
462
+ p2.bind( @app_info[ :room ].local_address ) # use the hole
406
463
 
407
464
  begin
408
- p2.connect_nonblock( @room_info[ :p1_sockaddr ] )
465
+ p2.connect_nonblock( @app_info[ :p1_sockaddr ] )
409
466
  rescue IO::WaitWritable, Errno::EINTR
410
467
  rescue Exception => e
411
468
  puts "connect p1 #{ e.class } #{ Time.new }"
412
469
  p2.close
470
+ add_closing( @app_info[ :room ] )
413
471
  return
414
472
  end
415
473
 
@@ -420,10 +478,9 @@ module P2p2
420
478
  chunk_dir: @p2_chunk_dir,
421
479
  chunks: [],
422
480
  chunk_seed: 0,
423
- need_decode: true
481
+ need_decode: true,
482
+ need_renew: false
424
483
  }
425
- @p2 = p2
426
- @p2_info = p2_info
427
484
  @roles[ p2 ] = :p2
428
485
  @infos[ p2 ] = p2_info
429
486
  @reads << p2
@@ -431,6 +488,8 @@ module P2p2
431
488
  unless p2_info[ :wbuff ].empty?
432
489
  @writes << p2
433
490
  end
491
+
492
+ @app_info[ :p2 ] = p2
434
493
  end
435
494
  end
436
495
  end
@@ -5,13 +5,24 @@ require 'socket'
5
5
  ##
6
6
  # P2p2::P2pd - 处于nat里的任意应用,访问处于另一个nat里的应用服务端,借助一根p2p管道。配对服务器端。
7
7
  #
8
- #```
9
- # p2pd p2pd
10
- # ^ ^
11
- # ^ ^
12
- # ssh --> p2 --> encode --> nat --> nat --> p1 --> decode --> sshd
8
+ # 1.
13
9
  #
14
- #```
10
+ # ```
11
+ # p2pd
12
+ # ^ ^
13
+ # ^ ^
14
+ # “周立波的房间” “周立波的房间”
15
+ # ^ ^
16
+ # ^ ^
17
+ # p1 --> nat --><-- nat <-- p2
18
+ #
19
+ # ```
20
+ #
21
+ # 2.
22
+ #
23
+ # ```
24
+ # ssh --> p2 --> (encode) --> p1 --> (decode) --> sshd
25
+ # ```
15
26
  #
16
27
  # usage
17
28
  # =====
@@ -37,18 +48,24 @@ module P2p2
37
48
  @reads = []
38
49
  @writes = []
39
50
  @closings = []
40
- @socks = {} # object_id => sock
41
- @pending_p1s = {} # title => room
42
- @pending_p2s = {} # title => room
43
51
  @roles = {} # sock => :roomd / :room
44
52
  @infos = {}
53
+ @rooms = {} # object_id => room
54
+ @p1s = {} # title => room
55
+ @p2s = {} # title => room
45
56
 
46
57
  ctlr, ctlw = IO.pipe
47
58
  @ctlw = ctlw
48
59
  @roles[ ctlr ] = :ctlr
49
60
  @reads << ctlr
50
61
 
51
- new_roomd
62
+ roomd = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
63
+ roomd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
64
+ roomd.bind( Socket.pack_sockaddr_in( @roomd_port, '0.0.0.0' ) )
65
+ roomd.listen( 511 )
66
+
67
+ @roles[ roomd ] = :roomd
68
+ @reads << roomd
52
69
  end
53
70
 
54
71
  def looping
@@ -93,13 +110,13 @@ module P2p2
93
110
  def loop_expire
94
111
  Thread.new do
95
112
  loop do
96
- sleep 900
113
+ sleep 3600
97
114
 
98
115
  if @infos.any?
99
116
  @mutex.synchronize do
100
117
  now = Time.new
101
118
 
102
- @infos.select{ | _, info | now - info[ :updated_at ] > 1800 }.each do | room, _ |
119
+ @infos.select{ | _, info | now - info[ :updated_at ] > 86400 }.each do | room, _ |
103
120
  @ctlw.write( [ CTL_CLOSE_ROOM, [ room.object_id ].pack( 'N' ) ].join )
104
121
  end
105
122
  end
@@ -108,11 +125,11 @@ module P2p2
108
125
  end
109
126
  end
110
127
 
111
- def read_ctlr( sock )
112
- case sock.read( 1 )
128
+ def read_ctlr( ctlr )
129
+ case ctlr.read( 1 )
113
130
  when CTL_CLOSE_ROOM
114
- room_id = sock.read( 4 ).unpack( 'N' ).first
115
- room = @socks[ room_id ]
131
+ room_id = ctlr.read( 4 ).unpack( 'N' ).first
132
+ room = @rooms[ room_id ]
116
133
 
117
134
  if room
118
135
  add_closing( room )
@@ -120,123 +137,109 @@ module P2p2
120
137
  end
121
138
  end
122
139
 
123
- def read_roomd( sock )
140
+ def read_roomd( roomd )
124
141
  begin
125
- room, addr = sock.accept_nonblock
142
+ room, addrinfo = roomd.accept_nonblock
126
143
  rescue IO::WaitReadable, Errno::EINTR
127
144
  return
128
145
  end
129
146
 
130
- @socks[ room.object_id ] = room
147
+ @rooms[ room.object_id ] = room
131
148
  @roles[ room ] = :room
132
149
  @infos[ room ] = {
133
150
  title: nil,
134
151
  wbuff: '',
135
- updated_at: Time.new,
136
- sockaddr: addr.to_sockaddr
152
+ sockaddr: addrinfo.to_sockaddr,
153
+ updated_at: Time.new
137
154
  }
138
155
  @reads << room
139
156
  end
140
157
 
141
- def read_room( sock )
158
+ def read_room( room )
142
159
  begin
143
- data = sock.read_nonblock( PACK_SIZE )
160
+ data = room.read_nonblock( PACK_SIZE )
144
161
  rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable
145
162
  return
146
163
  rescue Exception => e
147
- add_closing( sock )
164
+ add_closing( room )
148
165
  return
149
166
  end
150
167
 
151
- info = @infos[ sock ]
168
+ info = @infos[ room ]
152
169
  info[ :updated_at ] = Time.new
170
+ ctl_num = data[ 0 ].unpack( 'C' ).first
153
171
 
154
- until data.empty?
155
- ctl_num = data[ 0 ].unpack( 'C' ).first
172
+ case ctl_num
173
+ when SET_TITLE
174
+ title = data[ 1..-1 ]
156
175
 
157
- case ctl_num
158
- when HEARTBEAT
159
- data = data[ 1..-1 ]
160
- when SET_TITLE
161
- len = data[ 1, 2 ].unpack( 'n' ).first
176
+ if title.size > 255
177
+ puts 'title too long'
178
+ add_closing( room )
179
+ return
180
+ end
162
181
 
163
- if len > 255
164
- puts "title too long"
165
- add_closing( sock )
166
- return
167
- end
182
+ if @p1s.include?( title )
183
+ puts "p1 #{ title.inspect } already exist"
184
+ add_closing( room )
185
+ return
186
+ end
168
187
 
169
- title = data[ 3, len ]
170
-
171
- if @pending_p2s.include?( title )
172
- p2 = @pending_p2s[ title ]
173
- p2_info = @infos[ p2 ]
174
- add_write( sock, p2_info[ :sockaddr ] )
175
- add_write( p2, info[ :sockaddr ] )
176
- elsif @pending_p1s.include?( title )
177
- puts "pending p1 #{ title.inspect } already exist"
178
- add_closing( sock )
179
- return
180
- else
181
- @pending_p1s[ title ] = sock
182
- info[ :title ] = title
183
-
184
- begin
185
- File.open( File.join( @roomd_dir, title ), 'w' )
186
- rescue Errno::ENOENT, ArgumentError => e
187
- puts "open title path #{ e.class }"
188
- add_closing( sock )
189
- return
190
- end
191
- end
188
+ if @p2s.include?( title )
189
+ p2 = @p2s[ title ]
190
+ p2_info = @infos[ p2 ]
191
+ add_write( room, p2_info[ :sockaddr ] )
192
+ add_write( p2, info[ :sockaddr ] )
193
+ return
194
+ end
192
195
 
193
- data = data[ ( 3 + len )..-1 ]
194
- when PAIRING
195
- len = data[ 1, 2 ].unpack( 'n' ).first
196
+ begin
197
+ File.open( File.join( @roomd_dir, title ), 'w' )
198
+ rescue Errno::ENOENT, ArgumentError => e
199
+ puts "open title path #{ e.class }"
200
+ add_closing( room )
201
+ return
202
+ end
196
203
 
197
- if len > 255
198
- puts 'pairing title too long'
199
- add_closing( sock )
200
- return
201
- end
204
+ info[ :title ] = title
205
+ @p1s[ title ] = room
206
+ when PAIRING
207
+ title = data[ 1..-1 ]
202
208
 
203
- title = data[ 3, len ]
204
-
205
- if @pending_p1s.include?( title )
206
- p1 = @pending_p1s[ title ]
207
- p1_info = @infos[ p1 ]
208
- add_write( sock, p1_info[ :sockaddr ] )
209
- add_write( p1, info[ :sockaddr ] )
210
- elsif @pending_p2s.include?( title )
211
- puts "pending p2 #{ title.inspect } already exist"
212
- add_closing( sock )
213
- return
214
- else
215
- @pending_p2s[ title ] = sock
216
- info[ :title ] = title
217
- end
209
+ if title.size > 255
210
+ puts 'pairing title too long'
211
+ add_closing( room )
212
+ return
213
+ end
218
214
 
219
- data = data[ ( 3 + len )..-1 ]
215
+ if @p2s.include?( title )
216
+ puts "p2 #{ title.inspect } already exist"
217
+ add_closing( room )
218
+ return
220
219
  end
221
- end
222
- end
223
220
 
224
- def write_room( sock )
225
- if @closings.include?( sock )
226
- close_sock( sock )
227
- return
228
- end
221
+ if @p1s.include?( title )
222
+ p1 = @p1s[ title ]
223
+ p1_info = @infos[ p1 ]
224
+ add_write( room, p1_info[ :sockaddr ] )
225
+ add_write( p1, info[ :sockaddr ] )
226
+ return
227
+ end
229
228
 
230
- info = @infos[ sock ]
231
- data = info[ :wbuff ]
229
+ info[ :title ] = title
230
+ @p2s[ title ] = room
231
+ end
232
+ end
232
233
 
233
- if data.empty?
234
- @writes.delete( sock )
234
+ def write_room( room )
235
+ if @closings.include?( room )
236
+ close_room( room )
235
237
  return
236
238
  end
237
239
 
238
- sock.write( data )
239
- info[ :wbuff ].clear
240
+ info = @infos[ room ]
241
+ room.write( info[ :wbuff ] )
242
+ @writes.delete( room )
240
243
  end
241
244
 
242
245
  def add_closing( sock )
@@ -251,7 +254,7 @@ module P2p2
251
254
  def add_write( sock, data = nil )
252
255
  if data
253
256
  info = @infos[ sock ]
254
- info[ :wbuff ] << data
257
+ info[ :wbuff ] = data
255
258
  end
256
259
 
257
260
  unless @writes.include?( sock )
@@ -259,36 +262,25 @@ module P2p2
259
262
  end
260
263
  end
261
264
 
262
- def close_sock( sock )
263
- sock.close
264
- @reads.delete( sock )
265
- @writes.delete( sock )
266
- @closings.delete( sock )
267
- @socks.delete( sock.object_id )
268
- @roles.delete( sock )
269
- info = @infos.delete( sock )
265
+ def close_room( room )
266
+ room.close
267
+ @rooms.delete( room.object_id )
268
+ @reads.delete( room )
269
+ @writes.delete( room )
270
+ @closings.delete( room )
271
+ @roles.delete( room )
272
+ info = @infos.delete( room )
270
273
 
271
274
  if info && info[ :title ]
272
- @pending_p1s.delete( info[ :title ] )
273
- @pending_p2s.delete( info[ :title ] )
275
+ title_path = File.join( @roomd_dir, info[ :title ] )
274
276
 
275
- begin
276
- File.delete( File.join( @roomd_dir, info[ :title ] ) )
277
- rescue Errno::ENOENT
277
+ if File.exist?( title_path )
278
+ File.delete( title_path )
279
+ @p1s.delete( info[ :title ] )
280
+ else
281
+ @p2s.delete( info[ :title ] )
278
282
  end
279
283
  end
280
-
281
- info
282
- end
283
-
284
- def new_roomd
285
- roomd = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
286
- roomd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
287
- roomd.bind( Socket.pack_sockaddr_in( @roomd_port, '0.0.0.0' ) )
288
- roomd.listen( 511 )
289
-
290
- @roles[ roomd ] = :roomd
291
- @reads << roomd
292
284
  end
293
285
  end
294
286
  end
@@ -1,3 +1,3 @@
1
1
  module P2p2
2
- VERSION = "0.6.7"
2
+ VERSION = "0.6.8"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: p2p2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.7
4
+ version: 0.6.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - takafan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-20 00:00:00.000000000 Z
11
+ date: 2019-07-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 处于nat里的任意应用,访问处于另一个nat里的应用服务端,借助一根p2p管道。
14
14
  email: