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.
@@ -20,9 +20,8 @@ module DEVp2p
20
20
  # The default implementation of `command.receive` calls callbacks which can
21
21
  # be registered in a list which is available as: `protocol.receive_X_callbacks`.
22
22
  #
23
- class BaseProtocol
24
- include Celluloid
25
- include Control
23
+ class Protocol
24
+ include Concurrent::Async
26
25
 
27
26
  extend Configurable
28
27
  add_config(
@@ -41,28 +40,31 @@ module DEVp2p
41
40
  @peer = peer
42
41
  @service = service
43
42
 
44
- initialize_control
43
+ @stopped = false
45
44
 
46
45
  setup
47
46
  end
48
47
 
49
48
  def start
50
- logger.debug 'starting', proto: Actor.current
51
- service.on_wire_protocol_start Actor.current
52
- super
49
+ logger.debug 'starting', proto: self
50
+ service.async.on_wire_protocol_start self
51
+ rescue
52
+ puts $!
53
+ puts $!.backtrace[0,10].join("\n")
53
54
  end
54
55
 
55
56
  def stop
56
- logger.debug 'stopping', proto: Actor.current
57
- service.on_wire_protocol_stop Actor.current
57
+ logger.debug 'stopping', proto: self
58
+ service.async.on_wire_protocol_stop self
58
59
 
59
- super
60
-
61
- terminate
60
+ @stopped = true
61
+ rescue
62
+ puts $!
63
+ puts $!.backtrace[0,10].join("\n")
62
64
  end
63
65
 
64
- def _run
65
- # pass
66
+ def stopped?
67
+ @stopped
66
68
  end
67
69
 
68
70
  def receive_packet(packet)
@@ -75,7 +77,7 @@ module DEVp2p
75
77
  end
76
78
 
77
79
  def send_packet(packet)
78
- peer.send_packet packet
80
+ peer.async.send_packet packet
79
81
  end
80
82
 
81
83
  def to_s
@@ -98,14 +100,14 @@ module DEVp2p
98
100
 
99
101
  raise DuplicatedCommand unless klasses.map(&:cmd_id).uniq.size == klasses.size
100
102
 
101
- proto = Actor.current
103
+ proto = self
102
104
 
103
105
  klasses.each do |klass|
104
106
  instance = klass.new
105
107
 
106
108
  # decode rlp, create hash, call receive
107
109
  receive = lambda do |packet|
108
- raise ArgumentError unless packet.is_a?(Packet)
110
+ raise ArgumentError, "packet is not a Packet: #{packet.inspect}" unless packet.is_a?(Packet)
109
111
  instance.receive proto, klass.decode_payload(packet.payload)
110
112
  end
111
113
 
@@ -0,0 +1,50 @@
1
+ # -*- encoding : ascii-8bit -*-
2
+
3
+ module DEVp2p
4
+
5
+ class Service
6
+ include Concurrent::Async
7
+
8
+ extend Configurable
9
+ add_config(
10
+ name: '',
11
+ default_config: {},
12
+ required_services: []
13
+ )
14
+
15
+ class <<self
16
+ def register_with_app(app)
17
+ app.register_service self, app
18
+ end
19
+ end
20
+
21
+ attr :app, :config
22
+
23
+ def initialize(app)
24
+ super()
25
+
26
+ @app = app
27
+ @config = app.config.reverse_merge(default_config)
28
+
29
+ available_services = app.services.each_value.map(&:class)
30
+ required_services.each do |r|
31
+ raise MissingRequiredServiceError, "require service #{r}" unless available_services.include?(r)
32
+ end
33
+ end
34
+
35
+ def start
36
+ raise NotImplemented
37
+ end
38
+
39
+ def stop
40
+ raise NotImplemented
41
+ end
42
+
43
+ def to_s
44
+ "<Service #{name}##{object_id}>"
45
+ end
46
+ alias inspect to_s
47
+
48
+ end
49
+
50
+ end
@@ -1,8 +1,7 @@
1
1
  # -*- encoding : ascii-8bit -*-
2
2
 
3
- ##
4
- # A naive synchronized queue for Celluloid actors.
5
- #
3
+ require 'thread'
4
+
6
5
  class SyncQueue
7
6
 
8
7
  attr :queue, :max_size
@@ -12,69 +11,83 @@ class SyncQueue
12
11
  @num_waiting = 0
13
12
 
14
13
  @max_size = max_size
15
- @cond_full = Celluloid::Condition.new
16
- @cond_empty = Celluloid::Condition.new
14
+
15
+ @mutex = Mutex.new
16
+ @cond_full = ConditionVariable.new
17
+ @cond_empty = ConditionVariable.new
17
18
  end
18
19
 
19
20
  def enq(obj, non_block=false)
20
- loop do
21
- if full?
22
- if non_block
23
- raise ThreadError, 'queue full'
24
- else
25
- begin
26
- @num_waiting += 1
27
- @cond_full.wait
28
- ensure
29
- @num_waiting -= 1
21
+ Thread.handle_interrupt(StandardError => :on_blocking) do
22
+ loop do
23
+ @mutex.synchronize do
24
+ if full?
25
+ if non_block
26
+ raise ThreadError, 'queue full'
27
+ else
28
+ begin
29
+ @num_waiting += 1
30
+ @cond_full.wait @mutex
31
+ ensure
32
+ @num_waiting -= 1
33
+ end
34
+ end
35
+ else
36
+ @queue.push obj
37
+ @cond_empty.signal
38
+ return obj
30
39
  end
31
40
  end
32
- else
33
- @queue.push obj
34
- @cond_empty.signal
35
- return obj
36
41
  end
37
42
  end
38
43
  end
39
44
  alias << enq
40
45
 
41
46
  def deq(non_block=false)
42
- loop do
43
- if empty?
44
- if non_block
45
- raise ThreadError, 'queue empty'
46
- else
47
- begin
48
- @num_waiting += 1
49
- @cond_empty.wait
50
- ensure
51
- @num_waiting -= 1
47
+ Thread.handle_interrupt(StandardError => :on_blocking) do
48
+ loop do
49
+ @mutex.synchronize do
50
+ if empty?
51
+ if non_block
52
+ raise ThreadError, 'queue empty'
53
+ else
54
+ begin
55
+ @num_waiting += 1
56
+ @cond_empty.wait @mutex
57
+ ensure
58
+ @num_waiting -= 1
59
+ end
60
+ end
61
+ else
62
+ obj = @queue.shift
63
+ @cond_full.signal
64
+ return obj
52
65
  end
53
66
  end
54
- else
55
- obj = @queue.shift
56
- @cond_full.signal
57
- return obj
58
67
  end
59
68
  end
60
69
  end
61
70
 
62
71
  # Same as pop except it will not remove the element from queue, just peek.
63
72
  def peek(non_block=false)
64
- loop do
65
- if empty?
66
- if non_block
67
- raise ThreadError, 'queue empty'
68
- else
69
- begin
70
- @num_waiting += 1
71
- @cond_empty.wait
72
- ensure
73
- @num_waiting -= 1
73
+ Thread.handle_interrupt(StandardError => :on_blocking) do
74
+ loop do
75
+ @mutex.synchronize do
76
+ if empty?
77
+ if non_block
78
+ raise ThreadError, 'queue empty'
79
+ else
80
+ begin
81
+ @num_waiting += 1
82
+ @cond_empty.wait @mutex
83
+ ensure
84
+ @num_waiting -= 1
85
+ end
86
+ end
87
+ else
88
+ return @queue[0]
74
89
  end
75
90
  end
76
- else
77
- return @queue[0]
78
91
  end
79
92
  end
80
93
  end
@@ -1,6 +1,7 @@
1
1
  # -*- encoding : ascii-8bit -*-
2
+
2
3
  module DEVp2p
3
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0'
4
5
 
5
6
  VersionString = begin
6
7
  git_describe_re = /^(?<version>v\d+\.\d+\.\d+)-(?<git>\d+-g[a-fA-F0-9]+(?:-dirty)?)$/
@@ -12,17 +12,17 @@ module DEVp2p
12
12
  # with instances of Peer and WiredService
13
13
  # WiredService.wire_protocol(Peer.new, WiredService.new)
14
14
  #
15
- class WiredService < BaseService
15
+ class WiredService < Service
16
16
  name 'wired'
17
17
 
18
18
  attr_accessor :wire_protocol
19
19
 
20
20
  def on_wire_protocol_start(proto)
21
- raise ArgumentError, "argument is not a protocol" unless proto.is_a?(BaseProtocol)
21
+ raise ArgumentError, "argument is not a protocol" unless proto.is_a?(::DEVp2p::Protocol)
22
22
  end
23
23
 
24
24
  def on_wire_protocol_stop(proto)
25
- raise ArgumentError, "argument is not a protocol" unless proto.is_a?(BaseProtocol)
25
+ raise ArgumentError, "argument is not a protocol" unless proto.is_a?(::DEVp2p::Protocol)
26
26
  end
27
27
 
28
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devp2p
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Xie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-19 00:00:00.000000000 Z
11
+ date: 2016-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -38,34 +38,6 @@ dependencies:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.1.2
41
- - !ruby/object:Gem::Dependency
42
- name: celluloid
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '0.17'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '0.17'
55
- - !ruby/object:Gem::Dependency
56
- name: celluloid-io
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 0.17.3
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 0.17.3
69
41
  - !ruby/object:Gem::Dependency
70
42
  name: digest-sha3
71
43
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +80,20 @@ dependencies:
108
80
  - - ">="
109
81
  - !ruby/object:Gem::Version
110
82
  version: 0.7.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: concurrent-ruby
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
111
97
  - !ruby/object:Gem::Dependency
112
98
  name: rake
113
99
  requirement: !ruby/object:Gem::Requirement
@@ -162,14 +148,10 @@ files:
162
148
  - LICENSE
163
149
  - README.md
164
150
  - lib/devp2p.rb
165
- - lib/devp2p/app_helper.rb
166
- - lib/devp2p/base_app.rb
167
- - lib/devp2p/base_protocol.rb
168
- - lib/devp2p/base_service.rb
151
+ - lib/devp2p/app.rb
169
152
  - lib/devp2p/command.rb
170
153
  - lib/devp2p/configurable.rb
171
154
  - lib/devp2p/connection_monitor.rb
172
- - lib/devp2p/control.rb
173
155
  - lib/devp2p/crypto.rb
174
156
  - lib/devp2p/crypto/ecc_x.rb
175
157
  - lib/devp2p/crypto/ecies.rb
@@ -194,7 +176,9 @@ files:
194
176
  - lib/devp2p/peer.rb
195
177
  - lib/devp2p/peer_errors.rb
196
178
  - lib/devp2p/peer_manager.rb
179
+ - lib/devp2p/protocol.rb
197
180
  - lib/devp2p/rlpx_session.rb
181
+ - lib/devp2p/service.rb
198
182
  - lib/devp2p/sync_queue.rb
199
183
  - lib/devp2p/utils.rb
200
184
  - lib/devp2p/version.rb
@@ -1,85 +0,0 @@
1
- # -*- encoding : ascii-8bit -*-
2
-
3
- module DEVp2p
4
- class AppHelper
5
-
6
- def run(app_class, service_class, num_nodes: 3, seed: 0, min_peers: 2, max_peers: 2, random_port: false)
7
- base_port = random_port ? SecureRandom.random_number(50000) + 10000 : 29870
8
-
9
- bootstrap_node_privkey = Crypto.mk_privkey "#{seed}:udp:0"
10
- bootstrap_node_pubkey = Crypto.privtopub bootstrap_node_privkey
11
- enode = Utils.host_port_pubkey_to_uri "0.0.0.0", base_port, bootstrap_node_pubkey
12
-
13
- services = [Discovery::Service, PeerManager]#, service_class]
14
-
15
- base_config = {}
16
- services.each {|s| Utils.update_config_with_defaults base_config, s.default_config }
17
-
18
- base_config[:discovery][:bootstrap_nodes] = [enode]
19
- base_config[:seed] = seed
20
- base_config[:base_port] = base_port
21
- base_config[:num_nodes] = num_nodes
22
- base_config[:min_peers] = min_peers
23
- base_config[:max_peers] = max_peers
24
-
25
- apps = []
26
- num_nodes.times do |node_num|
27
- app = create_app node_num, base_config, services, app_class
28
- apps.push app
29
- end
30
-
31
- serve_until_stopped apps
32
- end
33
-
34
- def create_app(node_num, config, services, app_class)
35
- num_nodes = config[:num_nodes]
36
- base_port = config[:base_port]
37
- seed = config[:seed]
38
- min_peers = config[:min_peers]
39
- max_peers = config[:max_peers]
40
-
41
- raise "invalid node_num" unless node_num < num_nodes
42
- #raise "invalid min/max peers" unless min_peers <= max_peers && max_peers < num_nodes
43
-
44
- config = Marshal.load Marshal.dump(config)
45
- config[:node_num] = node_num
46
-
47
- config[:node][:privkey_hex] = Utils.encode_hex Crypto.mk_privkey("#{seed}:udp:#{node_num}")
48
- config[:discovery][:listen_port] = base_port + node_num
49
- config[:p2p][:listen_port] = base_port + node_num
50
- config[:p2p][:min_peers] = [min_peers, 10].min
51
- config[:p2p][:max_peers] = max_peers
52
- config[:client_version_string] = "NODE#{node_num}"
53
-
54
- app = app_class.new config
55
-
56
- services.each do |service|
57
- raise "invalid service" unless service.instance_of?(Class) && service < BaseService
58
-
59
- if !app.config[:deactivated_services].include?(service.name)
60
- raise "service should not be active" if app.services.has_key?(service.name)
61
- service.register_with_app app
62
- raise "servier should be active" unless app.services.has_key?(service.name)
63
- end
64
- end
65
-
66
- app
67
- end
68
-
69
- def serve_until_stopped(apps)
70
- apps.each do |app|
71
- app.start
72
-
73
- if app.config[:post_app_start_callback]
74
- app.config[:post_app_start_callback].call(app)
75
- end
76
- end
77
-
78
- apps.each(&:join)
79
-
80
- # finally stop
81
- apps.each(&:stop)
82
- end
83
-
84
- end
85
- end