Skip to content
Snippets Groups Projects
Commit a49638ea authored by Phil's avatar Phil
Browse files

Small redesign of automaton control loop and logic

parent 975dcc57
No related branches found
No related tags found
No related merge requests found
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
## Copyright (C) Philippe Biondi <phil@secdev.org> ## Copyright (C) Philippe Biondi <phil@secdev.org>
## This program is published under a GPLv2 license ## This program is published under a GPLv2 license
from __future__ import with_statement
import types,itertools,time,os import types,itertools,time,os
from select import select from select import select
from collections import deque from collections import deque
...@@ -316,7 +317,7 @@ class Automaton: ...@@ -316,7 +317,7 @@ class Automaton:
## Internals ## Internals
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
self.running = False self.running = thread.allocate_lock()
self.threadid = None self.threadid = None
self.breakpointed = None self.breakpointed = None
self.breakpoints = set() self.breakpoints = set()
...@@ -340,6 +341,8 @@ class Automaton: ...@@ -340,6 +341,8 @@ class Automaton:
self.parse_args(*args, **kargs) self.parse_args(*args, **kargs)
self.start()
def run_condition(self, cond, *args, **kargs): def run_condition(self, cond, *args, **kargs):
try: try:
cond(self,*args, **kargs) cond(self,*args, **kargs)
...@@ -355,41 +358,54 @@ class Automaton: ...@@ -355,41 +358,54 @@ class Automaton:
self.debug(2, "%s [%s] not taken" % (cond.atmt_type, cond.atmt_condname)) self.debug(2, "%s [%s] not taken" % (cond.atmt_type, cond.atmt_condname))
def __iter__(self): def __iter__(self):
if not self.running:
self.start()
return self return self
def do_control(self): def do_control(self, *args, **kargs):
singlestep = True with self.running:
self.debug(3, "Starting control thread [tid=%i]" % self.threadid) self.threadid = thread.get_ident()
try:
while True: # Update default parameters
c = self.cmdin.recv() a = args+self.init_args[len(args):]
self.debug(5, "Received command %s" % c.type) k = self.init_kargs
if c.type == _ATMT_Command.RUN: k.update(kargs)
singlestep = False self.parse_args(*a,**k)
elif c.type == _ATMT_Command.NEXT:
singlestep = True # Start the automaton
elif c.type == _ATMT_Command.STOP: self.state=self.initial_states[0](self)
break self.send_sock = conf.L3socket()
self.listen_sock = conf.L2listen(**self.socket_kargs)
self.packets = PacketList(name="session[%s]"%self.__class__.__name__)
singlestep = True
self.debug(3, "Starting control thread [tid=%i]" % self.threadid)
try:
while True: while True:
try: c = self.cmdin.recv()
state = self.do_next() self.debug(5, "Received command %s" % c.type)
except self.CommandMessage: if c.type == _ATMT_Command.RUN:
break singlestep = False
if singlestep: elif c.type == _ATMT_Command.NEXT:
c = Message(type=_ATMT_Command.SINGLESTEP,state=state) singlestep = True
self.cmdout.send(c) elif c.type == _ATMT_Command.STOP:
break break
except StopIteration,e: while True:
c = Message(type=_ATMT_Command.END, result=e.args[0]) try:
self.cmdout.send(c) state = self.do_next()
except Exception,e: except self.CommandMessage:
self.debug(3, "Transfering exception [%s] from tid=%i"% (e,self.threadid)) break
m = Message(type = _ATMT_Command.EXCEPTION, exception=e) if singlestep:
self.cmdout.send(m) c = Message(type=_ATMT_Command.SINGLESTEP,state=state)
self.debug(3, "Stopping control thread (tid=%i)"%self.threadid) self.cmdout.send(c)
self.threadid = None break
except StopIteration,e:
c = Message(type=_ATMT_Command.END, result=e.args[0])
self.cmdout.send(c)
except Exception,e:
self.debug(3, "Transfering exception [%s] from tid=%i"% (e,self.threadid))
m = Message(type = _ATMT_Command.EXCEPTION, exception=e)
self.cmdout.send(m)
self.debug(3, "Stopping control thread (tid=%i)"%self.threadid)
self.threadid = None
def do_next(self): def do_next(self):
...@@ -404,10 +420,8 @@ class Automaton: ...@@ -404,10 +420,8 @@ class Automaton:
self.breakpointed = None self.breakpointed = None
state_output = self.state.run() state_output = self.state.run()
if self.state.error: if self.state.error:
self.running = False
raise self.ErrorState("Reached %s: [%r]" % (self.state.state, state_output), result=state_output) raise self.ErrorState("Reached %s: [%r]" % (self.state.state, state_output), result=state_output)
if self.state.final: if self.state.final:
self.running = False
raise StopIteration(state_output) raise StopIteration(state_output)
if state_output is None: if state_output is None:
...@@ -470,6 +484,7 @@ class Automaton: ...@@ -470,6 +484,7 @@ class Automaton:
self.debug(2, "switching from [%s] to [%s]" % (self.state.state,state_req.state)) self.debug(2, "switching from [%s] to [%s]" % (self.state.state,state_req.state))
self.state = state_req self.state = state_req
return state_req return state_req
## Public API ## Public API
...@@ -500,22 +515,7 @@ class Automaton: ...@@ -500,22 +515,7 @@ class Automaton:
self.breakpoints.remove(pb) self.breakpoints.remove(pb)
def start(self, *args, **kargs): def start(self, *args, **kargs):
self.running = True thread.start_new_thread(self.do_control, args, kargs)
# Update default parameters
a = args+self.init_args[len(args):]
k = self.init_kargs
k.update(kargs)
self.parse_args(*a,**k)
# Start the automaton
self.state=self.initial_states[0](self)
self.send_sock = conf.L3socket()
self.listen_sock = conf.L2listen(**self.socket_kargs)
self.packets = PacketList(name="session[%s]"%self.__class__.__name__)
self.threadid = thread.start_new_thread(self.do_control, ())
def run(self, resume=None, wait=True): def run(self, resume=None, wait=True):
if resume is None: if resume is None:
...@@ -542,6 +542,10 @@ class Automaton: ...@@ -542,6 +542,10 @@ class Automaton:
def stop(self): def stop(self):
self.cmdin.send(Message(type=_ATMT_Command.STOP)) self.cmdin.send(Message(type=_ATMT_Command.STOP))
def restart(self):
self.stop()
self.start()
def accept_packet(self, pkt=None): def accept_packet(self, pkt=None):
rsm = Message() rsm = Message()
if pkt is None: if pkt is None:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment