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 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