p2p2 0.6.8 → 0.6.9
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 +4 -4
- data/lib/p2p2.rb +3 -3
- data/lib/p2p2/head.rb +9 -9
- data/lib/p2p2/p1.rb +457 -458
- data/lib/p2p2/p2.rb +494 -495
- data/lib/p2p2/p2pd.rb +286 -286
- data/lib/p2p2/version.rb +3 -3
- data/p2p2.gemspec +29 -29
- metadata +3 -2
data/lib/p2p2/p2pd.rb
CHANGED
@@ -1,286 +1,286 @@
|
|
1
|
-
require 'p2p2/head'
|
2
|
-
require 'p2p2/version'
|
3
|
-
require 'socket'
|
4
|
-
|
5
|
-
##
|
6
|
-
# P2p2::P2pd - 处于nat里的任意应用,访问处于另一个nat里的应用服务端,借助一根p2p管道。配对服务器端。
|
7
|
-
#
|
8
|
-
# 1.
|
9
|
-
#
|
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
|
-
# ```
|
26
|
-
#
|
27
|
-
# usage
|
28
|
-
# =====
|
29
|
-
#
|
30
|
-
# 1. Girl::P2pd.new( 5050 ).looping # @server
|
31
|
-
#
|
32
|
-
# 2. Girl::P1.new( 'your.server.ip', 5050, '127.0.0.1', 22, '周立波' ).looping # @home1
|
33
|
-
#
|
34
|
-
# 3. Girl::P2.new( 'your.server.ip', 5050, '0.0.0.0', 2222, '周立波' ).looping # @home2
|
35
|
-
#
|
36
|
-
# 4. ssh -p2222 libo@localhost
|
37
|
-
#
|
38
|
-
module P2p2
|
39
|
-
class P2pd
|
40
|
-
|
41
|
-
##
|
42
|
-
# roomd_port 配对服务器端口
|
43
|
-
# roomd_dir 可在该目录下看到所有的p1
|
44
|
-
def initialize( roomd_port = 5050, roomd_dir = '/tmp' )
|
45
|
-
@roomd_port = roomd_port
|
46
|
-
@roomd_dir = roomd_dir
|
47
|
-
@mutex = Mutex.new
|
48
|
-
@reads = []
|
49
|
-
@writes = []
|
50
|
-
@closings = []
|
51
|
-
@roles = {} # sock => :roomd / :room
|
52
|
-
@infos = {}
|
53
|
-
@rooms = {} # object_id => room
|
54
|
-
@p1s = {} # title => room
|
55
|
-
@p2s = {} # title => room
|
56
|
-
|
57
|
-
ctlr, ctlw = IO.pipe
|
58
|
-
@ctlw = ctlw
|
59
|
-
@roles[ ctlr ] = :ctlr
|
60
|
-
@reads << ctlr
|
61
|
-
|
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
|
69
|
-
end
|
70
|
-
|
71
|
-
def looping
|
72
|
-
puts 'looping'
|
73
|
-
|
74
|
-
loop_expire
|
75
|
-
|
76
|
-
loop do
|
77
|
-
rs, ws = IO.select( @reads, @writes )
|
78
|
-
|
79
|
-
@mutex.synchronize do
|
80
|
-
rs.each do | sock |
|
81
|
-
case @roles[ sock ]
|
82
|
-
when :ctlr
|
83
|
-
read_ctlr( sock )
|
84
|
-
when :roomd
|
85
|
-
read_roomd( sock )
|
86
|
-
when :room
|
87
|
-
read_room( sock )
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
ws.each do | sock |
|
92
|
-
case @roles[ sock ]
|
93
|
-
when :room
|
94
|
-
write_room( sock )
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
rescue Interrupt => e
|
100
|
-
puts e.class
|
101
|
-
quit!
|
102
|
-
end
|
103
|
-
|
104
|
-
def quit!
|
105
|
-
exit
|
106
|
-
end
|
107
|
-
|
108
|
-
private
|
109
|
-
|
110
|
-
def loop_expire
|
111
|
-
Thread.new do
|
112
|
-
loop do
|
113
|
-
sleep 3600
|
114
|
-
|
115
|
-
if @infos.any?
|
116
|
-
@mutex.synchronize do
|
117
|
-
now = Time.new
|
118
|
-
|
119
|
-
@infos.select{ | _, info | now - info[ :updated_at ] > 86400 }.each do | room, _ |
|
120
|
-
@ctlw.write( [ CTL_CLOSE_ROOM, [ room.object_id ].pack( 'N' ) ].join )
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def read_ctlr( ctlr )
|
129
|
-
case ctlr.read( 1 )
|
130
|
-
when CTL_CLOSE_ROOM
|
131
|
-
room_id = ctlr.read( 4 ).unpack( 'N' ).first
|
132
|
-
room = @rooms[ room_id ]
|
133
|
-
|
134
|
-
if room
|
135
|
-
add_closing( room )
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def read_roomd( roomd )
|
141
|
-
begin
|
142
|
-
room, addrinfo = roomd.accept_nonblock
|
143
|
-
rescue IO::WaitReadable, Errno::EINTR
|
144
|
-
return
|
145
|
-
end
|
146
|
-
|
147
|
-
@rooms[ room.object_id ] = room
|
148
|
-
@roles[ room ] = :room
|
149
|
-
@infos[ room ] = {
|
150
|
-
title: nil,
|
151
|
-
wbuff: '',
|
152
|
-
sockaddr: addrinfo.to_sockaddr,
|
153
|
-
updated_at: Time.new
|
154
|
-
}
|
155
|
-
@reads << room
|
156
|
-
end
|
157
|
-
|
158
|
-
def read_room( room )
|
159
|
-
begin
|
160
|
-
data = room.read_nonblock( PACK_SIZE )
|
161
|
-
rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable
|
162
|
-
return
|
163
|
-
rescue Exception => e
|
164
|
-
add_closing( room )
|
165
|
-
return
|
166
|
-
end
|
167
|
-
|
168
|
-
info = @infos[ room ]
|
169
|
-
info[ :updated_at ] = Time.new
|
170
|
-
ctl_num = data[ 0 ].unpack( 'C' ).first
|
171
|
-
|
172
|
-
case ctl_num
|
173
|
-
when SET_TITLE
|
174
|
-
title = data[ 1..-1 ]
|
175
|
-
|
176
|
-
if title.size > 255
|
177
|
-
puts 'title too long'
|
178
|
-
add_closing( room )
|
179
|
-
return
|
180
|
-
end
|
181
|
-
|
182
|
-
if @p1s.include?( title )
|
183
|
-
puts "p1 #{ title.inspect } already exist"
|
184
|
-
add_closing( room )
|
185
|
-
return
|
186
|
-
end
|
187
|
-
|
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
|
195
|
-
|
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
|
203
|
-
|
204
|
-
info[ :title ] = title
|
205
|
-
@p1s[ title ] = room
|
206
|
-
when PAIRING
|
207
|
-
title = data[ 1..-1 ]
|
208
|
-
|
209
|
-
if title.size > 255
|
210
|
-
puts 'pairing title too long'
|
211
|
-
add_closing( room )
|
212
|
-
return
|
213
|
-
end
|
214
|
-
|
215
|
-
if @p2s.include?( title )
|
216
|
-
puts "p2 #{ title.inspect } already exist"
|
217
|
-
add_closing( room )
|
218
|
-
return
|
219
|
-
end
|
220
|
-
|
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
|
228
|
-
|
229
|
-
info[ :title ] = title
|
230
|
-
@p2s[ title ] = room
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
def write_room( room )
|
235
|
-
if @closings.include?( room )
|
236
|
-
close_room( room )
|
237
|
-
return
|
238
|
-
end
|
239
|
-
|
240
|
-
info = @infos[ room ]
|
241
|
-
room.write( info[ :wbuff ] )
|
242
|
-
@writes.delete( room )
|
243
|
-
end
|
244
|
-
|
245
|
-
def add_closing( sock )
|
246
|
-
unless @closings.include?( sock )
|
247
|
-
@reads.delete( sock )
|
248
|
-
@closings << sock
|
249
|
-
end
|
250
|
-
|
251
|
-
add_write( sock )
|
252
|
-
end
|
253
|
-
|
254
|
-
def add_write( sock, data = nil )
|
255
|
-
if data
|
256
|
-
info = @infos[ sock ]
|
257
|
-
info[ :wbuff ] = data
|
258
|
-
end
|
259
|
-
|
260
|
-
unless @writes.include?( sock )
|
261
|
-
@writes << sock
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
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 )
|
273
|
-
|
274
|
-
if info && info[ :title ]
|
275
|
-
title_path = File.join( @roomd_dir, info[ :title ] )
|
276
|
-
|
277
|
-
if File.exist?( title_path )
|
278
|
-
File.delete( title_path )
|
279
|
-
@p1s.delete( info[ :title ] )
|
280
|
-
else
|
281
|
-
@p2s.delete( info[ :title ] )
|
282
|
-
end
|
283
|
-
end
|
284
|
-
end
|
285
|
-
end
|
286
|
-
end
|
1
|
+
require 'p2p2/head'
|
2
|
+
require 'p2p2/version'
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
##
|
6
|
+
# P2p2::P2pd - 处于nat里的任意应用,访问处于另一个nat里的应用服务端,借助一根p2p管道。配对服务器端。
|
7
|
+
#
|
8
|
+
# 1.
|
9
|
+
#
|
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
|
+
# ```
|
26
|
+
#
|
27
|
+
# usage
|
28
|
+
# =====
|
29
|
+
#
|
30
|
+
# 1. Girl::P2pd.new( 5050 ).looping # @server
|
31
|
+
#
|
32
|
+
# 2. Girl::P1.new( 'your.server.ip', 5050, '127.0.0.1', 22, '周立波' ).looping # @home1
|
33
|
+
#
|
34
|
+
# 3. Girl::P2.new( 'your.server.ip', 5050, '0.0.0.0', 2222, '周立波' ).looping # @home2
|
35
|
+
#
|
36
|
+
# 4. ssh -p2222 libo@localhost
|
37
|
+
#
|
38
|
+
module P2p2
|
39
|
+
class P2pd
|
40
|
+
|
41
|
+
##
|
42
|
+
# roomd_port 配对服务器端口
|
43
|
+
# roomd_dir 可在该目录下看到所有的p1
|
44
|
+
def initialize( roomd_port = 5050, roomd_dir = '/tmp' )
|
45
|
+
@roomd_port = roomd_port
|
46
|
+
@roomd_dir = roomd_dir
|
47
|
+
@mutex = Mutex.new
|
48
|
+
@reads = []
|
49
|
+
@writes = []
|
50
|
+
@closings = []
|
51
|
+
@roles = {} # sock => :roomd / :room
|
52
|
+
@infos = {}
|
53
|
+
@rooms = {} # object_id => room
|
54
|
+
@p1s = {} # title => room
|
55
|
+
@p2s = {} # title => room
|
56
|
+
|
57
|
+
ctlr, ctlw = IO.pipe
|
58
|
+
@ctlw = ctlw
|
59
|
+
@roles[ ctlr ] = :ctlr
|
60
|
+
@reads << ctlr
|
61
|
+
|
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
|
69
|
+
end
|
70
|
+
|
71
|
+
def looping
|
72
|
+
puts 'looping'
|
73
|
+
|
74
|
+
loop_expire
|
75
|
+
|
76
|
+
loop do
|
77
|
+
rs, ws = IO.select( @reads, @writes )
|
78
|
+
|
79
|
+
@mutex.synchronize do
|
80
|
+
rs.each do | sock |
|
81
|
+
case @roles[ sock ]
|
82
|
+
when :ctlr
|
83
|
+
read_ctlr( sock )
|
84
|
+
when :roomd
|
85
|
+
read_roomd( sock )
|
86
|
+
when :room
|
87
|
+
read_room( sock )
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
ws.each do | sock |
|
92
|
+
case @roles[ sock ]
|
93
|
+
when :room
|
94
|
+
write_room( sock )
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
rescue Interrupt => e
|
100
|
+
puts e.class
|
101
|
+
quit!
|
102
|
+
end
|
103
|
+
|
104
|
+
def quit!
|
105
|
+
exit
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def loop_expire
|
111
|
+
Thread.new do
|
112
|
+
loop do
|
113
|
+
sleep 3600
|
114
|
+
|
115
|
+
if @infos.any?
|
116
|
+
@mutex.synchronize do
|
117
|
+
now = Time.new
|
118
|
+
|
119
|
+
@infos.select{ | _, info | now - info[ :updated_at ] > 86400 }.each do | room, _ |
|
120
|
+
@ctlw.write( [ CTL_CLOSE_ROOM, [ room.object_id ].pack( 'N' ) ].join )
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def read_ctlr( ctlr )
|
129
|
+
case ctlr.read( 1 )
|
130
|
+
when CTL_CLOSE_ROOM
|
131
|
+
room_id = ctlr.read( 4 ).unpack( 'N' ).first
|
132
|
+
room = @rooms[ room_id ]
|
133
|
+
|
134
|
+
if room
|
135
|
+
add_closing( room )
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def read_roomd( roomd )
|
141
|
+
begin
|
142
|
+
room, addrinfo = roomd.accept_nonblock
|
143
|
+
rescue IO::WaitReadable, Errno::EINTR
|
144
|
+
return
|
145
|
+
end
|
146
|
+
|
147
|
+
@rooms[ room.object_id ] = room
|
148
|
+
@roles[ room ] = :room
|
149
|
+
@infos[ room ] = {
|
150
|
+
title: nil,
|
151
|
+
wbuff: '',
|
152
|
+
sockaddr: addrinfo.to_sockaddr,
|
153
|
+
updated_at: Time.new
|
154
|
+
}
|
155
|
+
@reads << room
|
156
|
+
end
|
157
|
+
|
158
|
+
def read_room( room )
|
159
|
+
begin
|
160
|
+
data = room.read_nonblock( PACK_SIZE )
|
161
|
+
rescue IO::WaitReadable, Errno::EINTR, IO::WaitWritable
|
162
|
+
return
|
163
|
+
rescue Exception => e
|
164
|
+
add_closing( room )
|
165
|
+
return
|
166
|
+
end
|
167
|
+
|
168
|
+
info = @infos[ room ]
|
169
|
+
info[ :updated_at ] = Time.new
|
170
|
+
ctl_num = data[ 0 ].unpack( 'C' ).first
|
171
|
+
|
172
|
+
case ctl_num
|
173
|
+
when SET_TITLE
|
174
|
+
title = data[ 1..-1 ]
|
175
|
+
|
176
|
+
if title.size > 255
|
177
|
+
puts 'title too long'
|
178
|
+
add_closing( room )
|
179
|
+
return
|
180
|
+
end
|
181
|
+
|
182
|
+
if @p1s.include?( title )
|
183
|
+
puts "p1 #{ title.inspect } already exist"
|
184
|
+
add_closing( room )
|
185
|
+
return
|
186
|
+
end
|
187
|
+
|
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
|
195
|
+
|
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
|
203
|
+
|
204
|
+
info[ :title ] = title
|
205
|
+
@p1s[ title ] = room
|
206
|
+
when PAIRING
|
207
|
+
title = data[ 1..-1 ]
|
208
|
+
|
209
|
+
if title.size > 255
|
210
|
+
puts 'pairing title too long'
|
211
|
+
add_closing( room )
|
212
|
+
return
|
213
|
+
end
|
214
|
+
|
215
|
+
if @p2s.include?( title )
|
216
|
+
puts "p2 #{ title.inspect } already exist"
|
217
|
+
add_closing( room )
|
218
|
+
return
|
219
|
+
end
|
220
|
+
|
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
|
228
|
+
|
229
|
+
info[ :title ] = title
|
230
|
+
@p2s[ title ] = room
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def write_room( room )
|
235
|
+
if @closings.include?( room )
|
236
|
+
close_room( room )
|
237
|
+
return
|
238
|
+
end
|
239
|
+
|
240
|
+
info = @infos[ room ]
|
241
|
+
room.write( info[ :wbuff ] )
|
242
|
+
@writes.delete( room )
|
243
|
+
end
|
244
|
+
|
245
|
+
def add_closing( sock )
|
246
|
+
unless @closings.include?( sock )
|
247
|
+
@reads.delete( sock )
|
248
|
+
@closings << sock
|
249
|
+
end
|
250
|
+
|
251
|
+
add_write( sock )
|
252
|
+
end
|
253
|
+
|
254
|
+
def add_write( sock, data = nil )
|
255
|
+
if data
|
256
|
+
info = @infos[ sock ]
|
257
|
+
info[ :wbuff ] = data
|
258
|
+
end
|
259
|
+
|
260
|
+
unless @writes.include?( sock )
|
261
|
+
@writes << sock
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
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 )
|
273
|
+
|
274
|
+
if info && info[ :title ]
|
275
|
+
title_path = File.join( @roomd_dir, info[ :title ] )
|
276
|
+
|
277
|
+
if File.exist?( title_path )
|
278
|
+
File.delete( title_path )
|
279
|
+
@p1s.delete( info[ :title ] )
|
280
|
+
else
|
281
|
+
@p2s.delete( info[ :title ] )
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|