devp2p 0.2.0 → 0.3.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/devp2p.rb +14 -29
- data/lib/devp2p/app.rb +70 -0
- data/lib/devp2p/command.rb +1 -1
- data/lib/devp2p/connection_monitor.rb +27 -21
- data/lib/devp2p/discovery.rb +1 -1
- data/lib/devp2p/discovery/protocol.rb +2 -2
- data/lib/devp2p/discovery/service.rb +108 -49
- data/lib/devp2p/p2p_protocol.rb +9 -9
- data/lib/devp2p/peer.rb +53 -59
- data/lib/devp2p/peer_manager.rb +77 -39
- data/lib/devp2p/{base_protocol.rb → protocol.rb} +19 -17
- data/lib/devp2p/service.rb +50 -0
- data/lib/devp2p/sync_queue.rb +58 -45
- data/lib/devp2p/version.rb +2 -1
- data/lib/devp2p/wired_service.rb +3 -3
- metadata +19 -35
- data/lib/devp2p/app_helper.rb +0 -85
- data/lib/devp2p/base_app.rb +0 -88
- data/lib/devp2p/base_service.rb +0 -55
- data/lib/devp2p/control.rb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7da6641d9e8596c7a5ef84501b60dba802a38c7d
|
4
|
+
data.tar.gz: eb5ae074cca21812736d03f67949648242482b87
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2580541428dc68edea68859e888e235c940637fe2219759d35a58ba3256d96d7de364a343c74935bf714b7c4f54c8be3fc1291e0a6d099bf32df38973c0678c2
|
7
|
+
data.tar.gz: 95f168e5a41dc87646a55dbc794a0cb64984fc8e10aef647f7b94fa09820f1cc6645bdb6e1b6fa625925d618df1b436a99aabc8a8d07611ca1f28f32a739a634
|
data/lib/devp2p.rb
CHANGED
@@ -1,16 +1,9 @@
|
|
1
1
|
# -*- encoding : ascii-8bit -*-
|
2
2
|
|
3
|
+
require 'concurrent'
|
3
4
|
require 'block_logger'
|
4
|
-
require 'celluloid/io'
|
5
|
-
|
6
5
|
require 'rlp'
|
7
6
|
|
8
|
-
#Celluloid.exception_handler do |ex|
|
9
|
-
# puts "!!!!! Exception raised in celluloid actor:"
|
10
|
-
# puts ex
|
11
|
-
# puts ex.backtrace[0,20].join("\n")
|
12
|
-
#end
|
13
|
-
|
14
7
|
module DEVp2p
|
15
8
|
Logger = BlockLogger
|
16
9
|
|
@@ -22,36 +15,28 @@ end
|
|
22
15
|
|
23
16
|
require 'devp2p/version'
|
24
17
|
|
25
|
-
require 'devp2p/configurable'
|
26
|
-
require 'devp2p/utils'
|
27
18
|
require 'devp2p/exception'
|
19
|
+
require 'devp2p/crypto'
|
20
|
+
require 'devp2p/utils'
|
21
|
+
require 'devp2p/configurable'
|
28
22
|
|
29
|
-
require 'devp2p/
|
30
|
-
require 'devp2p/
|
23
|
+
require 'devp2p/app'
|
24
|
+
require 'devp2p/service'
|
31
25
|
require 'devp2p/wired_service'
|
32
26
|
|
33
|
-
require 'devp2p/kademlia'
|
34
|
-
require 'devp2p/discovery'
|
35
|
-
|
36
27
|
require 'devp2p/sync_queue'
|
37
|
-
|
38
|
-
require 'devp2p/packet'
|
39
28
|
require 'devp2p/frame'
|
29
|
+
require 'devp2p/packet'
|
40
30
|
require 'devp2p/multiplexer'
|
41
|
-
|
42
|
-
require 'devp2p/crypto'
|
43
|
-
require 'devp2p/rlpx_session'
|
44
31
|
require 'devp2p/multiplexed_session'
|
32
|
+
require 'devp2p/rlpx_session'
|
45
33
|
|
46
|
-
require 'devp2p/
|
47
|
-
require 'devp2p/
|
34
|
+
require 'devp2p/kademlia'
|
35
|
+
require 'devp2p/discovery'
|
48
36
|
require 'devp2p/connection_monitor'
|
37
|
+
require 'devp2p/command'
|
38
|
+
require 'devp2p/protocol'
|
49
39
|
require 'devp2p/p2p_protocol'
|
50
|
-
|
51
|
-
require 'devp2p/peer'
|
52
|
-
require 'devp2p/peer_errors'
|
53
40
|
require 'devp2p/peer_manager'
|
54
|
-
|
55
|
-
require 'devp2p/
|
56
|
-
require 'devp2p/app_helper'
|
57
|
-
|
41
|
+
require 'devp2p/peer_errors'
|
42
|
+
require 'devp2p/peer'
|
data/lib/devp2p/app.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# -*- encoding : ascii-8bit -*-
|
2
|
+
require 'hashie'
|
3
|
+
|
4
|
+
module DEVp2p
|
5
|
+
class App
|
6
|
+
include Concurrent::Async
|
7
|
+
|
8
|
+
extend Configurable
|
9
|
+
add_config(
|
10
|
+
default_config: {
|
11
|
+
client_version_string: "ruby-devp2p #{VersionString}",
|
12
|
+
deactivated_services: []
|
13
|
+
}
|
14
|
+
)
|
15
|
+
|
16
|
+
attr :config, :services
|
17
|
+
|
18
|
+
def initialize(config=default_config)
|
19
|
+
super()
|
20
|
+
|
21
|
+
@config = Hashie::Mash.new(default_config).merge(config)
|
22
|
+
@registry = {}
|
23
|
+
@services = Hashie::Mash.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def register_service(klass, *args)
|
27
|
+
raise ArgumentError, "service #{klass.name} already registered" if services.has_key?(klass.name)
|
28
|
+
|
29
|
+
logger.info "registering service", service: klass.name
|
30
|
+
@registry[klass.name] = [klass, args]
|
31
|
+
services[klass.name] = klass.new(*args)
|
32
|
+
end
|
33
|
+
|
34
|
+
def deregister_service(klass)
|
35
|
+
raise ArgumentError, "service #{klass.name} not registered" unless services.has_key?(klass.name)
|
36
|
+
|
37
|
+
logger.info "deregistering service", service: klass.name
|
38
|
+
services[klass.name].async.stop
|
39
|
+
services.delete klass.name
|
40
|
+
@registry.delete klass.name
|
41
|
+
end
|
42
|
+
|
43
|
+
def start
|
44
|
+
@registry.each do |name, (klass, args)|
|
45
|
+
services[name] ||= klass.new(*args)
|
46
|
+
services[name].async.start
|
47
|
+
end
|
48
|
+
rescue
|
49
|
+
puts $!
|
50
|
+
puts $!.backtrace[0,10].join("\n")
|
51
|
+
end
|
52
|
+
|
53
|
+
def stop
|
54
|
+
services.keys.each do |name|
|
55
|
+
services[name].async.stop
|
56
|
+
services.delete name
|
57
|
+
end
|
58
|
+
rescue
|
59
|
+
puts $!
|
60
|
+
puts $!.backtrace[0,10].join("\n")
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def logger
|
66
|
+
@logger ||= Logger.new 'app'
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
data/lib/devp2p/command.rb
CHANGED
@@ -64,7 +64,7 @@ module DEVp2p
|
|
64
64
|
# optionally implement create
|
65
65
|
def create(proto, *args)
|
66
66
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
67
|
-
raise ArgumentError, "proto #{proto} must be protocol" unless proto.is_a?(
|
67
|
+
raise ArgumentError, "proto #{proto} must be protocol" unless proto.is_a?(Protocol)
|
68
68
|
raise ArgumentError, "command structure mismatch" if !options.empty? && structure.instance_of?(RLP::Sedes::CountableList)
|
69
69
|
options.empty? ? args : options
|
70
70
|
end
|
@@ -6,7 +6,7 @@ module DEVp2p
|
|
6
6
|
# monitors the connection by sending pings and checking pongs
|
7
7
|
#
|
8
8
|
class ConnectionMonitor
|
9
|
-
include
|
9
|
+
include Concurrent::Async
|
10
10
|
|
11
11
|
def initialize(proto)
|
12
12
|
@proto = proto
|
@@ -28,8 +28,10 @@ module DEVp2p
|
|
28
28
|
}
|
29
29
|
@proto.receive_pong_callbacks.push(track_response)
|
30
30
|
|
31
|
-
monitor =
|
32
|
-
|
31
|
+
monitor = self
|
32
|
+
# FIXME: sleep 1 to make sure ConnectionMonitor start after connection of
|
33
|
+
# other protocols like ETHProtocol
|
34
|
+
@proto.receive_hello_callbacks.push(->(p, **kwargs) { sleep 1; monitor.start })
|
33
35
|
end
|
34
36
|
|
35
37
|
def latency(num_samples=@max_samples)
|
@@ -38,38 +40,42 @@ module DEVp2p
|
|
38
40
|
(0...num_samples).map {|i| @samples[i] }.reduce(0, &:+)
|
39
41
|
end
|
40
42
|
|
41
|
-
def
|
42
|
-
logger.debug 'started', monitor:
|
43
|
-
loop do
|
44
|
-
logger.debug 'pinging', monitor: Actor.current
|
45
|
-
@proto.send_ping
|
43
|
+
def start
|
44
|
+
logger.debug 'started', monitor: self
|
46
45
|
|
47
|
-
|
48
|
-
|
46
|
+
logger.debug 'pinging', monitor: self
|
47
|
+
@proto.async.send_ping
|
48
|
+
now = @last_request = Time.now
|
49
|
+
|
50
|
+
@task = Concurrent::TimerTask.new(execution_interval: @ping_interval) do
|
49
51
|
logger.debug('latency', peer: @proto, latency: ("%.3f" % latency))
|
50
52
|
|
51
53
|
if now - @last_response > @response_delay_threshold
|
52
|
-
logger.debug "unresponsive_peer", monitor:
|
53
|
-
@proto.peer.report_error 'not responding to ping'
|
54
|
-
@proto.stop
|
55
|
-
terminate
|
54
|
+
logger.debug "unresponsive_peer", monitor: self
|
55
|
+
@proto.peer.async.report_error 'not responding to ping'
|
56
|
+
@proto.async.stop
|
56
57
|
end
|
57
|
-
end
|
58
|
-
end
|
59
58
|
|
60
|
-
|
61
|
-
|
59
|
+
logger.debug 'pinging', monitor: self
|
60
|
+
@proto.async.send_ping
|
61
|
+
now = @last_request = Time.now
|
62
|
+
end
|
63
|
+
@task.execute
|
64
|
+
rescue
|
65
|
+
puts $!
|
66
|
+
puts $!.backtrace[0,10].join("\n")
|
62
67
|
end
|
63
68
|
|
64
69
|
def stop
|
65
|
-
logger.debug 'stopped', monitor:
|
66
|
-
|
70
|
+
logger.debug 'stopped', monitor: self
|
71
|
+
@task.shutdown
|
72
|
+
@task = nil
|
67
73
|
end
|
68
74
|
|
69
75
|
private
|
70
76
|
|
71
77
|
def logger
|
72
|
-
@logger ||= Logger.new("
|
78
|
+
@logger ||= Logger.new("p2p.ctxmonitor")
|
73
79
|
end
|
74
80
|
|
75
81
|
end
|
data/lib/devp2p/discovery.rb
CHANGED
@@ -173,7 +173,7 @@ module DEVp2p
|
|
173
173
|
get_node(nodeid, address) unless @nodes.has_key?(nodeid)
|
174
174
|
send cmd, nodeid, payload, mdc
|
175
175
|
rescue
|
176
|
-
logger.error 'invalid message', error:
|
176
|
+
logger.error 'invalid message', error: $!, from: address
|
177
177
|
end
|
178
178
|
|
179
179
|
def send_message(node, message)
|
@@ -319,7 +319,7 @@ module DEVp2p
|
|
319
319
|
private
|
320
320
|
|
321
321
|
def logger
|
322
|
-
@logger ||= Logger.new("
|
322
|
+
@logger ||= Logger.new("p2p.discovery").tap {|l| l.level = :info }
|
323
323
|
end
|
324
324
|
|
325
325
|
def encode_cmd_id(cmd_id)
|
@@ -3,12 +3,82 @@
|
|
3
3
|
module DEVp2p
|
4
4
|
module Discovery
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
class Service < BaseService
|
10
|
-
include Celluloid::IO
|
6
|
+
class Receiver
|
7
|
+
include Concurrent::Async
|
11
8
|
|
9
|
+
def initialize(service, socket)
|
10
|
+
super()
|
11
|
+
|
12
|
+
@service = service
|
13
|
+
@socket = socket
|
14
|
+
|
15
|
+
@stopped = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def start
|
19
|
+
maxlen = Multiplexer.max_window_size * 2
|
20
|
+
|
21
|
+
loop do
|
22
|
+
break if @stopped || @socket.closed?
|
23
|
+
|
24
|
+
message, info = @socket.recvfrom maxlen
|
25
|
+
handle_packet message, info[3], info[1]
|
26
|
+
end
|
27
|
+
rescue
|
28
|
+
puts $!
|
29
|
+
puts $!.backtrace[0,10].join("\n")
|
30
|
+
end
|
31
|
+
|
32
|
+
def stop
|
33
|
+
@stopped = true
|
34
|
+
end
|
35
|
+
|
36
|
+
def handle_packet(message, ip, port)
|
37
|
+
logger.debug "handling packet", ip: ip, port: port, size: message.size
|
38
|
+
@service.async.receive_message Address.new(ip, port), message
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def logger
|
44
|
+
@logger ||= Logger.new "p2p.discovery"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Sender
|
49
|
+
include Concurrent::Async
|
50
|
+
|
51
|
+
def initialize(service, socket)
|
52
|
+
super()
|
53
|
+
|
54
|
+
@service = service
|
55
|
+
@socket = socket
|
56
|
+
|
57
|
+
@stopped = false
|
58
|
+
end
|
59
|
+
|
60
|
+
def start
|
61
|
+
# do nothing
|
62
|
+
end
|
63
|
+
|
64
|
+
def send_message(address, message)
|
65
|
+
raise ArgumentError, 'address must be Address' unless address.instance_of?(Address)
|
66
|
+
logger.debug "sending", size: message.size, to: address
|
67
|
+
|
68
|
+
@socket.send message, 0, address.ip, address.udp_port
|
69
|
+
rescue
|
70
|
+
puts $!
|
71
|
+
puts $!.backtrace[0,10].join("\n")
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def logger
|
77
|
+
@logger ||= Logger.new "p2p.discovery"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class Service < ::DEVp2p::Service
|
12
82
|
name 'discovery'
|
13
83
|
|
14
84
|
default_config(
|
@@ -27,33 +97,8 @@ module DEVp2p
|
|
27
97
|
super(app)
|
28
98
|
logger.info "Discovery service init"
|
29
99
|
|
30
|
-
@
|
31
|
-
@protocol = Protocol.new app,
|
32
|
-
end
|
33
|
-
|
34
|
-
def address
|
35
|
-
ip = @app.config[:discovery][:listen_host]
|
36
|
-
port = @app.config[:discovery][:listen_port]
|
37
|
-
Address.new ip, port
|
38
|
-
end
|
39
|
-
|
40
|
-
def send_message(address, message)
|
41
|
-
raise ArgumentError, 'address must be Address' unless address.instance_of?(Address)
|
42
|
-
logger.debug "sending", size: message.size, to: address
|
43
|
-
|
44
|
-
begin
|
45
|
-
@server.send message, 0, address.ip, address.udp_port
|
46
|
-
rescue
|
47
|
-
# should never reach here? udp has no connection!
|
48
|
-
logger.error "udp write error", error: $!
|
49
|
-
logger.error "waiting for recovery"
|
50
|
-
sleep 5
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def receive_message(address, message)
|
55
|
-
raise ArgumentError, 'address must be Address' unless address.instance_of?(Address)
|
56
|
-
@protocol.receive_message address, message
|
100
|
+
@socket = nil
|
101
|
+
@protocol = Protocol.new app, self
|
57
102
|
end
|
58
103
|
|
59
104
|
def start
|
@@ -64,38 +109,52 @@ module DEVp2p
|
|
64
109
|
|
65
110
|
logger.info "starting udp listener", port: port, host: ip
|
66
111
|
|
67
|
-
@
|
68
|
-
@
|
112
|
+
@socket = UDPSocket.new
|
113
|
+
@socket.bind ip, port
|
69
114
|
|
70
|
-
|
115
|
+
@receiver = Receiver.new self, @socket
|
116
|
+
@sender = Sender.new self, @socket
|
117
|
+
@receiver.async.start
|
118
|
+
@sender.async.start
|
71
119
|
|
72
120
|
nodes = @app.config[:discovery][:bootstrap_nodes] || []
|
73
121
|
@protocol.bootstrap( nodes.map {|x| Node.from_uri(x) } )
|
122
|
+
rescue
|
123
|
+
puts $!
|
124
|
+
puts $!.backtrace[0,10].join("\n")
|
74
125
|
end
|
75
126
|
|
76
127
|
def stop
|
77
128
|
logger.info "stopping discovery"
|
78
|
-
|
129
|
+
|
130
|
+
@socket.close if @socket
|
131
|
+
@sender.async.stop if @sender
|
132
|
+
@receiver.async.stop if @receiver
|
133
|
+
|
134
|
+
@socket = nil
|
135
|
+
@sender = nil
|
136
|
+
@receiver = nil
|
79
137
|
end
|
80
138
|
|
81
|
-
|
139
|
+
def address
|
140
|
+
ip = @app.config[:discovery][:listen_host]
|
141
|
+
port = @app.config[:discovery][:listen_port]
|
142
|
+
Address.new ip, port
|
143
|
+
end
|
82
144
|
|
83
|
-
def
|
84
|
-
|
145
|
+
def receive_message(address, message)
|
146
|
+
raise ArgumentError, 'address must be Address' unless address.instance_of?(Address)
|
147
|
+
@protocol.receive_message address, message
|
85
148
|
end
|
86
149
|
|
87
|
-
def
|
88
|
-
|
89
|
-
loop do
|
90
|
-
break if stopped?
|
91
|
-
message, info = @server.recvfrom maxlen
|
92
|
-
async.handle_packet message, info[3], info[1]
|
93
|
-
end
|
150
|
+
def send_message(address, message)
|
151
|
+
@sender.async.send_message address, message
|
94
152
|
end
|
95
153
|
|
96
|
-
|
97
|
-
|
98
|
-
|
154
|
+
private
|
155
|
+
|
156
|
+
def logger
|
157
|
+
@logger ||= Logger.new "p2p.discovery"
|
99
158
|
end
|
100
159
|
|
101
160
|
end
|