139 lines
5.5 KiB
Python
139 lines
5.5 KiB
Python
|
#!/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)
|