p2p2 0.15.1 → 0.20.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 'json'
1
2
  require 'p2p2/head'
3
+ require 'p2p2/p2pd_worker'
2
4
  require 'p2p2/version'
3
5
  require 'socket'
4
6
 
5
7
  ##
6
8
  # P2p2::P2pd - 内网里的任意应用,访问另一个内网里的应用服务端。配对服务器端。
7
9
  #
8
- # 1.
10
+ # 包结构
11
+ # ======
9
12
  #
10
- # ```
11
- # p2pd
12
- # ^ ^
13
- # ^ ^
14
- # “周立波的房间” “周立波的房间”
15
- # ^ ^
16
- # ^ ^
17
- # p1 --> nat --><-- nat <-- p2
13
+ # tund-p2pd, tun-p2pd:
18
14
  #
19
- # ```
15
+ # room
20
16
  #
21
- # 2.
17
+ # p2pd-tund, p2pd-tun:
22
18
  #
23
- # ```
24
- # ssh --> p2 --> (encode) --> p1 --> (decode) --> sshd
25
- # ```
19
+ # Q>: 0 ctlmsg -> C: 1 peer addr -> tun sockaddr / tund sockaddr
26
20
  #
27
- # usage
28
- # =====
21
+ # tun-tund:
29
22
  #
30
- # 1. Girl::P2pd.new( 5050 ).looping # @server
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
31
35
  #
32
- # 2. Girl::P1.new( 'your.server.ip', 5050, '127.0.0.1', 22, '周立波' ).looping # @home1
36
+ # Q>: 1+ pack_id -> Q>/n: src id / dst port -> traffic
33
37
  #
34
- # 3. Girl::P2.new( 'your.server.ip', 5050, '0.0.0.0', 2222, '周立波' ).looping # @home2
38
+ # close logic
39
+ # ===========
35
40
  #
36
- # 4. ssh -p2222 libo@localhost
41
+ # 1-1. after close src -> dst closed ? no -> send fin1
42
+ # 1-2. tun recv fin2 -> del src ext
37
43
  #
38
- # 包结构
39
- # ======
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
40
50
  #
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
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
55
54
  #
56
55
  module P2p2
57
56
  class P2pd
58
57
 
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' ) )
58
+ def initialize( config_path = nil )
59
+ unless config_path
60
+ config_path = File.expand_path( '../p2p2.conf.json', __FILE__ )
61
+ end
66
62
 
67
- @p2pd = p2pd
68
- @p2pd_dir = p2pd_dir
69
- end
63
+ unless File.exist?( config_path )
64
+ raise "missing config file #{ config_path }"
65
+ end
70
66
 
71
- def looping
72
- puts 'looping'
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 ]
73
70
 
74
- loop do
75
- rs, _ = IO.select( [ @p2pd ] )
76
- read_p2pd( rs.first )
71
+ unless p2pd_port
72
+ p2pd_port = 2020
77
73
  end
78
- rescue Interrupt => e
79
- puts e.class
80
- quit!
81
- end
82
74
 
83
- def quit!
84
- exit
85
- end
75
+ unless p2pd_tmp_dir
76
+ p2pd_tmp_dir = '/tmp/p2p2.p2pd'
77
+ end
86
78
 
87
- private
79
+ unless File.exist?( p2pd_tmp_dir )
80
+ Dir.mkdir( p2pd_tmp_dir )
81
+ end
88
82
 
89
- def read_p2pd( p2pd )
90
- data, addrinfo, rflags, *controls = p2pd.recvmsg
91
- return if ( data.bytesize == 1 ) || ( data.bytesize > 255 ) || ( data =~ /\/|\.|\ / )
83
+ title = "p2p2 p2pd #{ P2p2::VERSION }"
84
+ puts title
85
+ puts "p2pd port #{ p2pd_port }"
86
+ puts "p2pd tmp dir #{ p2pd_tmp_dir }"
92
87
 
93
- sockaddr = addrinfo.to_sockaddr
94
- title_path = File.join( @p2pd_dir, data.gsub( "\u0000" , '' ) )
88
+ if RUBY_PLATFORM.include?( 'linux' )
89
+ $0 = title
95
90
 
96
- unless File.exist?( title_path )
97
- write_title( title_path, sockaddr )
98
- return
99
- end
91
+ pid = fork do
92
+ $0 = 'p2p2 p2pd worker'
93
+ worker = P2p2::P2pdWorker.new( p2pd_port, p2pd_tmp_dir )
100
94
 
101
- if Time.new - File.mtime( title_path ) > 300
102
- write_title( title_path, sockaddr )
103
- return
104
- end
95
+ Signal.trap( :TERM ) do
96
+ puts 'exit'
97
+ worker.quit!
98
+ end
105
99
 
106
- op_sockaddr = IO.binread( title_path )
100
+ worker.looping
101
+ end
107
102
 
108
- if Addrinfo.new( op_sockaddr ).ip_address == addrinfo.ip_address
109
- write_title( title_path, sockaddr )
110
- return
111
- end
103
+ Signal.trap( :TERM ) do
104
+ puts 'trap TERM'
112
105
 
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
106
+ begin
107
+ Process.kill( :TERM, pid )
108
+ rescue Errno::ESRCH => e
109
+ puts e.class
110
+ end
111
+ end
116
112
 
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 }"
113
+ Process.waitall
114
+ else
115
+ P2p2::P2pdWorker.new( p2pd_port, p2pd_tmp_dir ).looping
123
116
  end
124
117
  end
125
118
 
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
119
  end
135
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
1
  module P2p2
2
- VERSION = '0.15.1'.freeze
2
+ VERSION = '0.20.0'.freeze
3
3
  end
@@ -17,10 +17,15 @@ Gem::Specification.new do |spec|
17
17
  spec.files = %w[
18
18
  p2p2.gemspec
19
19
  lib/p2p2.rb
20
+ lib/p2p2/custom.rb
20
21
  lib/p2p2/head.rb
21
- lib/p2p2/hex.rb
22
+ lib/p2p2/p1_custom.rb
23
+ lib/p2p2/p1_worker.rb
22
24
  lib/p2p2/p1.rb
25
+ lib/p2p2/p2_custom.rb
26
+ lib/p2p2/p2_worker.rb
23
27
  lib/p2p2/p2.rb
28
+ lib/p2p2/p2pd_worker.rb
24
29
  lib/p2p2/p2pd.rb
25
30
  lib/p2p2/version.rb
26
31
  ]
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.15.1
4
+ version: 0.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - takafan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-02 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