Allow lazy actor initialization, add receive_packet, check packet network

This commit is contained in:
Nick Thomas
2011-06-21 22:52:06 +01:00
parent f68242170e
commit 561d7c5777

View File

@@ -122,23 +122,8 @@ module EventMachine
begin
packet = BTC::Message.read(@data)
used = @data.slice!(0, packet.num_bytes) # Remove data from buf
log(:info, "Read #{packet.cmd_sym} packet (#{used.length}b)")
log(:debug, used.inspect)
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
receive_packet(packet)
rescue IOError,EOFError # Not enough data
finished = true
end
end
@@ -146,6 +131,34 @@ module EventMachine
log(:debug, @data.inspect) if @data.length > 0
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
# 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
@@ -188,9 +201,11 @@ module EventMachine
class BitcoinClient < EM::Connection
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)
@actor = actor
@actor = @actor.call if actor.is_a?(Proc)
result, msg = valid_actor?
raise ArgumentError.new("Invalid actor: #{msg}") unless result
@@ -223,7 +238,7 @@ module EventMachine
@ready == :version_sent
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
@ready = true
actor.ready!
@@ -248,9 +263,11 @@ module EventMachine
my_netaddr.port
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)
@actor = actor
@actor = @actor.call if actor.is_a?(Proc)
result, msg = valid_actor?
raise ArgumentError.new("Invalid actor: #{msg}") unless result
@@ -279,6 +296,7 @@ module EventMachine
def receive_verack(p)
raise PE.new("Received verack inappropriately") unless
@ready == :version_sent
log(:info, "Notifying actor of ready peer (v.#{p.payload.version})")
@ready = true
actor.ready!
end