p2p2 0.15.1 → 0.20.0

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