diff --git a/lib/em-bitcoin.rb b/lib/em-bitcoin.rb index abd9855..154eed9 100644 --- a/lib/em-bitcoin.rb +++ b/lib/em-bitcoin.rb @@ -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