p2p2 0.7.2 → 0.8.0
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 +28 -10
- data/lib/p2p2/p1.rb +820 -459
- data/lib/p2p2/p2.rb +860 -496
- data/lib/p2p2/p2pd.rb +135 -286
- data/lib/p2p2/version.rb +3 -3
- data/p2p2.gemspec +29 -29
- metadata +4 -3
data/lib/p2p2/p2pd.rb
CHANGED
@@ -1,286 +1,135 @@
|
|
1
|
-
require 'p2p2/head'
|
2
|
-
require 'p2p2/version'
|
3
|
-
require 'socket'
|
4
|
-
|
5
|
-
##
|
6
|
-
# P2p2::P2pd - 内网里的任意应用,访问另一个内网里的应用服务端。配对服务器端。
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
@
|
68
|
-
@
|
69
|
-
end
|
70
|
-
|
71
|
-
def looping
|
72
|
-
puts 'looping'
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
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 #{ Time.new }"
|
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 #{ Time.new }"
|
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 - 内网里的任意应用,访问另一个内网里的应用服务端。配对服务器端。
|
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
|
+
# 包结构
|
39
|
+
# ======
|
40
|
+
#
|
41
|
+
# Q>: 1+ app/shadow_id -> Q>: pack_id -> traffic
|
42
|
+
# 0 ctlmsg -> C: 1 peer addr -> p1/p2_sockaddr
|
43
|
+
# 2 heartbeat -> C: random char
|
44
|
+
# 3 a new app -> Q>: app_id
|
45
|
+
# 4 paired -> Q>Q>: app_id shadow_id
|
46
|
+
# 5 shadow status -> Q>Q>Q>: shadow_id biggest_shadow_pack_id continue_app_pack_id
|
47
|
+
# 6 app status -> Q>Q>Q>: app_id biggest_app_pack_id continue_shadow_pack_id
|
48
|
+
# 7 miss -> Q>Q>Q>: app/shadow_id pack_id_begin pack_id_end
|
49
|
+
# 8 fin1 -> Q>: app/shadow_id
|
50
|
+
# 9 got fin1 -> Q>: app/shadow_id
|
51
|
+
# 10 fin2 -> Q>: app/shadow_id
|
52
|
+
# 11 got fin2 -> Q>: app/shadow_id
|
53
|
+
# 12 p1 fin
|
54
|
+
# 13 p2 fin
|
55
|
+
#
|
56
|
+
module P2p2
|
57
|
+
class P2pd
|
58
|
+
|
59
|
+
##
|
60
|
+
# p2pd_port 配对服务器端口
|
61
|
+
# p2pd_dir 可在该目录下看到所有的房间
|
62
|
+
def initialize( p2pd_port = 5050, p2pd_dir = '/tmp' )
|
63
|
+
p2pd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
|
64
|
+
p2pd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
|
65
|
+
p2pd.bind( Socket.pack_sockaddr_in( p2pd_port, '0.0.0.0' ) )
|
66
|
+
|
67
|
+
@p2pd = p2pd
|
68
|
+
@p2pd_dir = p2pd_dir
|
69
|
+
end
|
70
|
+
|
71
|
+
def looping
|
72
|
+
puts 'looping'
|
73
|
+
|
74
|
+
loop do
|
75
|
+
rs, _ = IO.select( [ @p2pd ] )
|
76
|
+
read_p2pd( rs.first )
|
77
|
+
end
|
78
|
+
rescue Interrupt => e
|
79
|
+
puts e.class
|
80
|
+
quit!
|
81
|
+
end
|
82
|
+
|
83
|
+
def quit!
|
84
|
+
exit
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def read_p2pd( p2pd )
|
90
|
+
data, addrinfo, rflags, *controls = p2pd.recvmsg
|
91
|
+
return if data.size > 255
|
92
|
+
|
93
|
+
sockaddr = addrinfo.to_sockaddr
|
94
|
+
title_path = File.join( @p2pd_dir, data )
|
95
|
+
|
96
|
+
unless File.exist?( title_path )
|
97
|
+
write_title( title_path, sockaddr )
|
98
|
+
return
|
99
|
+
end
|
100
|
+
|
101
|
+
if Time.new - File.mtime( title_path ) > 300
|
102
|
+
write_title( title_path, sockaddr )
|
103
|
+
return
|
104
|
+
end
|
105
|
+
|
106
|
+
op_sockaddr = IO.binread( title_path )
|
107
|
+
|
108
|
+
if Addrinfo.new( op_sockaddr ).ip_address == addrinfo.ip_address
|
109
|
+
write_title( title_path, sockaddr )
|
110
|
+
return
|
111
|
+
end
|
112
|
+
|
113
|
+
send_pack( p2pd, "#{ [ 0, PEER_ADDR ].pack( 'Q>C' ) }#{ op_sockaddr }", sockaddr )
|
114
|
+
send_pack( p2pd, "#{ [ 0, PEER_ADDR ].pack( 'Q>C' ) }#{ sockaddr }", op_sockaddr )
|
115
|
+
end
|
116
|
+
|
117
|
+
def write_title( title_path, sockaddr )
|
118
|
+
begin
|
119
|
+
# puts "debug write title #{ title_path } #{ Time.new }"
|
120
|
+
IO.binwrite( title_path, sockaddr )
|
121
|
+
rescue Errno::ENOENT, ArgumentError => e
|
122
|
+
puts "binwrite #{ e.class } #{ Time.new }"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def send_pack( sock, data, target_sockaddr )
|
127
|
+
begin
|
128
|
+
# puts "debug sendmsg #{ data.inspect } #{ Time.new }"
|
129
|
+
sock.sendmsg( data, 0, target_sockaddr )
|
130
|
+
rescue IO::WaitWritable, Errno::EINTR => e
|
131
|
+
puts "sendmsg #{ e.class } #{ Time.new }"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
data/lib/p2p2/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module P2p2
|
2
|
-
VERSION = "0.
|
3
|
-
end
|
1
|
+
module P2p2
|
2
|
+
VERSION = "0.8.0"
|
3
|
+
end
|
data/p2p2.gemspec
CHANGED
@@ -1,29 +1,29 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require "p2p2/version"
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "p2p2"
|
8
|
-
spec.version = P2p2::VERSION
|
9
|
-
spec.authors = ["takafan"]
|
10
|
-
spec.email = ["qqtakafan@gmail.com"]
|
11
|
-
|
12
|
-
spec.summary = %q{p2p}
|
13
|
-
spec.description = %q{内网里的任意应用,访问另一个内网里的应用服务端。}
|
14
|
-
spec.homepage = "https://github.com/takafan/p2p2"
|
15
|
-
spec.license = "MIT"
|
16
|
-
|
17
|
-
spec.files = %w[
|
18
|
-
p2p2.gemspec
|
19
|
-
lib/p2p2.rb
|
20
|
-
lib/p2p2/head.rb
|
21
|
-
lib/p2p2/hex.rb
|
22
|
-
lib/p2p2/p1.rb
|
23
|
-
lib/p2p2/p2.rb
|
24
|
-
lib/p2p2/p2pd.rb
|
25
|
-
lib/p2p2/version.rb
|
26
|
-
]
|
27
|
-
|
28
|
-
spec.require_paths = ["lib"]
|
29
|
-
end
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "p2p2/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "p2p2"
|
8
|
+
spec.version = P2p2::VERSION
|
9
|
+
spec.authors = ["takafan"]
|
10
|
+
spec.email = ["qqtakafan@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{p2p}
|
13
|
+
spec.description = %q{内网里的任意应用,访问另一个内网里的应用服务端。}
|
14
|
+
spec.homepage = "https://github.com/takafan/p2p2"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = %w[
|
18
|
+
p2p2.gemspec
|
19
|
+
lib/p2p2.rb
|
20
|
+
lib/p2p2/head.rb
|
21
|
+
lib/p2p2/hex.rb
|
22
|
+
lib/p2p2/p1.rb
|
23
|
+
lib/p2p2/p2.rb
|
24
|
+
lib/p2p2/p2pd.rb
|
25
|
+
lib/p2p2/version.rb
|
26
|
+
]
|
27
|
+
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
end
|