gsm_call_fsm: Connect the RTP streams of the two call legs
This commit is contained in:
parent
5b4c297ad9
commit
3d058cf657
|
@ -7,6 +7,10 @@ import pykka
|
|||
from fysom import Fysom
|
||||
from mncc_sock import mncc_msg, mncc_number, mncc_rtp_msg
|
||||
|
||||
class RtpEndpointData(object):
|
||||
def __init__(self):
|
||||
self.ip = self.port = self.payload_type = self.payload_msg_type = None
|
||||
|
||||
class GsmCallFsm(pykka.ThreadingActor):
|
||||
last_callref = 0
|
||||
|
||||
|
@ -31,6 +35,11 @@ class GsmCallFsm(pykka.ThreadingActor):
|
|||
# CC-CONNECT-ACK to be sent to MS
|
||||
msg = mncc_msg(msg_type = mncc.MNCC_SETUP_COMPL_REQ, callref = self.callref)
|
||||
self.mncc_ref.tell({'type': 'send', 'msg': msg})
|
||||
# ask to create the RTP socket in RTP bridge mode
|
||||
if self.rtp_bridge:
|
||||
msg = mncc_rtp_msg(msg_type = mncc.MNCC_RTP_CREATE, callref = self.callref)
|
||||
self.mncc_ref.tell({'type': 'send', 'msg': msg})
|
||||
# directly transition into the ACTIVE state
|
||||
self.fsm.mncc_setup_compl_req()
|
||||
|
||||
def _onmncc_disc_ind(self, e):
|
||||
|
@ -42,11 +51,13 @@ class GsmCallFsm(pykka.ThreadingActor):
|
|||
if e.event != 'startup':
|
||||
self.stop()
|
||||
|
||||
def __init__(self, mncc_ref, ctrl_ref = None):
|
||||
def __init__(self, mncc_ref, ctrl_ref = None, rtp_bridge = True):
|
||||
super(GsmCallFsm, self).__init__()
|
||||
self.mncc_ref = mncc_ref;
|
||||
self.callref = self._get_next_callref()
|
||||
self.ctrl_ref = ctrl_ref
|
||||
self.rtp_bridge = rtp_bridge
|
||||
self.rtp = None
|
||||
self.fsm = Fysom(initial = 'NULL',
|
||||
events = [
|
||||
# MT call setup
|
||||
|
@ -87,7 +98,7 @@ class GsmCallFsm(pykka.ThreadingActor):
|
|||
('mncc_rel_ind', '*', 'NULL'),
|
||||
('mncc_disc_ind', 'DISCONNECT_INDICATION', 'RELEASE_REQUEST'),
|
||||
|
||||
('mncc_rel_cnf', 'RELEASE_REQUEST', 'NULL')
|
||||
('mncc_rel_cnf', 'RELEASE_REQUEST', 'NULL'),
|
||||
],
|
||||
callbacks = [('onmncc_setup_req', self._onmncc_setup_req),
|
||||
('onmncc_setup_cnf', self._onmncc_setup_cnf),
|
||||
|
@ -102,6 +113,11 @@ class GsmCallFsm(pykka.ThreadingActor):
|
|||
self.called = called
|
||||
self.fsm.mncc_setup_req()
|
||||
|
||||
def connect_rtp(self, rtp):
|
||||
rtp.msg_type = mncc.MNCC_RTP_CONNECT
|
||||
rtp.callref = self.callref
|
||||
self.mncc_ref.tell({'type': 'send', 'msg': rtp})
|
||||
|
||||
# MT call
|
||||
def _do_mncc_rel_ind(self, mncc_msg):
|
||||
self.fsm.mncc_rel_ind(mncc_msg)
|
||||
|
@ -126,6 +142,22 @@ class GsmCallFsm(pykka.ThreadingActor):
|
|||
def _do_mncc_rel_cnf(self, mncc_msg):
|
||||
self.fsm.mncc_rel_cnf(mncc_msg)
|
||||
|
||||
# RTP
|
||||
def _do_mncc_rtp_create_ind(self, mncc_msg):
|
||||
if self.rtp_bridge == False:
|
||||
raise Exception('GsmCallFsm', 'rtp_create_ind but not in RTP bridge mode')
|
||||
self.rtp = mncc_msg
|
||||
# notify the call controller about this
|
||||
self.ctrl_ref.tell({'type':'rtp_create_ind', 'called':self.called, 'rtp':self.rtp})
|
||||
|
||||
def _do_mncc_rtp_connect_ind(self, mncc_msg):
|
||||
# FIXME
|
||||
return
|
||||
|
||||
def _do_mncc_rtp_free_ind(self, mncc_msg):
|
||||
# FIXME
|
||||
return
|
||||
|
||||
_func_by_type = {
|
||||
# MT call
|
||||
mncc.MNCC_REL_IND: _do_mncc_rel_ind,
|
||||
|
@ -141,6 +173,11 @@ class GsmCallFsm(pykka.ThreadingActor):
|
|||
mncc.MNCC_DISC_IND: _do_mncc_disc_ind,
|
||||
mncc.MNCC_REL_IND: _do_mncc_rel_ind,
|
||||
mncc.MNCC_REL_CNF: _do_mncc_rel_cnf,
|
||||
|
||||
# RTP
|
||||
mncc.MNCC_RTP_CREATE: _do_mncc_rtp_create_ind,
|
||||
mncc.MNCC_RTP_CONNECT: _do_mncc_rtp_connect_ind,
|
||||
mncc.MNCC_RTP_FREE: _do_mncc_rtp_free_ind,
|
||||
}
|
||||
|
||||
def _lookup_method(self, mncc_msg_type):
|
||||
|
@ -155,40 +192,67 @@ class GsmCallFsm(pykka.ThreadingActor):
|
|||
def on_receive(self, message):
|
||||
if message['type'] == 'mncc':
|
||||
msg = message['msg']
|
||||
print 'GsmCallFsm(%u):on_receive(mncc, %s)' % (self.callref, msg)
|
||||
if msg.callref == self.callref:
|
||||
print 'GsmCallFsm(%u):on_receive(mncc, %s)' % (self.callref, msg)
|
||||
return self._handle_mncc(msg)
|
||||
elif message['type'] == 'start_mt_call':
|
||||
self.start_mt_call(message['calling'], message['called'])
|
||||
elif message['type'] == 'connect_rtp':
|
||||
self.connect_rtp(message['rtp'])
|
||||
else:
|
||||
raise Exception('mncc', 'Unknown message %s' % message)
|
||||
|
||||
|
||||
class GsmCallConnector(pykka.ThreadingActor):
|
||||
def __init__(self, mncc_act):
|
||||
def __init__(self, mncc_act, rtp_bridge = True):
|
||||
super(GsmCallConnector, self).__init__()
|
||||
self.mncc_act = mncc_act
|
||||
self.rtp_bridge = rtp_bridge
|
||||
print 'Starting Call A actor'
|
||||
self.call_a = GsmCallFsm.start(self.mncc_act, self.actor_ref)
|
||||
self.call_a = GsmCallFsm.start(self.mncc_act, self.actor_ref, self.rtp_bridge)
|
||||
print 'Starting Call B actor'
|
||||
self.call_b = GsmCallFsm.start(self.mncc_act, self.actor_ref)
|
||||
self.call_b = GsmCallFsm.start(self.mncc_act, self.actor_ref, self.rtp_bridge)
|
||||
self.state_a = self_state_b = 'NULL'
|
||||
self.rtp_a = self.rtp_b = None
|
||||
|
||||
def start_call_ab(self, msisdn_a, msisdn_b):
|
||||
print 'Starting calls for A and B'
|
||||
self.msisdn_a = msisdn_a
|
||||
self.msisdn_b = msisdn_b
|
||||
|
||||
# start MT call A->B
|
||||
print 'Starting Call A->B'
|
||||
self.call_a.tell({'type':'start_mt_call', 'calling':self.msisdn_a, 'called':self.msisdn_b})
|
||||
|
||||
# start MT call B->A
|
||||
print 'Starting Call B->A'
|
||||
self.call_b.tell({'type':'start_mt_call', 'calling':self.msisdn_b, 'called':self.msisdn_a})
|
||||
print 'Starting MT Call to A'
|
||||
self.call_a.tell({'type':'start_mt_call', 'calling':self.msisdn_b, 'called':self.msisdn_a})
|
||||
|
||||
# start MT call A->B
|
||||
print 'Starting Call to B'
|
||||
self.call_b.tell({'type':'start_mt_call', 'calling':self.msisdn_a, 'called':self.msisdn_b})
|
||||
|
||||
def rtp_created(self, msisdn, rtp):
|
||||
print 'CallConnector:rtp_created(%s) %s' % (msisdn, rtp)
|
||||
if self.rtp_bridge == False:
|
||||
raise Exception('GsmCallConnector', 'rtp_created but not in RTP bridge mode')
|
||||
if msisdn == self.msisdn_a: # A->B leg
|
||||
self.rtp_a = rtp
|
||||
elif msisdn == self.msisdn_b: # B->A leg
|
||||
self.rtp_b = rtp
|
||||
if self.rtp_a and self.rtp_b:
|
||||
self.call_a.tell({'type':'connect_rtp', 'rtp':self.rtp_b})
|
||||
self.call_b.tell({'type':'connect_rtp', 'rtp':self.rtp_a})
|
||||
|
||||
def call_state_change(self, msisdn, old_state, new_state):
|
||||
print 'CallConnector:leg_state_change(%s) %s -> %s' % (msisdn, old_state, new_state)
|
||||
if msisdn == self.msisdn_a: # A->B leg
|
||||
self.state_a = new_state
|
||||
elif msisdn == self.msisdn_b: # B->A leg
|
||||
self.state_b = new_state
|
||||
#if self.rtp_bridge == False and self.state_a == 'ACTIVE' and self.state_b == 'ACTIVE':
|
||||
# self.connect_legs()
|
||||
|
||||
def on_receive(self, message):
|
||||
if message['type'] == 'call_state_change':
|
||||
self.call_state_change(message['called'], message['old_state'], message['new_state'])
|
||||
elif message['type'] == 'rtp_create_ind':
|
||||
self.rtp_created(message['called'], message['rtp'])
|
||||
#else:
|
||||
# raise Exception('mncc', 'GsmCallConnector Rx Unknown message %s' % message)
|
||||
|
|
Loading…
Reference in New Issue