Respect BtcWireProto changes, make another step towards tests
This commit is contained in:
@@ -7,13 +7,6 @@ module EventMachine
|
||||
# Implements the TCP protocol that Bitcoin peers speak to each other. This
|
||||
# module is mixed into both incoming and outgoing connections.
|
||||
#
|
||||
#
|
||||
#
|
||||
# Here is a list of states:
|
||||
# send_ver, recv_ver, verify_ver
|
||||
# send_verack, recv_verack
|
||||
# wait, finish
|
||||
#
|
||||
# Documentation is here: https://en.bitcoin.it/wiki/Network
|
||||
#
|
||||
# @author Nick Thomas <nick@lupine.me.uk>
|
||||
@@ -28,10 +21,6 @@ module EventMachine
|
||||
# The actor for this peer
|
||||
attr_reader :actor
|
||||
|
||||
# Randomly-generated 32-bit number allowing us to guarantee we're not
|
||||
# connecting to ourselves.
|
||||
attr_reader :connection_nonce
|
||||
|
||||
# The list of methods a valid actor will respond to.
|
||||
ACTOR_METHODS = [
|
||||
:network_name, # Returns a symbol telling us which network to be on
|
||||
@@ -39,33 +28,43 @@ module EventMachine
|
||||
:sub_version, # String specifying custom version string
|
||||
:current_height, # Number of the newest block known to the actor
|
||||
:log, # log(:level, message) - self-evident
|
||||
:node_nonce, # 32-bit number lets us identify streams to self
|
||||
:connection=, # Called with +self+ to allow actor interaction
|
||||
:ready! # Called when the connection is ready to be used
|
||||
]
|
||||
|
||||
# receive_version and receive_verack implementations differ in client &
|
||||
# server, so are implemented there.
|
||||
|
||||
# Simple wrapper around +send_data+ that logs usage
|
||||
# @param[BTC::Message] packet Packet to send
|
||||
def send_packet(packet)
|
||||
data = packet.to_binary_s
|
||||
log(:info, "Sending #{packet.cmd_sym} message (#{data.length}b)")
|
||||
log(:debug, data.inspect)
|
||||
log(:debug, packet.inspect)
|
||||
send_data(data)
|
||||
end
|
||||
|
||||
# Send a 'version' message to the peer.
|
||||
def send_version
|
||||
log(:info, "Sending version message")
|
||||
|
||||
m = build_message(:version, {
|
||||
:version => BTC::CURRENT_VERSION(actor.network_name),
|
||||
:services => {:node_network => 1},
|
||||
:timestamp => actor.current_time.to_i,
|
||||
:addr_me => my_netaddr,
|
||||
:addr_you => peer_netaddr,
|
||||
:nonce => connection_nonce,
|
||||
:nonce => actor.node_nonce,
|
||||
:sub_version_num => (actor.sub_version || "em-bitcoin"),
|
||||
:start_height => actor.current_height
|
||||
})
|
||||
send_data(m.to_binary_s)
|
||||
send_packet(m)
|
||||
end
|
||||
|
||||
# Send a 'verack' message to the peer
|
||||
def send_verack
|
||||
log(:info, "Sending verack message")
|
||||
send_data(build_message(:verack).to_binary_s)
|
||||
send_packet(build_message(:verack))
|
||||
end
|
||||
|
||||
protected
|
||||
@@ -75,7 +74,8 @@ module EventMachine
|
||||
def build_message(command, payload_opts = {}, header_opts = {})
|
||||
header_opts[:command] = command.to_s
|
||||
header_opts[:magic] ||= BTC::NETWORKS[actor.network_name]
|
||||
m = BTC::Message.new(:header => header_opts, :payload => payload_opts)
|
||||
header_opts[:payload] = payload_opts
|
||||
m = BTC::Message.new(header_opts)
|
||||
end
|
||||
|
||||
def log(level, data)
|
||||
@@ -85,7 +85,6 @@ module EventMachine
|
||||
def init_state!
|
||||
@data = ""
|
||||
@ready = nil
|
||||
@connection_nonce = rand(2**32)
|
||||
actor.connection = self # Tell the actor about the connection
|
||||
end
|
||||
|
||||
@@ -122,7 +121,10 @@ module EventMachine
|
||||
while !finished
|
||||
begin
|
||||
packet = BTC::Message.read(@data)
|
||||
@data.slice!(0, packet.num_bytes - 1) # Remove data from buffer
|
||||
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)
|
||||
@@ -133,13 +135,15 @@ module EventMachine
|
||||
end
|
||||
else
|
||||
log(:warn, "Received packet with no command, discarding it")
|
||||
log(:debug, packet)
|
||||
end
|
||||
rescue IOError # Not enough data
|
||||
finished = true
|
||||
rescue EOFError
|
||||
finished = true
|
||||
end
|
||||
end
|
||||
log(:debug, "Leaving receive_data with #{@data.length} bytes in buffer")
|
||||
log(:debug, @data.inspect) if @data.length > 0
|
||||
end
|
||||
|
||||
# Checks whether we can communicate sensibly with a peer of a particular
|
||||
@@ -240,6 +244,10 @@ module EventMachine
|
||||
class BitcoinServer < EM::Connection
|
||||
include BitcoinPeer
|
||||
|
||||
def port
|
||||
my_netaddr.port
|
||||
end
|
||||
|
||||
# @param[Object] actor See the BitcoinPeer#valid_actor? method
|
||||
def initialize(actor)
|
||||
@actor = actor
|
||||
|
Reference in New Issue
Block a user