diff options
author | Harald Welte <laforge@gnumonks.org> | 2015-12-01 19:07:30 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2015-12-01 19:07:30 +0100 |
commit | 3d66bfbeeeeacd7e6974785484f1f3ec06b1b73c (patch) | |
tree | 634e5759084b5c5e9bbc99ae2d2e1ee316e9adda /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.py | 138 |
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) |