p2p2 0.6.7 → 0.6.8

Sign up to get free protection for your applications and to get access to all the features.
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: