class DEVp2p::Protocol
A protocol mediates between the network and the service. It implements a collection of commands.
For each command X the following methods are created at initialization:
-
‘packet = protocol.create_X(*args, **kwargs)`
-
‘protocol.send_X(*args, **kwargs)`, which is a shortcut for `send_packet` plus `create_X`.
-
‘protocol.receive_X(data)`
On ‘protocol.receive_packet`, the packet is deserialized according to the `command.structure` and the `command.receive` method called with a hash containing the received data.
The default implementation of ‘command.receive` calls callbacks which can be registered in a list which is available as: `protocol.receive_X_callbacks`.
Attributes
peer[RW]
Public Class Methods
new(peer, service)
click to toggle source
# File lib/devp2p/protocol.rb, line 35 def initialize(peer, service) raise ArgumentError, 'service must be WiredService' unless service.is_a?(WiredService) raise ArgumentError, 'peer.send_packet must be callable' unless peer.respond_to?(:send_packet) @peer = peer @service = service @stopped = false setup end
Public Instance Methods
receive_packet(packet)
click to toggle source
# File lib/devp2p/protocol.rb, line 69 def receive_packet(packet) cmd_name = @cmd_by_id[packet.cmd_id] cmd = "receive_#{cmd_name}" send cmd, packet rescue ProtocolError => e logger.warn "protocol exception, stopping", error: e stop end
send_packet(packet)
click to toggle source
# File lib/devp2p/protocol.rb, line 78 def send_packet(packet) peer.async.send_packet packet end
start()
click to toggle source
# File lib/devp2p/protocol.rb, line 47 def start logger.debug 'starting', proto: self service.async.on_wire_protocol_start self rescue puts $! puts $!.backtrace[0,10].join("\n") end
stop()
click to toggle source
# File lib/devp2p/protocol.rb, line 55 def stop logger.debug 'stopping', proto: self service.async.on_wire_protocol_stop self @stopped = true rescue puts $! puts $!.backtrace[0,10].join("\n") end
stopped?()
click to toggle source
# File lib/devp2p/protocol.rb, line 65 def stopped? @stopped end
to_s()
click to toggle source
# File lib/devp2p/protocol.rb, line 82 def to_s "<#{name} #{peer}>" end
Also aliased as: inspect
Private Instance Methods
logger()
click to toggle source
# File lib/devp2p/protocol.rb, line 89 def logger @logger ||= Logger.new('protocol') end
setup()
click to toggle source
# File lib/devp2p/protocol.rb, line 93 def setup klasses = [] self.class.constants.each do |name| c = self.class.const_get name klasses.push(c) if c.instance_of?(Class) && c < Command end raise DuplicatedCommand unless klasses.map(&:cmd_id).uniq.size == klasses.size proto = self klasses.each do |klass| instance = klass.new # decode rlp, create hash, call receive receive = lambda do |packet| raise ArgumentError, "packet is not a Packet: #{packet.inspect}" unless packet.is_a?(Packet) instance.receive proto, klass.decode_payload(packet.payload) end # get data, rlp encode, return packet create = lambda do |*args| res = instance.create(proto, *args) payload = klass.encode_payload res Packet.new protocol_id, klass.cmd_id, payload end # create and send packet send_packet = lambda do |*args| packet = create.call *args send_packet packet end name = Utils.class_to_cmd_name(klass) singleton_class.send(:define_method, "receive_#{name}", &receive) singleton_class.send(:define_method, "create_#{name}", &create) singleton_class.send(:define_method, "send_#{name}", &send_packet) singleton_class.send(:define_method, "receive_#{name}_callbacks") do instance.receive_callbacks end end @cmd_by_id = klasses.map {|k| [k.cmd_id, Utils.class_to_cmd_name(k)] }.to_h end