p2p2 0.14.0 → 0.18.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.
@@ -1,135 +1,120 @@
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.bytesize == 1 ) || ( data.bytesize > 255 ) || ( data =~ /\/|\.|\ / )
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::EISDIR, Errno::ENAMETOOLONG, 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
1
+ require 'json'
2
+ require 'p2p2/head'
3
+ require 'p2p2/p2pd_worker'
4
+ require 'p2p2/version'
5
+ require 'socket'
6
+
7
+ ##
8
+ # P2p2::P2pd - 内网里的任意应用,访问另一个内网里的应用服务端。配对服务器端。
9
+ #
10
+ # 包结构
11
+ # ======
12
+ #
13
+ # tund-p2pd, tun-p2pd:
14
+ #
15
+ # room
16
+ #
17
+ # p2pd-tund, p2pd-tun:
18
+ #
19
+ # Q>: 0 ctlmsg -> C: 1 peer addr -> tun sockaddr / tund sockaddr
20
+ #
21
+ # tun-tund:
22
+ #
23
+ # Q>: 0 ctlmsg -> C: 2 heartbeat -> C: random char
24
+ # 3 a new source -> Q>: src id
25
+ # 4 paired -> Q>: src id -> n: dst port
26
+ # 5 dest status -> n: dst port -> Q>: biggest relayed dst pack id -> Q>: continue src pack id
27
+ # 6 source status -> Q>: src id -> Q>: biggest relayed src pack id -> Q>: continue dst pack id
28
+ # 7 miss -> Q>/n: src id / dst port -> Q>: pack id begin -> Q>: pack id end
29
+ # 8 fin1 -> Q>/n: src id / dst port -> Q>: biggest src pack id / biggest dst pack id -> Q>: continue dst pack id / continue src pack id
30
+ # 9 not use
31
+ # 10 fin2 -> Q>/n: src id / dst port
32
+ # 11 not use
33
+ # 12 tund fin
34
+ # 13 tun fin
35
+ #
36
+ # Q>: 1+ pack_id -> Q>/n: src id / dst port -> traffic
37
+ #
38
+ # close logic
39
+ # ===========
40
+ #
41
+ # 1-1. after close src -> dst closed ? no -> send fin1
42
+ # 1-2. tun recv fin2 -> del src ext
43
+ #
44
+ # 2-1. tun recv fin1 -> all traffic received ? -> close src after write
45
+ # 2-2. tun recv traffic -> dst closed and all traffic received ? -> close src after write
46
+ # 2-3. after close src -> dst closed ? yes -> del src ext -> send fin2
47
+ #
48
+ # 3-1. after close dst -> src closed ? no -> send fin1
49
+ # 3-2. tund recv fin2 -> del dst ext
50
+ #
51
+ # 4-1. tund recv fin1 -> all traffic received ? -> close dst after write
52
+ # 4-2. tund recv traffic -> src closed and all traffic received ? -> close dst after write
53
+ # 4-3. after close dst -> src closed ? yes -> del dst ext -> send fin2
54
+ #
55
+ module P2p2
56
+ class P2pd
57
+
58
+ def initialize( config_path = nil )
59
+ unless config_path
60
+ config_path = File.expand_path( '../p2p2.conf.json', __FILE__ )
61
+ end
62
+
63
+ unless File.exist?( config_path )
64
+ raise "missing config file #{ config_path }"
65
+ end
66
+
67
+ conf = JSON.parse( IO.binread( config_path ), symbolize_names: true )
68
+ p2pd_port = conf[ :p2pd_port ]
69
+ p2pd_tmp_dir = conf[ :p2pd_tmp_dir ]
70
+
71
+ unless p2pd_port
72
+ p2pd_port = 2020
73
+ end
74
+
75
+ unless p2pd_tmp_dir
76
+ p2pd_tmp_dir = '/tmp/p2p2.p2pd'
77
+ end
78
+
79
+ unless File.exist?( p2pd_tmp_dir )
80
+ Dir.mkdir( p2pd_tmp_dir )
81
+ end
82
+
83
+ title = "p2p2 p2pd #{ P2p2::VERSION }"
84
+ puts title
85
+ puts "p2pd port #{ p2pd_port }"
86
+ puts "p2pd tmp dir #{ p2pd_tmp_dir }"
87
+
88
+ if RUBY_PLATFORM.include?( 'linux' )
89
+ $0 = title
90
+
91
+ pid = fork do
92
+ $0 = 'p2p2 p2pd worker'
93
+ worker = P2p2::P2pdWorker.new( p2pd_port, p2pd_tmp_dir )
94
+
95
+ Signal.trap( :TERM ) do
96
+ puts 'exit'
97
+ worker.quit!
98
+ end
99
+
100
+ worker.looping
101
+ end
102
+
103
+ Signal.trap( :TERM ) do
104
+ puts 'trap TERM'
105
+
106
+ begin
107
+ Process.kill( :TERM, pid )
108
+ rescue Errno::ESRCH => e
109
+ puts e.class
110
+ end
111
+ end
112
+
113
+ Process.waitall
114
+ else
115
+ P2p2::P2pdWorker.new( p2pd_port, p2pd_tmp_dir ).looping
116
+ end
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,78 @@
1
+ module P2p2
2
+ class P2pdWorker
3
+
4
+ def initialize( p2pd_port, p2pd_tmp_dir )
5
+ p2pd = Socket.new( Socket::AF_INET, Socket::SOCK_DGRAM, 0 )
6
+ p2pd.setsockopt( Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 )
7
+ p2pd.bind( Socket.pack_sockaddr_in( p2pd_port, '0.0.0.0' ) )
8
+
9
+ @p2pd = p2pd
10
+ @p2pd_tmp_dir = p2pd_tmp_dir
11
+ end
12
+
13
+ def looping
14
+ puts 'looping'
15
+
16
+ loop do
17
+ rs, _ = IO.select( [ @p2pd ] )
18
+ read_p2pd( rs.first )
19
+ end
20
+ rescue Interrupt => e
21
+ puts e.class
22
+ quit!
23
+ end
24
+
25
+ def quit!
26
+ exit
27
+ end
28
+
29
+ private
30
+
31
+ def read_p2pd( p2pd )
32
+ data, addrinfo, rflags, *controls = p2pd.recvmsg
33
+ return if ( data.bytesize == 1 ) || ( data.bytesize > 255 ) || ( data =~ /\/|\.|\ / )
34
+
35
+ from_addr = addrinfo.to_sockaddr
36
+ room_path = File.join( @p2pd_tmp_dir, data.gsub( "\u0000" , '' ) )
37
+
38
+ unless File.exist?( room_path )
39
+ puts "#{ Time.new } create #{ room_path } #{ addrinfo.inspect }"
40
+ write_room( room_path, from_addr )
41
+ return
42
+ end
43
+
44
+ if Time.new - File.mtime( room_path ) > EXPIRE_AFTER
45
+ puts "#{ Time.new } overwrite #{ room_path } #{ addrinfo.inspect }"
46
+ write_room( room_path, from_addr )
47
+ return
48
+ end
49
+
50
+ op_addr = IO.binread( room_path )
51
+ op_addrinfo = Addrinfo.new( op_addr )
52
+
53
+ if ( addrinfo.ip_address == op_addrinfo.ip_address ) || ( addrinfo.ip_port == op_addrinfo.ip_port )
54
+ write_room( room_path, from_addr )
55
+ else
56
+ puts "#{ Time.new } paired #{ addrinfo.inspect } #{ op_addrinfo.inspect }"
57
+ send_pack( [ [ 0, PEER_ADDR ].pack( 'Q>C' ), op_addr ].join, from_addr )
58
+ send_pack( [ [ 0, PEER_ADDR ].pack( 'Q>C' ), from_addr ].join, op_addr )
59
+ end
60
+ end
61
+
62
+ def write_room( room_path, data )
63
+ begin
64
+ IO.binwrite( room_path, data )
65
+ rescue Errno::EISDIR, Errno::ENAMETOOLONG, Errno::ENOENT, ArgumentError => e
66
+ puts "binwrite #{ e.class } #{ Time.new }"
67
+ end
68
+ end
69
+
70
+ def send_pack( data, target_addr )
71
+ begin
72
+ @p2pd.sendmsg( data, 0, target_addr )
73
+ rescue IO::WaitWritable, Errno::EINTR => e
74
+ puts "#{ Time.new } sendmsg ignore #{ e.class }"
75
+ end
76
+ end
77
+ end
78
+ end
@@ -1,3 +1,3 @@
1
- module P2p2
2
- VERSION = '0.14.0'.freeze
3
- end
1
+ module P2p2
2
+ VERSION = '0.18.0'.freeze
3
+ end
@@ -1,29 +1,34 @@
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/custom.rb
21
+ lib/p2p2/head.rb
22
+ lib/p2p2/p1_custom.rb
23
+ lib/p2p2/p1_worker.rb
24
+ lib/p2p2/p1.rb
25
+ lib/p2p2/p2_custom.rb
26
+ lib/p2p2/p2_worker.rb
27
+ lib/p2p2/p2.rb
28
+ lib/p2p2/p2pd_worker.rb
29
+ lib/p2p2/p2pd.rb
30
+ lib/p2p2/version.rb
31
+ ]
32
+
33
+ spec.require_paths = ["lib"]
34
+ 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.14.0
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - takafan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-03 00:00:00.000000000 Z
11
+ date: 2020-07-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 内网里的任意应用,访问另一个内网里的应用服务端。
14
14
  email:
@@ -18,11 +18,16 @@ extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
20
  - lib/p2p2.rb
21
+ - lib/p2p2/custom.rb
21
22
  - lib/p2p2/head.rb
22
- - lib/p2p2/hex.rb
23
23
  - lib/p2p2/p1.rb
24
+ - lib/p2p2/p1_custom.rb
25
+ - lib/p2p2/p1_worker.rb
24
26
  - lib/p2p2/p2.rb
27
+ - lib/p2p2/p2_custom.rb
28
+ - lib/p2p2/p2_worker.rb
25
29
  - lib/p2p2/p2pd.rb
30
+ - lib/p2p2/p2pd_worker.rb
26
31
  - lib/p2p2/version.rb
27
32
  - p2p2.gemspec
28
33
  homepage: https://github.com/takafan/p2p2
@@ -44,7 +49,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
44
49
  - !ruby/object:Gem::Version
45
50
  version: '0'
46
51
  requirements: []
47
- rubygems_version: 3.0.4
52
+ rubyforge_project:
53
+ rubygems_version: 2.7.6.2
48
54
  signing_key:
49
55
  specification_version: 4
50
56
  summary: p2p