p2p2 0.6.8 → 0.6.9

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