p2p2 0.6.3 → 0.6.4

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: 304436e9d7374bc6e93585c3a5eb19e9609de9781847893b86d6c3d4743de621
4
- data.tar.gz: 5fe0577da9088b012a45e48637b867bb0e5a9e008bc7e16d4365dc324a3a42e1
3
+ metadata.gz: ca1bca606c23b34a5ee3a3f73b8e0764f8f965be5724a7e8fafd478c449c5d37
4
+ data.tar.gz: 2afdaf91bc5df9b534d322c1b1e3d46588aeff0369a87badf44e575f60d39c7b
5
5
  SHA512:
6
- metadata.gz: 40543a3591a792096d3b663deb762132fbf15f09c7cc7df2c342e97d1a2aab566a5744bf616005e0a3e3eae15c6479adbfd270ed628145373c6b4354e7790506
7
- data.tar.gz: 730b27755bdd1033e2310ae86f3dab1f6b8e25c2bc42c4ceaa109e2c03cdd2728e64aab553e49abc63f58dfee3befd55c29df4b52f07c6e9ed25b0790790b26a
6
+ metadata.gz: 57e9f9faebd08006a37d7a71529bc2db8b6f445011717652f23a66b5fbe984bdb36e857cc8c379d1dbbba58dda5f20031f9f59083bca11d357c3a471ce7a2af0
7
+ data.tar.gz: b2610f153384a3b6eb4bcfd474072cabb7a95e08bbc1f1340a54c45ad1cab5406cdf533ce0034a244e7085b4542890dba7bcacd4988897f17b835b62978d2630
@@ -1,6 +1,6 @@
1
- require "p2p2/version"
2
-
3
- module P2p2
4
- class Error < StandardError; end
5
- # Your code goes here...
6
- end
1
+ require "p2p2/version"
2
+
3
+ module P2p2
4
+ class Error < StandardError; end
5
+ # Your code goes here...
6
+ end
@@ -1,10 +1,10 @@
1
- module P2p2
2
- PACK_SIZE = 1448 # 包大小
3
- CHUNK_SIZE = PACK_SIZE * 1000 # 块大小
4
- REP2P_LIMIT = 5 # p2p重试次数。到早了另一头还没从洞里出来,会吃ECONNREFUSED,不慌,再来一发。
5
- HEARTBEAT = 1
6
- SET_TITLE = 2
7
- PAIRING = 3
8
- NEED_CHUNK = true
9
- NEED_RENEW = true
10
- end
1
+ module P2p2
2
+ PACK_SIZE = 1448 # 包大小
3
+ CHUNK_SIZE = PACK_SIZE * 1000 # 块大小
4
+ REP2P_LIMIT = 5 # p2p重试次数。到早了另一头还没从洞里出来,会吃ECONNREFUSED,不慌,再来一发。
5
+ HEARTBEAT = 1
6
+ SET_TITLE = 2
7
+ PAIRING = 3
8
+ NEED_CHUNK = true
9
+ NEED_RENEW = true
10
+ end
@@ -1,413 +1,410 @@
1
- require 'p2p2/head'
2
- require 'p2p2/hex'
3
- require 'p2p2/version'
4
- require 'socket'
5
-
6
- ##
7
- # P2p2::P1 - 处于各自nat里的两端p2p。p1端。
8
- #
9
- module P2p2
10
- class P1
11
-
12
- ##
13
- # roomd_host 匹配服务器ip
14
- # roomd_port 匹配服务器端口
15
- # appd_host 任意的一个应用的ip
16
- # appd_port 应用端口
17
- # title 约定的房间名
18
- # app_chunk_dir 文件缓存目录,缓存app来不及写的流量
19
- # p1_chunk_dir 文件缓存目录,缓存p1来不及写的流量
20
- def initialize( roomd_host, roomd_port, appd_host, appd_port, title, app_chunk_dir = '/tmp', p1_chunk_dir = '/tmp' )
21
- @roomd_sockaddr = Socket.sockaddr_in( roomd_port, roomd_host )
22
- @appd_sockaddr = Socket.sockaddr_in( appd_port, appd_host )
23
- @title = title
24
- @app_chunk_dir = app_chunk_dir
25
- @p1_chunk_dir = p1_chunk_dir
26
- @hex = P2p2::Hex.new
27
- @mutex = Mutex.new
28
- @roles = {} # sock => :room / :p1 / :app
29
- @infos = {}
30
- @closings = {} # sock => need_renew
31
- @reads = []
32
- @writes = []
33
- @is_renew = false
34
-
35
- new_room
36
- end
37
-
38
- def looping
39
- puts 'looping'
40
-
41
- loop_heartbeat
42
-
43
- loop do
44
- rs, ws = IO.select( @reads, @writes )
45
-
46
- @mutex.synchronize do
47
- rs.each do | sock |
48
- case @roles[ sock ]
49
- when :room
50
- read_room( sock )
51
- when :p1
52
- read_p1( sock )
53
- when :app
54
- read_app( sock )
55
- end
56
- end
57
-
58
- ws.each do | sock |
59
- case @roles[ sock ]
60
- when :room
61
- write_room( sock )
62
- when :p1
63
- write_p1( sock )
64
- when :app
65
- write_app( sock )
66
- end
67
- end
68
- end
69
- end
70
- rescue Interrupt => e
71
- puts e.class
72
- quit!
73
- end
74
-
75
- def quit!
76
- exit
77
- end
78
-
79
- private
80
-
81
- def loop_heartbeat
82
- Thread.new do
83
- loop do
84
- sleep 59
85
-
86
- @mutex.synchronize do
87
- @room.write( [ HEARTBEAT ].pack( 'C' ) )
88
- end
89
- end
90
- end
91
- end
92
-
93
- def read_room( sock )
94
- begin
95
- data = sock.read_nonblock( PACK_SIZE )
96
- rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable => e
97
- return
98
- rescue Errno::ECONNREFUSED, EOFError, Errno::ECONNRESET => e
99
- puts "read room #{ e.class } #{ Time.new }"
100
-
101
- if @is_renew
102
- raise e
103
- end
104
-
105
- add_closing( sock )
106
- return
107
- end
108
-
109
- @is_renew = false
110
- info = @infos[ sock ]
111
- info[ :p2_sockaddr ] = data
112
- new_p1
113
- end
114
-
115
- def read_p1( sock )
116
- begin
117
- data = sock.read_nonblock( PACK_SIZE )
118
- rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable => e
119
- return
120
- rescue Errno::ECONNREFUSED => e
121
- if @room_info[ :rep2p ] >= REP2P_LIMIT
122
- raise e
123
- end
124
-
125
- add_closing( sock, NEED_RENEW )
126
- return
127
- rescue Exception => e
128
- add_closing( sock )
129
- return
130
- end
131
-
132
- unless @app
133
- @room_info[ :rep2p ] = 0
134
- app = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
135
- app.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
136
-
137
- begin
138
- app.connect_nonblock( @appd_sockaddr )
139
- rescue IO::WaitWritable, Errno::EINTR
140
- end
141
-
142
- app_info = {
143
- wbuff: '',
144
- cache: '',
145
- filename: [ Process.pid, app.object_id ].join( '-' ),
146
- chunk_dir: @app_chunk_dir,
147
- chunks: [],
148
- chunk_seed: 0,
149
- p1: sock,
150
- need_encode: true
151
- }
152
-
153
- @app = app
154
- @app_info = app_info
155
- @roles[ app ] = :app
156
- @infos[ app ] = app_info
157
- @reads << app
158
- end
159
-
160
- info = @infos[ sock ]
161
-
162
- if info[ :need_decode ]
163
- len = data[ 0, 2 ].unpack( 'n' ).first
164
- head = @hex.decode( data[ 2, len ] )
165
- data = head + data[ ( 2 + len )..-1 ]
166
- info[ :need_decode ] = false
167
- end
168
-
169
- add_write( @app, data, NEED_CHUNK )
170
- end
171
-
172
- def read_app( sock )
173
- begin
174
- data = sock.read_nonblock( PACK_SIZE )
175
- rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable => e
176
- return
177
- rescue Exception => e
178
- add_closing( sock )
179
- return
180
- end
181
-
182
- info = @infos[ sock ]
183
-
184
- if info[ :need_encode ]
185
- data = @hex.encode( data )
186
- data = [ [ data.size ].pack( 'n' ), data ].join
187
- info[ :need_encode ] = false
188
- end
189
-
190
- add_write( @p1, data, NEED_CHUNK )
191
- end
192
-
193
- def write_room( sock )
194
- if @closings.include?( sock )
195
- close_sock( sock )
196
- sleep 5
197
- new_room
198
- @is_renew = true
199
- @closings.delete( sock )
200
-
201
- return
202
- end
203
-
204
- info = @infos[ sock ]
205
- data = info[ :wbuff ]
206
-
207
- if data.empty?
208
- @writes.delete( sock )
209
- return
210
- end
211
-
212
- sock.write( data )
213
- info[ :wbuff ].clear
214
- end
215
-
216
- def write_p1( sock )
217
- if @closings.include?( sock )
218
- close_sock( sock )
219
- @p1 = nil
220
-
221
- if @app && !@app.closed?
222
- add_closing( @app )
223
- end
224
-
225
- need_renew = @closings.delete( sock )
226
-
227
- if need_renew
228
- sleep 1
229
- new_p1
230
- @room_info[ :rep2p ] += 1
231
- end
232
-
233
- return
234
- end
235
-
236
- info = @infos[ sock ]
237
- data, from = get_buff( info )
238
-
239
- if data.empty?
240
- @writes.delete( sock )
241
- return
242
- end
243
-
244
- begin
245
- written = sock.write_nonblock( data )
246
- rescue IO::WaitWritable, Errno::EINTR, IO::WaitReadable
247
- return
248
- rescue Exception => e
249
- add_closing( sock )
250
- return
251
- end
252
-
253
- data = data[ written..-1 ]
254
- info[ from ] = data
255
- end
256
-
257
- def write_app( sock )
258
- if @closings.include?( sock )
259
- close_sock( sock )
260
- @app = nil
261
-
262
- if @p1 && !@p1.closed?
263
- add_closing( @p1 )
264
- end
265
-
266
- @closings.delete( sock )
267
- return
268
- end
269
-
270
- info = @infos[ sock ]
271
- data, from = get_buff( info )
272
-
273
- if data.empty?
274
- @writes.delete( sock )
275
- return
276
- end
277
-
278
- begin
279
- written = sock.write_nonblock( data )
280
- rescue IO::WaitWritable, Errno::EINTR, IO::WaitReadable
281
- return
282
- rescue Exception => e
283
- add_closing( sock )
284
- return
285
- end
286
-
287
- data = data[ written..-1 ]
288
- info[ from ] = data
289
- end
290
-
291
- def get_buff( info )
292
- data, from = info[ :cache ], :cache
293
-
294
- if data.empty?
295
- if info[ :chunks ].any?
296
- path = File.join( info[ :chunk_dir ], info[ :chunks ].shift )
297
- data = info[ :cache ] = IO.binread( path )
298
-
299
- begin
300
- File.delete( path )
301
- rescue Errno::ENOENT
302
- end
303
- else
304
- data, from = info[ :wbuff ], :wbuff
305
- end
306
- end
307
-
308
- [ data, from ]
309
- end
310
-
311
- def add_closing( sock, need_renew = false )
312
- unless @closings.include?( sock )
313
- @closings[ sock ] = need_renew
314
- end
315
-
316
- add_write( sock )
317
- end
318
-
319
- def add_write( sock, data = nil, need_chunk = false )
320
- if data
321
- info = @infos[ sock ]
322
- info[ :wbuff ] << data
323
-
324
- if need_chunk && info[ :wbuff ].size >= CHUNK_SIZE
325
- filename = [ info[ :filename ], info[ :chunk_seed ] ].join( '.' )
326
- chunk_path = File.join( info[ :chunk_dir ], filename )
327
- IO.binwrite( chunk_path, info[ :wbuff ] )
328
- info[ :chunks ] << filename
329
- info[ :chunk_seed ] += 1
330
- info[ :wbuff ].clear
331
- end
332
- end
333
-
334
- unless @writes.include?( sock )
335
- @writes << sock
336
- end
337
- end
338
-
339
- def close_sock( sock )
340
- sock.close
341
- @roles.delete( sock )
342
- @reads.delete( sock )
343
- @writes.delete( sock )
344
- info = @infos.delete( sock )
345
-
346
- if info && info[ :chunks ]
347
- info[ :chunks ].each do | filename |
348
- begin
349
- File.delete( File.join( info[ :chunk_dir ], filename ) )
350
- rescue Errno::ENOENT
351
- end
352
- end
353
- end
354
-
355
- info
356
- end
357
-
358
- def new_room
359
- room = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
360
- room.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
361
- room.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
362
-
363
- begin
364
- room.connect_nonblock( @roomd_sockaddr )
365
- rescue IO::WaitWritable, Errno::EINTR
366
- end
367
-
368
- bytes = @title.unpack( "C*" ).map{ | c | c.chr }.join
369
- room_info = {
370
- wbuff: [ [ SET_TITLE, bytes.size ].pack( 'Cn' ), bytes ].join,
371
- p2_sockaddr: nil,
372
- rep2p: 0
373
- }
374
- @room = room
375
- @room_info = room_info
376
- @roles[ room ] = :room
377
- @infos[ room ] = room_info
378
- @reads << room
379
- @writes << room
380
- end
381
-
382
- def new_p1
383
- p1 = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
384
- p1.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
385
- p1.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
386
- p1.bind( @room.local_address ) # use the hole
387
-
388
- begin
389
- p1.connect_nonblock( @room_info[ :p2_sockaddr ] )
390
- rescue IO::WaitWritable, Errno::EINTR
391
- rescue Exception => e
392
- puts "connect p2 #{ e.class } #{ Time.new }"
393
- p1.close
394
- return
395
- end
396
-
397
- p1_info = {
398
- wbuff: '',
399
- cache: '',
400
- filename: [ Process.pid, p1.object_id ].join( '-' ),
401
- chunk_dir: @p1_chunk_dir,
402
- chunks: [],
403
- chunk_seed: 0,
404
- need_decode: true
405
- }
406
- @p1 = p1
407
- @p1_info = p1_info
408
- @roles[ p1 ] = :p1
409
- @infos[ p1 ] = p1_info
410
- @reads << p1
411
- end
412
- end
413
- end
1
+ require 'p2p2/head'
2
+ require 'p2p2/hex'
3
+ require 'p2p2/version'
4
+ require 'socket'
5
+
6
+ ##
7
+ # P2p2::P1 - 处于各自nat里的两端p2p。p1端。
8
+ #
9
+ module P2p2
10
+ class P1
11
+
12
+ ##
13
+ # roomd_host 匹配服务器ip
14
+ # roomd_port 匹配服务器端口
15
+ # appd_host 任意的一个应用的ip
16
+ # appd_port 应用端口
17
+ # title 约定的房间名
18
+ # app_chunk_dir 文件缓存目录,缓存app来不及写的流量
19
+ # p1_chunk_dir 文件缓存目录,缓存p1来不及写的流量
20
+ def initialize( roomd_host, roomd_port, appd_host, appd_port, title, app_chunk_dir = '/tmp', p1_chunk_dir = '/tmp' )
21
+ @roomd_sockaddr = Socket.sockaddr_in( roomd_port, roomd_host )
22
+ @appd_sockaddr = Socket.sockaddr_in( appd_port, appd_host )
23
+ @title = title
24
+ @app_chunk_dir = app_chunk_dir
25
+ @p1_chunk_dir = p1_chunk_dir
26
+ @hex = P2p2::Hex.new
27
+ @mutex = Mutex.new
28
+ @roles = {} # sock => :room / :p1 / :app
29
+ @infos = {}
30
+ @closings = {} # sock => need_renew
31
+ @reads = []
32
+ @writes = []
33
+ @is_renew = false
34
+
35
+ new_room
36
+ end
37
+
38
+ def looping
39
+ puts 'looping'
40
+
41
+ loop_heartbeat
42
+
43
+ loop do
44
+ rs, ws = IO.select( @reads, @writes )
45
+
46
+ @mutex.synchronize do
47
+ rs.each do | sock |
48
+ case @roles[ sock ]
49
+ when :room
50
+ read_room( sock )
51
+ when :p1
52
+ read_p1( sock )
53
+ when :app
54
+ read_app( sock )
55
+ end
56
+ end
57
+
58
+ ws.each do | sock |
59
+ case @roles[ sock ]
60
+ when :room
61
+ write_room( sock )
62
+ when :p1
63
+ write_p1( sock )
64
+ when :app
65
+ write_app( sock )
66
+ end
67
+ end
68
+ end
69
+ end
70
+ rescue Interrupt => e
71
+ puts e.class
72
+ quit!
73
+ end
74
+
75
+ def quit!
76
+ exit
77
+ end
78
+
79
+ private
80
+
81
+ def loop_heartbeat
82
+ Thread.new do
83
+ loop do
84
+ sleep 59
85
+
86
+ @mutex.synchronize do
87
+ @room.write( [ HEARTBEAT ].pack( 'C' ) )
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ def read_room( sock )
94
+ begin
95
+ data = sock.read_nonblock( PACK_SIZE )
96
+ rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable => e
97
+ return
98
+ rescue Errno::ECONNREFUSED, EOFError, Errno::ECONNRESET => e
99
+ puts "read room #{ e.class } #{ Time.new }"
100
+
101
+ if @is_renew
102
+ raise e
103
+ end
104
+
105
+ add_closing( sock )
106
+ return
107
+ end
108
+
109
+ @is_renew = false
110
+ info = @infos[ sock ]
111
+ info[ :p2_sockaddr ] = data
112
+ new_p1
113
+ end
114
+
115
+ def read_p1( sock )
116
+ begin
117
+ data = sock.read_nonblock( PACK_SIZE )
118
+ rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable => e
119
+ return
120
+ rescue Errno::ECONNREFUSED => e
121
+ if @room_info[ :rep2p ] >= REP2P_LIMIT
122
+ raise e
123
+ end
124
+
125
+ add_closing( sock, NEED_RENEW )
126
+ return
127
+ rescue Exception => e
128
+ add_closing( sock )
129
+ return
130
+ end
131
+
132
+ @room_info[ :rep2p ] = 0
133
+ info = @infos[ sock ]
134
+
135
+ if info[ :need_decode ]
136
+ len = data[ 0, 2 ].unpack( 'n' ).first
137
+ head = @hex.decode( data[ 2, len ] )
138
+ data = head + data[ ( 2 + len )..-1 ]
139
+ info[ :need_decode ] = false
140
+ end
141
+
142
+ add_write( @app, data, NEED_CHUNK )
143
+ end
144
+
145
+ def read_app( sock )
146
+ begin
147
+ data = sock.read_nonblock( PACK_SIZE )
148
+ rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable => e
149
+ return
150
+ rescue Exception => e
151
+ add_closing( sock )
152
+ return
153
+ end
154
+
155
+ info = @infos[ sock ]
156
+
157
+ if info[ :need_encode ]
158
+ data = @hex.encode( data )
159
+ data = [ [ data.size ].pack( 'n' ), data ].join
160
+ info[ :need_encode ] = false
161
+ end
162
+
163
+ add_write( @p1, data, NEED_CHUNK )
164
+ end
165
+
166
+ def write_room( sock )
167
+ if @closings.include?( sock )
168
+ close_sock( sock )
169
+ sleep 5
170
+ new_room
171
+ @is_renew = true
172
+ @closings.delete( sock )
173
+
174
+ return
175
+ end
176
+
177
+ info = @infos[ sock ]
178
+ data = info[ :wbuff ]
179
+
180
+ if data.empty?
181
+ @writes.delete( sock )
182
+ return
183
+ end
184
+
185
+ sock.write( data )
186
+ info[ :wbuff ].clear
187
+ end
188
+
189
+ def write_p1( sock )
190
+ if @closings.include?( sock )
191
+ close_sock( sock )
192
+ @p1 = nil
193
+
194
+ if @app && !@app.closed?
195
+ add_closing( @app )
196
+ end
197
+
198
+ need_renew = @closings.delete( sock )
199
+
200
+ if need_renew
201
+ sleep 1
202
+ new_p1
203
+ @room_info[ :rep2p ] += 1
204
+ end
205
+
206
+ return
207
+ end
208
+
209
+ info = @infos[ sock ]
210
+ data, from = get_buff( info )
211
+
212
+ if data.empty?
213
+ @writes.delete( sock )
214
+ return
215
+ end
216
+
217
+ begin
218
+ written = sock.write_nonblock( data )
219
+ rescue IO::WaitWritable, Errno::EINTR, IO::WaitReadable
220
+ return
221
+ rescue Exception => e
222
+ add_closing( sock )
223
+ return
224
+ end
225
+
226
+ data = data[ written..-1 ]
227
+ info[ from ] = data
228
+ end
229
+
230
+ def write_app( sock )
231
+ if @closings.include?( sock )
232
+ close_sock( sock )
233
+ @app = nil
234
+
235
+ if @p1 && !@p1.closed?
236
+ add_closing( @p1 )
237
+ end
238
+
239
+ @closings.delete( sock )
240
+ return
241
+ end
242
+
243
+ info = @infos[ sock ]
244
+ data, from = get_buff( info )
245
+
246
+ if data.empty?
247
+ @writes.delete( sock )
248
+ return
249
+ end
250
+
251
+ begin
252
+ written = sock.write_nonblock( data )
253
+ rescue IO::WaitWritable, Errno::EINTR, IO::WaitReadable
254
+ return
255
+ rescue Exception => e
256
+ add_closing( sock )
257
+ return
258
+ end
259
+
260
+ data = data[ written..-1 ]
261
+ info[ from ] = data
262
+ end
263
+
264
+ def get_buff( info )
265
+ data, from = info[ :cache ], :cache
266
+
267
+ if data.empty?
268
+ if info[ :chunks ].any?
269
+ path = File.join( info[ :chunk_dir ], info[ :chunks ].shift )
270
+ data = info[ :cache ] = IO.binread( path )
271
+
272
+ begin
273
+ File.delete( path )
274
+ rescue Errno::ENOENT
275
+ end
276
+ else
277
+ data, from = info[ :wbuff ], :wbuff
278
+ end
279
+ end
280
+
281
+ [ data, from ]
282
+ end
283
+
284
+ def add_closing( sock, need_renew = false )
285
+ unless @closings.include?( sock )
286
+ @closings[ sock ] = need_renew
287
+ end
288
+
289
+ add_write( sock )
290
+ end
291
+
292
+ def add_write( sock, data = nil, need_chunk = false )
293
+ if data
294
+ info = @infos[ sock ]
295
+ info[ :wbuff ] << data
296
+
297
+ if need_chunk && info[ :wbuff ].size >= CHUNK_SIZE
298
+ filename = [ info[ :filename ], info[ :chunk_seed ] ].join( '.' )
299
+ chunk_path = File.join( info[ :chunk_dir ], filename )
300
+ IO.binwrite( chunk_path, info[ :wbuff ] )
301
+ info[ :chunks ] << filename
302
+ info[ :chunk_seed ] += 1
303
+ info[ :wbuff ].clear
304
+ end
305
+ end
306
+
307
+ unless @writes.include?( sock )
308
+ @writes << sock
309
+ end
310
+ end
311
+
312
+ def close_sock( sock )
313
+ sock.close
314
+ @roles.delete( sock )
315
+ @reads.delete( sock )
316
+ @writes.delete( sock )
317
+ info = @infos.delete( sock )
318
+
319
+ if info && info[ :chunks ]
320
+ info[ :chunks ].each do | filename |
321
+ begin
322
+ File.delete( File.join( info[ :chunk_dir ], filename ) )
323
+ rescue Errno::ENOENT
324
+ end
325
+ end
326
+ end
327
+
328
+ info
329
+ end
330
+
331
+ def new_room
332
+ room = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
333
+ room.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
334
+ room.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
335
+
336
+ begin
337
+ room.connect_nonblock( @roomd_sockaddr )
338
+ rescue IO::WaitWritable, Errno::EINTR
339
+ end
340
+
341
+ bytes = @title.unpack( "C*" ).map{ | c | c.chr }.join
342
+ room_info = {
343
+ wbuff: [ [ SET_TITLE, bytes.size ].pack( 'Cn' ), bytes ].join,
344
+ p2_sockaddr: nil,
345
+ rep2p: 0
346
+ }
347
+ @room = room
348
+ @room_info = room_info
349
+ @roles[ room ] = :room
350
+ @infos[ room ] = room_info
351
+ @reads << room
352
+ @writes << room
353
+ end
354
+
355
+ def new_p1
356
+ p1 = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
357
+ p1.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
358
+ p1.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
359
+ p1.bind( @room.local_address ) # use the hole
360
+
361
+ begin
362
+ p1.connect_nonblock( @room_info[ :p2_sockaddr ] )
363
+ rescue IO::WaitWritable, Errno::EINTR
364
+ rescue Exception => e
365
+ puts "connect p2 #{ e.class } #{ Time.new }"
366
+ p1.close
367
+ return
368
+ end
369
+
370
+ p1_info = {
371
+ wbuff: '',
372
+ cache: '',
373
+ filename: [ Process.pid, p1.object_id ].join( '-' ),
374
+ chunk_dir: @p1_chunk_dir,
375
+ chunks: [],
376
+ chunk_seed: 0,
377
+ need_decode: true
378
+ }
379
+ @p1 = p1
380
+ @p1_info = p1_info
381
+ @roles[ p1 ] = :p1
382
+ @infos[ p1 ] = p1_info
383
+ @reads << p1
384
+
385
+ app = Socket.new( Socket::AF_INET, Socket::SOCK_STREAM, 0 )
386
+ app.setsockopt( Socket::SOL_TCP, Socket::TCP_NODELAY, 1 )
387
+
388
+ begin
389
+ app.connect_nonblock( @appd_sockaddr )
390
+ rescue IO::WaitWritable, Errno::EINTR
391
+ end
392
+
393
+ app_info = {
394
+ wbuff: '',
395
+ cache: '',
396
+ filename: [ Process.pid, app.object_id ].join( '-' ),
397
+ chunk_dir: @app_chunk_dir,
398
+ chunks: [],
399
+ chunk_seed: 0,
400
+ need_encode: true
401
+ }
402
+
403
+ @app = app
404
+ @app_info = app_info
405
+ @roles[ app ] = :app
406
+ @infos[ app ] = app_info
407
+ @reads << app
408
+ end
409
+ end
410
+ end