Allow lazy actor initialization, add receive_packet, check packet network
This commit is contained in:
@@ -122,23 +122,8 @@ module EventMachine
|
|||||||
begin
|
begin
|
||||||
packet = BTC::Message.read(@data)
|
packet = BTC::Message.read(@data)
|
||||||
used = @data.slice!(0, packet.num_bytes) # Remove data from buf
|
used = @data.slice!(0, packet.num_bytes) # Remove data from buf
|
||||||
log(:info, "Read #{packet.cmd_sym} packet (#{used.length}b)")
|
receive_packet(packet)
|
||||||
log(:debug, used.inspect)
|
rescue IOError,EOFError # Not enough data
|
||||||
log(:debug, packet.inspect)
|
|
||||||
if packet.cmd_sym
|
|
||||||
m = "receive_#{packet.cmd_sym}"
|
|
||||||
if self.respond_to?(m)
|
|
||||||
log(:info, "Received #{packet.cmd_sym}")
|
|
||||||
send(m, packet)
|
|
||||||
else
|
|
||||||
raise NotImplementedError.new("#{m} not implemented")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
log(:warn, "Received packet with no command, discarding it")
|
|
||||||
end
|
|
||||||
rescue IOError # Not enough data
|
|
||||||
finished = true
|
|
||||||
rescue EOFError
|
|
||||||
finished = true
|
finished = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -146,6 +131,34 @@ module EventMachine
|
|||||||
log(:debug, @data.inspect) if @data.length > 0
|
log(:debug, @data.inspect) if @data.length > 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Checks the passed-in packet for validity and dispatches it if valid
|
||||||
|
# @param[BTC::Message] packet Received packet
|
||||||
|
def receive_packet(packet)
|
||||||
|
log(:info, "Received #{packet.cmd_sym} packet (#{packet.num_bytes}b)")
|
||||||
|
log(:debug, packet.inspect)
|
||||||
|
|
||||||
|
if packet.network_name != actor.network_name
|
||||||
|
log(
|
||||||
|
:info, "Received packet from incorrect network: " +
|
||||||
|
"#{packet.network_name || packet.magic}, discarding"
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if packet.cmd_sym
|
||||||
|
m = "receive_#{packet.cmd_sym}"
|
||||||
|
if self.respond_to?(m)
|
||||||
|
log(:info, "Received #{packet.cmd_sym}")
|
||||||
|
send(m, packet)
|
||||||
|
else
|
||||||
|
raise NotImplementedError.new("#{m} not implemented")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
log(:info, "Received packet with no command, discarding it")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Checks whether we can communicate sensibly with a peer of a particular
|
# Checks whether we can communicate sensibly with a peer of a particular
|
||||||
# version. At the moment, we're fairly liberal about who we try to talk to
|
# version. At the moment, we're fairly liberal about who we try to talk to
|
||||||
# @param[Fixnum] their_version Version of the peer under question
|
# @param[Fixnum] their_version Version of the peer under question
|
||||||
@@ -188,9 +201,11 @@ module EventMachine
|
|||||||
class BitcoinClient < EM::Connection
|
class BitcoinClient < EM::Connection
|
||||||
include BitcoinPeer
|
include BitcoinPeer
|
||||||
|
|
||||||
# @param[Object] actor See the BitcoinPeer#valid_actor?
|
# @param[Object] actor See the BitcoinPeer#valid_actor? method. If this is
|
||||||
|
# a proc, we execute it and use the return value as the actor.
|
||||||
def initialize(actor)
|
def initialize(actor)
|
||||||
@actor = actor
|
@actor = actor
|
||||||
|
@actor = @actor.call if actor.is_a?(Proc)
|
||||||
result, msg = valid_actor?
|
result, msg = valid_actor?
|
||||||
raise ArgumentError.new("Invalid actor: #{msg}") unless result
|
raise ArgumentError.new("Invalid actor: #{msg}") unless result
|
||||||
|
|
||||||
@@ -223,7 +238,7 @@ module EventMachine
|
|||||||
@ready == :version_sent
|
@ready == :version_sent
|
||||||
|
|
||||||
if can_talk_version?(p.payload.version)
|
if can_talk_version?(p.payload.version)
|
||||||
log(:info, "Valid peer, version is #{p.payload.version}")
|
log(:info, "Notifying actor of ready peer (v.#{p.payload.version})")
|
||||||
send_verack
|
send_verack
|
||||||
@ready = true
|
@ready = true
|
||||||
actor.ready!
|
actor.ready!
|
||||||
@@ -248,9 +263,11 @@ module EventMachine
|
|||||||
my_netaddr.port
|
my_netaddr.port
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param[Object] actor See the BitcoinPeer#valid_actor? method
|
# @param[Object] actor See the BitcoinPeer#valid_actor? method. If this is
|
||||||
|
# a proc, we execute it and use the return value as the actor.
|
||||||
def initialize(actor)
|
def initialize(actor)
|
||||||
@actor = actor
|
@actor = actor
|
||||||
|
@actor = @actor.call if actor.is_a?(Proc)
|
||||||
result, msg = valid_actor?
|
result, msg = valid_actor?
|
||||||
raise ArgumentError.new("Invalid actor: #{msg}") unless result
|
raise ArgumentError.new("Invalid actor: #{msg}") unless result
|
||||||
|
|
||||||
@@ -279,6 +296,7 @@ module EventMachine
|
|||||||
def receive_verack(p)
|
def receive_verack(p)
|
||||||
raise PE.new("Received verack inappropriately") unless
|
raise PE.new("Received verack inappropriately") unless
|
||||||
@ready == :version_sent
|
@ready == :version_sent
|
||||||
|
log(:info, "Notifying actor of ready peer (v.#{p.payload.version})")
|
||||||
@ready = true
|
@ready = true
|
||||||
actor.ready!
|
actor.ready!
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user