State machine gubbins. We need tests.

This commit is contained in:
Nick Thomas
2011-05-19 23:13:34 +01:00
parent ccfdad020a
commit d1c433b92c

View File

@@ -1,4 +1,5 @@
require 'eventmachine'
require 'stringio'
require 'btc_wire_proto'
module EventMachine
@@ -26,10 +27,11 @@ module EventMachine
# Sets up the variables required to manage the state machine. Should be
# called before you try to push a state - in post_init, say.
def init_state!
@stream = StringIO.new("")
@state_m = Mutex.new # Synchronize around @states and @working
@state_m.synchronize do
@states = []
@working = false
@current_state = nil
end
end
@@ -41,6 +43,20 @@ module EventMachine
[false, "configuration check not implemented yet"]
end
# Grabs the state that we're currently working on.
# @return[Array[Symbol,Object]] state symbol + data
def get_state
@state_m.synchronize do
@current_state ||= @states.shift
@current_state
end
end
# Call this when we've completed the actions required by the current state
def finished_state
@state_m.synchronize { @current_state = nil }
end
# Push a state to the end of the state queue.
def state(new_state, data = nil)
@state_m.synchronize { @states.push(new_state, data) }
@@ -51,6 +67,24 @@ module EventMachine
@state_m.synchronize { @states.unshift(new_state, data) }
end
# Do some work on the state machine
def state_tick
state, data = get_state
return unless state
if respond_to?(state)
send(state, data)
else
raise NotImplementedError.new("Unknown state: #{state} with #{data}")
end
end
# Receiving data mostly drives the state machine. Where something wants
# to send data, it gets queued straight onto the I/O/
def receive_data(io)
end
# State machine behaviours now.
# Send a 'version' message to the peer.
@@ -85,6 +119,10 @@ module EventMachine
def post_init
state(:send_ver)
end
def connection_completed
advance_state
end
end
# EventMachine protocol class that handles an *incoming* connection from