port mncc_test2 and gsm_call_fsm to pykka Actor framework

This commit is contained in:
Harald Welte 2015-12-01 20:17:45 +01:00
parent 3d66bfbeee
commit 0679cd4b97
4 changed files with 76 additions and 117 deletions

View File

@ -7,34 +7,35 @@ import pykka
from fysom import Fysom
from mncc_sock import mncc_msg, mncc_number
class GsmCallFsm(object):
class GsmCallFsm(pykka.ThreadingActor):
last_callref = 0
def get_next_callref(self):
def _get_next_callref(self):
GsmCallFsm.last_callref = GsmCallFsm.last_callref + 1
return GsmCallFsm.last_callref;
def printstatechange(self, e):
def _printstatechange(self, e):
print 'GsmCallFsm(%s): event: %s, src: %s, dst: %s' % (self.name, e.event, e.src, e.dst)
def onmncc_setup_req(self, e):
def _onmncc_setup_req(self, e):
msg = mncc_msg(msg_type = mncc.MNCC_SETUP_REQ, callref = self.callref,
fields = mncc.MNCC_F_CALLED | mncc.MNCC_F_CALLING,
calling = mncc_number(self.calling),
called = mncc_number(self.called))
self.mncc.send(msg)
self.mncc_ref.tell({'type': 'send', 'msg': msg})
print 'GsmCallFsm(%s): mncc_setup_req event: %s, src: %s, dst: %s' % (self.name, e.event, e.src, e.dst)
def onmncc_setup_cnf(self, e):
def _onmncc_setup_cnf(self, e):
# send MNCC_SETUP_COMPL_REQ to MNCC interface, causing
# CC-CONNECT-ACK to be sent to MS
msg = mncc_msg(msg_type = mncc.MNCC_SETUP_COMPL_REQ)
self.mncc.send(msg)
self.mncc_ref.tell({'send', msg})
def __init__(self, name, mncc):
def __init__(self, name, mncc_ref):
super(GsmCallFsm, self).__init__()
self.name = name
self.mncc = mncc;
self.callref = self.get_next_callref()
self.mncc_ref = mncc_ref;
self.callref = self._get_next_callref()
self.fsm = Fysom(initial = 'NULL',
events = [
# MT call setup
@ -77,11 +78,11 @@ class GsmCallFsm(object):
('mncc_rel_cnf', 'RELEASE_REQUEST', 'NULL')
],
callbacks = [('onmncc_setup_req', self.onmncc_setup_req),
('onmncc_setup_cnf', self.onmncc_setup_cnf),
callbacks = [('onmncc_setup_req', self._onmncc_setup_req),
('onmncc_setup_cnf', self._onmncc_setup_cnf),
],
)
self.fsm.onchangestate = self.printstatechange
self.fsm.onchangestate = self._printstatechange
def start_mt_call(self, calling, called):
self.calling = calling
@ -89,50 +90,59 @@ class GsmCallFsm(object):
self.fsm.mncc_setup_req()
# MT call
def do_mncc_rel_ind(self, mncc_msg):
def _do_mncc_rel_ind(self, mncc_msg):
self.fsm.mncc_rel_ind(mncc_msg)
def do_mncc_call_conf_ind(self, mncc_msg):
def _do_mncc_call_conf_ind(self, mncc_msg):
self.fsm.mncc_call_conf_ind(mncc_msg)
def do_mncc_alert_ind(self, mncc_msg):
def _do_mncc_alert_ind(self, mncc_msg):
self.fsm.mncc_allert_ind(mncc_msg)
def do_mncc_setup_cnf(self, mncc_msg):
def _do_mncc_setup_cnf(self, mncc_msg):
self.fsm.mncc_setup_cnf(mncc_msg)
# MO call
def do_mncc_setup_ind(self, mncc_msg):
def _do_mncc_setup_ind(self, mncc_msg):
self.fsm.mncc_setup_ind(mncc_msg)
def do_mncc_setup_compl_ind(self, mncc_msg):
def _do_mncc_setup_compl_ind(self, mncc_msg):
self.fsm.mncc_setup_compl_ind(mncc_msg)
# Misc
def do_mncc_disc_ind(self, mncc_msg):
def _do_mncc_disc_ind(self, mncc_msg):
self.fsm.mncc_disc_ind(mncc_msg)
def do_mncc_rel_ind(self, mncc_msg):
def _do_mncc_rel_ind(self, mncc_msg):
self.fsm.mncc_rel_ind(mncc_msg)
def do_mncc_rel_cnf(self, mncc_msg):
def _do_mncc_rel_cnf(self, mncc_msg):
self.fsm.mncc_rel_cnf(mncc_msg)
func_by_type = {
_func_by_type = {
# MT call
mncc.MNCC_REL_IND: do_mncc_rel_ind,
mncc.MNCC_CALL_CONF_IND: do_mncc_call_conf_ind,
mncc.MNCC_ALERT_IND: do_mncc_alert_ind,
mncc.MNCC_SETUP_CNF: do_mncc_setup_cnf,
mncc.MNCC_REL_IND: _do_mncc_rel_ind,
mncc.MNCC_CALL_CONF_IND: _do_mncc_call_conf_ind,
mncc.MNCC_ALERT_IND: _do_mncc_alert_ind,
mncc.MNCC_SETUP_CNF: _do_mncc_setup_cnf,
# MO call
mncc.MNCC_SETUP_IND: do_mncc_setup_ind,
mncc.MNCC_SETUP_COMPL_IND: do_mncc_setup_compl_ind,
mncc.MNCC_SETUP_IND: _do_mncc_setup_ind,
mncc.MNCC_SETUP_COMPL_IND: _do_mncc_setup_compl_ind,
# misc
mncc.MNCC_DISC_IND: do_mncc_disc_ind,
mncc.MNCC_REL_IND: do_mncc_rel_ind,
mncc.MNCC_REL_CNF: do_mncc_rel_cnf,
mncc.MNCC_DISC_IND: _do_mncc_disc_ind,
mncc.MNCC_REL_IND: _do_mncc_rel_ind,
mncc.MNCC_REL_CNF: _do_mncc_rel_cnf,
}
def lookup_method(self, mncc_msg_type):
return self.func_by_type[mncc_msg_type]
def _lookup_method(self, mncc_msg_type):
return self._func_by_type[mncc_msg_type]
def handle_mncc(self, mncc_msg):
def _handle_mncc(self, mncc_msg):
if mncc_msg.callref != self.callref:
raise Exception('mncc', 'Callref not for this GsmCallFsm')
self.lookup_method(mncc_msg.msg_type)(self, mncc_msg)
self._lookup_method(mncc_msg.msg_type)(self, mncc_msg)
# pykka Actor message receiver
def on_receive(self, message):
if message['type'] == 'mncc':
msg = message['msg']
if msg.callref == self.callref:
return self._handle_mncc(msg)
else:
raise Exception('mncc', 'Unknown message %s' % message)

View File

@ -2,14 +2,39 @@
from gsm_call_fsm import GsmCallFsm
from mncc_sock import MnccSocket
import pykka
import logging
import signal
import sys
class MnccActor(pykka.ThreadingActor):
def __init__(self, mncc_sock):
super(MnccActor, self).__init__()
self.mncc_sock = mncc_sock
def on_receive(self, message):
print 'MnccActor Received %s' % message
if message['type'] == 'send':
mncc_sock.send(message['msg'])
def sigint_handler(signum, frame):
pykka.ActorRegistry.stop_all()
sys.exit(0)
logging.basicConfig(level=logging.DEBUG)
signal.signal(signal.SIGINT, sigint_handler)
mncc_sock = MnccSocket()
mncc_act = MnccActor.start(mncc_sock)
call = GsmCallFsm('foo', mncc_sock)
#call.fsm.mncc_setup_req()
call.start_mt_call("1234", "6789")
call_proxy = GsmCallFsm.start('foo', mncc_act).proxy()
call_proxy.start_mt_call("1234", "6789")
while 1:
msg = mncc_sock.recv()
# FIXME: look-up the call based on msg.callref
call.handle_mncc(msg)
print "Received %s from MNCC, broadcasting to Call FSMs" % msg
# FIXME: we simply broadcast to all calls
pykka.ActorRegistry.broadcast({'type': 'mncc', 'msg': msg}, GsmCallFsm)
#pykka.ActorRegistry.broadcast({'type': 'mncc', 'msg': msg})

View File

@ -1,63 +0,0 @@
#!/usr/bin/python
import os, sys
from twisted.python.log import startLogging
from twisted.python.filepath import FilePath
from twisted.internet.defer import Deferred
from twisted.internet.protocol import Factory, BaseProtocol
from twisted.internet.endpoints import UNIXClientEndpoint
from twisted.internet import reactor
import mncc
import ctypes
class mncc_msg(mncc.gsm_mncc):
def send(self):
return buffer(self)[:]
def receive(self, bytes):
fit = min(len(bytes), ctypes.sizeof(self))
ctypes.memmove(ctypes.addressof(self), bytes, fit)
def mncc_number(number, num_type = 0, num_plan = 0, num_present = 1, num_screen = 0):
return mncc.gsm_mncc_number(number = number, type = num_type,
plan = num_plan, present = num_present,
screen = num_screen)
class MnccProtocol(BaseProtocol):
def __init__(self):
self.whenDisconnected = Deferred()
def dataReceived(self, data):
print 'received "%s"' % data
ms = mncc_msg()
ms.receive(data)
def connectionLost(self, reason):
self.whenDisconnected.callback(None)
def main():
address = FilePath('/tmp/bsc_mncc')
startLogging(sys.stdout)
factory = Factory()
factory.protocol = MnccProtocol
factory.quiet = True
endpoint = UnixClientEndpoint(reactor, address.path)
connected = endpoint.connect(factory)
def succeded(client):
print "succeeded"
return client.whenDisconnected
def failed(reason):
print "Could not connect:", reason.getErrorMessage()
def disconnected(ignored):
print "disconnected"
reactor.stop()
connected.addCallbacks(succeeded, failed)
connected.addCallback(disconnected)
reactor.run()

View File

@ -1,13 +0,0 @@
#!/usr/bin/python
import pykka
class Greeter(pykka.ThreadingActor):
def on_receive(self, message):
print('Hi there, you sent %s' % message)
actor_ref = Greeter.start()
actor_ref.tell({'msg': 'Hi!'})
actor_ref.stop()