aboutsummaryrefslogtreecommitdiffstats
path: root/gsm_call_fsm.py
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2015-12-01 19:07:30 +0100
committerHarald Welte <laforge@gnumonks.org>2015-12-01 19:07:30 +0100
commit3d66bfbeeeeacd7e6974785484f1f3ec06b1b73c (patch)
tree634e5759084b5c5e9bbc99ae2d2e1ee316e9adda /gsm_call_fsm.py
initial checkin of experiments with python and the MNCC interface
Diffstat (limited to 'gsm_call_fsm.py')
-rw-r--r--gsm_call_fsm.py138
1 files changed, 138 insertions, 0 deletions
diff --git a/gsm_call_fsm.py b/gsm_call_fsm.py
new file mode 100644
index 0000000..d67e097
--- /dev/null
+++ b/gsm_call_fsm.py
@@ -0,0 +1,138 @@
+#!/usr/bin/python
+
+import mncc
+import ctypes
+import pykka
+
+from fysom import Fysom
+from mncc_sock import mncc_msg, mncc_number
+
+class GsmCallFsm(object):
+ last_callref = 0
+
+ def get_next_callref(self):
+ GsmCallFsm.last_callref = GsmCallFsm.last_callref + 1
+ return GsmCallFsm.last_callref;
+
+ 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):
+ 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)
+ 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):
+ # 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)
+
+ def __init__(self, name, mncc):
+ self.name = name
+ self.mncc = mncc;
+ self.callref = self.get_next_callref()
+ self.fsm = Fysom(initial = 'NULL',
+ events = [
+ # MT call setup
+ ('mncc_setup_req', 'NULL', 'CALL_PRESENT'),
+ ('mncc_rel_ind', 'CALL_PRESENT', 'NULL'),
+ ('mncc_call_conf_ind', 'CALL_PRESENT', 'MT_CALL_CONFIRMED'),
+ ('mncc_alert_ind', 'MT_CALL_CONFIRMED', 'CALL_RECEIVED'),
+ ('mncc_setup_cnf', 'CALL_RECEIVED', 'CONNECT_REQUEST'),
+ ('mncc_setup_cnf', 'MT_CALL_CONFIRMED', 'CONNECT_REQUEST'),
+ ('mncc_setup_compl_req', 'CONNECT_REQUEST', 'ACTIVE'),
+
+ # MO call setup
+ # SETUP INDICATION (MS->MNCC)
+ ('mncc_setup_ind', 'NULL', 'CALL_INIT'),
+ # CALL PROCEEDING REQ (MNCC->MS)
+ ('mncc_call_proc_req', 'CALL_INIT', 'MO_CALL_PROC'),
+ # SETUP RESPONSE (MS->MNCC)
+ ('mncc_setup_resp', 'MO_CALL_PROC', 'CONNECT_INDICATION'),
+ # ALERT REQ (MNCC->MS)
+ ('mncc_alert_req', 'MO_CALL_PROC', 'CALL_DELIVERED'),
+ # SETUP RESPONSE (MS->MNCC)
+ ('mncc_setup_resp', 'CALL_DELIVERED', 'CONNECT_INDICATION'),
+ # PROGRESS REQ (MNCC->MS)
+ ('mncc_progress_req', 'MO_CALL_PROC', 'MO_CALL_PROC'),
+ # SETUP COMPL IND (MS->MNCC)
+ ('mncc_setup_compl_ind', 'CONNECT_INDICATION', 'ACTIVE'),
+
+ ('mncc_disc_ind', ['CALL_INIT', 'MO_CALL_PROC',
+ 'CALL_RECEIVED', 'CONNECT_REQUEST',
+ 'MT_CALL_CONFIRMED', 'ACTIVE',
+ 'CONNECT_INDICATION'], 'RELEASE_REQUEST'),
+
+ ('mncc_disc_req', ['CALL_INIT', 'MO_CALL_PROC',
+ 'CALL_RECEIVED', 'CONNECT_REQUEST',
+ 'MT_CALL_CONFIRMED', 'ACTIVE',
+ 'CONNECT_INDICATION'], 'DISCONNECT_INDICATION'),
+
+ ('mncc_rel_ind', 'DISCONNECT_INDICATION', 'NULL'),
+ ('mncc_disc_ind', 'DISCONNECT_INDICATION', 'RELEASE_REQUEST'),
+
+ ('mncc_rel_cnf', 'RELEASE_REQUEST', 'NULL')
+ ],
+ callbacks = [('onmncc_setup_req', self.onmncc_setup_req),
+ ('onmncc_setup_cnf', self.onmncc_setup_cnf),
+ ],
+ )
+ self.fsm.onchangestate = self.printstatechange
+
+ def start_mt_call(self, calling, called):
+ self.calling = calling
+ self.called = called
+ self.fsm.mncc_setup_req()
+
+ # MT call
+ def do_mncc_rel_ind(self, mncc_msg):
+ self.fsm.mncc_rel_ind(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):
+ self.fsm.mncc_allert_ind(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):
+ self.fsm.mncc_setup_ind(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):
+ self.fsm.mncc_disc_ind(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):
+ self.fsm.mncc_rel_cnf(mncc_msg)
+
+ 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,
+
+ # MO call
+ 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,
+ }
+
+ def lookup_method(self, mncc_msg_type):
+ return self.func_by_type[mncc_msg_type]
+
+ 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)