p2p2 0.14.0 → 0.18.0

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