def __init__(self, global_config, body, done_cb, portrange): uaO = UA(global_config, event_cb = self.recvEvent, nh_address = ('127.0.0.1', 5060), \ conn_cbs = (self.connected,), disc_cbs = (self.disconnected,), fail_cbs = (self.disconnected,), \ dead_cbs = (self.alldone,)) uaO.godead_timeout = 10 uaO.compact_sip = self.compact_sip event = CCEventTry((SipCallId(), SipCiscoGUID(), self.cli, self.cld, body, \ None, 'Alice Smith')) uaO.recvEvent(event) self.done_cb = done_cb self.portrange = portrange
def recvRequest(self, req, sip_t): if req.getMethod() in ('NOTIFY', 'PING'): # Whynot? return (req.genResponse(200, 'OK'), None, None) if req.getMethod() == 'INVITE': if self.rserv != None: return (req.genResponse(486, 'Busy Here'), None, None) # New dialog uaA = UA(self.global_config, self.recvEvent, disc_cbs = (self.sess_term,)) uaA.recvRequest(req, sip_t) return return (req.genResponse(501, 'Not Implemented'), None, None)
def __init__(self, remote_ip, source, global_config, pass_headers): self.id = CallController.id CallController.id += 1 self.global_config = global_config self.uaA = UA(self.global_config, event_cb = self.recvEvent, conn_cbs = (self.aConn,), disc_cbs = (self.aDisc,), \ fail_cbs = (self.aDisc,), dead_cbs = (self.aDead,)) self.uaA.kaInterval = self.global_config['keepalive_ans'] self.uaA.local_ua = self.global_config['_uaname'] self.state = CCStateIdle self.uaO = None self.routes = [] self.remote_ip = remote_ip self.source = source self.pass_headers = pass_headers
def recvRequest(self, req, sip_t): if req.getMethod() in ('NOTIFY', 'PING'): # Whynot? return (req.genResponse(200, 'OK'), None, None) if req.getMethod() == 'INVITE': if self.rserv != None: return (req.genResponse(486, 'Busy Here'), None, None) # New dialog uaA = UA(self.global_config, self.recvEvent, disc_cbs=(self.sess_term, )) uaA.recvRequest(req, sip_t) return return (req.genResponse(501, 'Not Implemented'), None, None)
def answer(self, global_config, body, req, sip_t): in_body = req.getBody() in_body.parse() if not checkhostport(in_body, self.portrange, self.atype): self.nerrs += 1 raise ValueError('Bob(%s): hostport validation has failed' % str(self.__class__)) # New dialog uaA = UA(global_config, self.recvEvent, disc_cbs = (self.disconnected,), \ fail_cbs = (self.disconnected,), dead_cbs = (self.alldone,)) uaA.godead_timeout = 10 uaA.compact_sip = self.compact_sip Timeout(self.ring, self.ring_ival, 1, uaA) self.body = body return uaA.recvRequest(req, sip_t)
def placeOriginate(self, oroute): cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData() cld = oroute.cld self.huntstop_scodes = oroute.params.get('huntstop_scodes', ()) if 'static_tr_out' in self.global_config: cld = re_replace(self.global_config['static_tr_out'], cld) if oroute.hostport == 'sip-ua': host = self.source[0] nh_address, same_af = self.source, True else: host = oroute.hostonly nh_address, same_af = oroute.getNHAddr(self.source) if not oroute.forward_on_fail and self.global_config['acct_enable']: self.acctO = RadiusAccounting(self.global_config, 'originate', \ send_start = self.global_config['start_acct_enable'], lperiod = \ self.global_config.getdefault('alive_acct_int', None)) self.acctO.ms_precision = self.global_config.getdefault('precise_acct', False) self.acctO.setParams(oroute.params.get('bill-to', self.username), oroute.params.get('bill-cli', oroute.cli), \ oroute.params.get('bill-cld', cld), self.cGUID, self.cId, host) else: self.acctO = None self.acctA.credit_time = oroute.credit_time conn_handlers = [self.oConn] disc_handlers = [] if not oroute.forward_on_fail and self.global_config['acct_enable']: disc_handlers.append(self.acctO.disc) self.uaO = UA(self.global_config, self.recvEvent, oroute.user, oroute.passw, nh_address, oroute.credit_time, tuple(conn_handlers), \ tuple(disc_handlers), tuple(disc_handlers), dead_cbs = (self.oDead,), expire_time = oroute.expires, \ no_progress_time = oroute.no_progress_expires, extra_headers = oroute.extra_headers) self.uaO.local_ua = self.global_config['_uaname'] if self.source != oroute.params.get('outbound_proxy', None): self.uaO.outbound_proxy = oroute.params.get('outbound_proxy', None) if self.rtp_proxy_session != None and oroute.params.get('rtpp', True): self.uaO.on_local_sdp_change = self.rtp_proxy_session.on_caller_sdp_change self.uaO.on_remote_sdp_change = self.rtp_proxy_session.on_callee_sdp_change self.rtp_proxy_session.caller.raddress = nh_address if body != None: body = body.getCopy() self.proxied = True self.uaO.kaInterval = self.global_config['keepalive_orig'] if 'group_timeout' in oroute.params: timeout, skipto = oroute.params['group_timeout'] Timeout(self.group_expires, timeout, 1, skipto) if self.global_config.getdefault('hide_call_id', False): cId = SipCallId(md5(str(cId).encode()).hexdigest() + ('-b2b_%d' % oroute.rnum)) else: cId += '-b2b_%d' % oroute.rnum event = CCEventTry((cId, cGUID, oroute.cli, cld, body, auth, \ oroute.params.get('caller_name', self.caller_name))) if self.eTry.max_forwards != None: event.max_forwards = self.eTry.max_forwards - 1 if event.max_forwards <= 0: self.uaA.recvEvent(CCEventFail((483, 'Too Many Hops'))) self.state = CCStateDead return event.reason = self.eTry.reason self.uaO.recvEvent(event)
def answer(self, global_config, body, req, sip_t): if self.connect_done or self.disconnect_done: return in_body = req.getBody() in_body.parse() cres, why = self.tccfg.checkhostport(in_body) if not cres: self.nerrs += 1 raise ValueError('%s: class %s: hostport validation has failed (%s): %s:\n%s' % \ (self.my_name(), str(self.__class__), self.atype, why, in_body)) # New dialog uaA = UA(global_config, self.recvEvent, disc_cbs = (self.disconnected,), \ fail_cbs = (self.disconnected,), dead_cbs = (self.alldone,)) uaA.godead_timeout = self.godead_timeout uaA.compact_sip = self.compact_sip Timeout(self.ring, self.ring_ival, 1, uaA) self.body = body self.call_id = req.getHFBody('call-id') return self.complete_answer(uaA, req, sip_t)
def __init__(self, global_config, body, done_cb, portrange, atype = 'IP4', \ cli = None): self.atype = atype if cli != None: self.cli = cli if atype == 'IP4': nh_address = self.nh_address4 else: nh_address = self.nh_address6 uaO = UA(global_config, event_cb = self.recvEvent, nh_address = nh_address, \ conn_cbs = (self.connected,), disc_cbs = (self.disconnected,), fail_cbs = (self.disconnected,), \ dead_cbs = (self.alldone,)) uaO.godead_timeout = 10 uaO.compact_sip = self.compact_sip event = CCEventTry((SipCallId(), SipCiscoGUID(), self.cli, self.cld, body, \ None, 'Alice Smith')) self.done_cb = done_cb self.portrange = portrange self.run(uaO, event)
def recvEvent(self, event, ua): if ua == self.uaA: if self.uaO == None: if not isinstance(event, CCEventTry): # Some weird event received self.uaA.recvEvent(CCEventDisconnect()) return self.uaO = UA(self.global_config, event_cb = self.recvEvent, nh_address = (self.global_config['nh_addr'], self.global_config['sip_port_default'])) self.uaO.recvEvent(event) else: self.uaA.recvEvent(event)
def __init__(self, remote_ip, source, global_config, pass_headers): self.id = CallController.id CallController.id += 1 self.global_config = global_config self.uaA = UA(self.global_config, event_cb = self.recvEvent, conn_cbs = (self.aConn,), disc_cbs = (self.aDisc,), \ fail_cbs = (self.aDisc,), dead_cbs = (self.aDead,)) self.uaA.kaInterval = self.global_config['keepalive_ans'] self.state = CCStateIdle self.uaO = None self.routes = [] self.remote_ip = remote_ip self.source = source self.pass_headers = pass_headers
def sess_term(self, ua, rtime, origin, result = 0): print('disconnected', origin) if origin == 'IoTUAC': return self.rgen.suspend() self.ua = UA(self.global_config, event_cb = self.recvEvent, \ nh_address = tuple(self.global_config['nh_addr']), disc_cbs = (self.sess_term,)) self.ua.username = self.authname self.ua.password = self.authpass self.body.content.o_header = SdpOrigin() event = CCEventTry((SipCallId(), SipCiscoGUID(), self.cli, self.cld, self.body, \ None, 'PEL 150-2')) self.ua.recvEvent(event)
def sess_started(self): print('started') self.ua = UA(self.global_config, event_cb = self.recvEvent, \ nh_address = tuple(self.global_config['nh_addr']), disc_cbs = (self.sess_term,)) self.ua.username = self.authname self.ua.password = self.authpass rtp_laddr = local4remote(self.global_config['nh_addr'][0]) rserv_opts = Udp_server_opts((rtp_laddr, 0), self.rtp_received) rserv_opts.nworkers = 1 self.rserv = Udp_server({}, rserv_opts) sect = self.body.content.sections[0] sect.c_header.addr = self.rserv.uopts.laddress[0] sect.m_header.port = self.rserv.uopts.laddress[1] self.body.content.o_header = SdpOrigin() event = CCEventTry((SipCallId(), SipCiscoGUID(), self.cli, self.cld, self.body, \ None, 'PEL 150-2')) self.rgen = RTPGen() self.ua.recvEvent(event) return (self.rgen.enqueue)
def placeOriginate(self, args, conn_cbs): cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData() rnum, host, cld, credit_time, expires, no_progress_expires, forward_on_fail, user, passw, cli, \ parameters = args self.huntstop_scodes = parameters.get('huntstop_scodes', ()) if self.global_config.has_key('static_tr_out'): cld = re_replace(self.global_config['static_tr_out'], cld) if host == 'sip-ua': host = self.source[0] port = self.source[1] else: host = host.split(':', 1) if len(host) > 1: port = int(host[1]) else: port = SipConf.default_port host = host[0] disc_cbs = [] if not forward_on_fail and self.global_config['acct_enable']: self.acctO = RadiusAccounting(self.global_config, 'originate', send_start = self.global_config['start_acct_enable']) self.acctO.setParams(parameters.get('bill-to', self.username), parameters.get('bill-cli', cli), \ parameters.get('bill-cld', cld), self.cGUID, self.cId, host, credit_time) print 'adding acct stop cb' disc_cbs.append(self.acctO.disc) else: self.acctO = None self.acctA.credit_time = credit_time ua = UA(self.global_config, self.recvEvent, user, passw, (host, port), credit_time, \ (conn_cbs,), tuple(disc_cbs), tuple(disc_cbs), dead_cbs = (self.oDead,), \ expire_time = expires, no_progress_time = no_progress_expires, \ extra_headers = parameters.get('extra_headers', None)) if self.rtp_proxy_session and parameters.get('rtpp', True): ua.on_local_sdp_change = self.rtp_proxy_session.on_caller_sdp_change ua.on_remote_sdp_change = self.rtp_proxy_session.on_callee_sdp_change body = body.getCopy() body.content += 'a=nortpproxy:yes\r\n' self.proxied = True ua.kaInterval = self.global_config['ka_orig'] if parameters.has_key('group_timeout'): timeout, skipto = parameters['group_timeout'] Timeout(self.group_expires, timeout, 1, skipto) ua.recvEvent(CCEventTry((cId + '-b2b_%d' % rnum, cGUID, cli, cld, body, auth, \ parameters.get('caller_name', self.caller_name)))) return ua
def placeAnswer(self, args): cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData() #TODO: move to a subroutine rnum, host, cld, credit_time, expires, no_progress_expires, forward_on_fail, user, passw, cli, \ parameters = args self.huntstop_scodes = parameters.get('huntstop_scodes', ()) if self.global_config.has_key('static_tr_out'): cld = re_replace(self.global_config['static_tr_out'], cld) if host == 'sip-ua': host = self.source[0] port = self.source[1] else: host = host.split(':', 1) if len(host) > 1: port = int(host[1]) else: port = SipConf.default_port host = host[0] if not forward_on_fail and self.global_config['acct_enable']: self.acctA = RadiusAccounting(self.global_config, 'answer', send_start = self.global_config['start_acct_enable']) self.acctA.setParams(parameters.get('bill-to', self.username), parameters.get('bill-cli', cli), \ parameters.get('bill-cld', cld), self.cGUID, self.cId, host, credit_time) print 'adding acct stop cb' else: self.acctA = FakeAccounting() ua = UA(self.global_config, self.recvEvent, user, passw, (host, port), credit_time, \ (self.aConnA,), (self.aDisc,), (self.aDisc,), dead_cbs = (self.aDead,), \ expire_time = expires, no_progress_time = no_progress_expires, \ extra_headers = parameters.get('extra_headers', None)) if self.rtp_proxy_session and parameters.get('rtpp', True): print 'placeAnswer() registering on sdp change callbacks' ua.on_local_sdp_change = self.rtp_proxy_session.on_callee_sdp_change ua.on_remote_sdp_change = self.rtp_proxy_session.on_caller_sdp_change body = body.getCopy() body.content += 'a=nortpproxy:yes\r\n' self.proxied = True ua.kaInterval = self.global_config['ka_ans'] #TODO: is this okay for uaA? if parameters.has_key('group_timeout'): timeout, skipto = parameters['group_timeout'] Timeout(self.group_expires, timeout, 1, skipto) ua.recvEvent(CCEventTry((cId + '-b2b_%d' % rnum, cGUID, cli, cld, body, auth, \ parameters.get('caller_name', self.caller_name)))) return ua
class CallController(object): global_config = None uaA = None uaO = None nh_addr = None def __init__(self, global_config): self.global_config = global_config self.uaA = UA(self.global_config, self.recvEvent) self.uaO = None def recvEvent(self, event, ua): if ua == self.uaA: if self.uaO == None: if not isinstance(event, CCEventTry): # Some weird event received self.uaA.recvEvent(CCEventDisconnect()) return self.uaO = UA(self.global_config, event_cb = self.recvEvent, nh_address = (self.global_config['nh_addr'], self.global_config['sip_port_default'])) self.uaO.recvEvent(event) else: self.uaA.recvEvent(event)
class CallController(object): global_config = None uaA = None uaO = None nh_addr = None def __init__(self, global_config): self.global_config = global_config self.uaA = UA(self.global_config, self.recvEvent) self.uaO = None def recvEvent(self, event, ua): if ua == self.uaA: if self.uaO == None: if not isinstance(event, CCEventTry): # Some weird event received self.uaA.recvEvent(CCEventDisconnect()) return self.uaO = UA(self.global_config, event_cb=self.recvEvent, \ nh_address=self.global_config['nh_addr']) self.uaO.recvEvent(event) else: self.uaA.recvEvent(event)
class CallController(object): id = 1 uaA = None uaO = None state = None cId = None cld = None eTry = None routes = None remote_ip = None source = None acctA = None acctO = None global_config = None rtp_proxy_session = None huntstop_scodes = None pass_headers = None auth_proc = None proxied = False challenge = None def __init__(self, remote_ip, source, global_config, pass_headers): self.id = CallController.id CallController.id += 1 self.global_config = global_config self.uaA = UA(self.global_config, event_cb = self.recvEvent, conn_cbs = (self.aConn,), disc_cbs = (self.aDisc,), \ fail_cbs = (self.aDisc,), dead_cbs = (self.aDead,)) self.uaA.kaInterval = self.global_config['keepalive_ans'] self.state = CCStateIdle self.uaO = None self.routes = [] self.remote_ip = remote_ip self.source = source self.pass_headers = pass_headers def recvEvent(self, event, ua): if ua == self.uaA: if self.state == CCStateIdle: if not isinstance(event, CCEventTry): # Some weird event received self.uaA.recvEvent(CCEventDisconnect(rtime = event.rtime)) return self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name = event.getData() self.cGUID = cGUID.hexForm() if self.cld == None: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (1)'), rtime = event.rtime)) self.state = CCStateDead return if body != None and self.global_config.has_key('_allowed_pts'): try: body.parse() except: self.uaA.recvEvent(CCEventFail((400, 'Malformed SDP Body'), rtime = event.rtime)) self.state = CCStateDead return allowed_pts = self.global_config['_allowed_pts'] mbody = body.content.sections[0].m_header if mbody.transport.lower() == 'rtp/avp': old_len = len(mbody.formats) mbody.formats = [x for x in mbody.formats if x in allowed_pts] if len(mbody.formats) == 0: self.uaA.recvEvent(CCEventFail((488, 'Not Acceptable Here'))) self.state = CCStateDead return if old_len > len(mbody.formats): body.content.sections[0].optimize_a() if self.cld.startswith('nat-'): self.cld = self.cld[4:] if body != None: body.content += 'a=nated:yes\r\n' event.data = (self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name) if self.global_config.has_key('static_tr_in'): self.cld = re_replace(self.global_config['static_tr_in'], self.cld) event.data = (self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name) if self.global_config.has_key('_rtp_proxy_clients'): self.rtp_proxy_session = Rtp_proxy_session(self.global_config, call_id = self.cId, \ notify_socket = global_config['b2bua_socket'], \ notify_tag = quote('r %s' % str(self.id))) self.rtp_proxy_session.callee_raddress = (self.remote_ip, 5060) self.eTry = event self.state = CCStateWaitRoute if not self.global_config['auth_enable']: self.username = self.remote_ip self.rDone(((), 0)) elif auth == None or auth.username == None or len(auth.username) == 0: self.username = self.remote_ip self.auth_proc = self.global_config['_radius_client'].do_auth(self.remote_ip, self.cli, self.cld, self.cGUID, \ self.cId, self.remote_ip, self.rDone) else: self.username = auth.username self.auth_proc = self.global_config['_radius_client'].do_auth(auth.username, self.cli, self.cld, self.cGUID, self.cId, self.remote_ip, self.rDone, auth.realm, auth.nonce, auth.uri, auth.response) return if self.state not in (CCStateARComplete, CCStateConnected, CCStateDisconnecting) or self.uaO == None: return self.uaO.recvEvent(event) else: if (isinstance(event, CCEventFail) or isinstance(event, CCEventDisconnect)) and self.state == CCStateARComplete and \ (isinstance(self.uaA.state, UasStateTrying) or isinstance(self.uaA.state, UasStateRinging)) and len(self.routes) > 0: if isinstance(event, CCEventFail): code = event.getData()[0] else: code = None if code == None or code not in self.huntstop_scodes: self.placeOriginate(self.routes.pop(0)) return self.uaA.recvEvent(event) def rDone(self, results): # Check that we got necessary result from Radius if len(results) != 2 or results[1] != 0: if isinstance(self.uaA.state, UasStateTrying): if self.challenge != None: event = CCEventFail((401, 'Unauthorized')) event.extra_header = self.challenge else: event = CCEventFail((403, 'Auth Failed')) self.uaA.recvEvent(event) self.state = CCStateDead return if self.global_config['acct_enable']: self.acctA = RadiusAccounting(self.global_config, 'answer', \ send_start = self.global_config['start_acct_enable'], lperiod = \ self.global_config.getdefault('alive_acct_int', None)) self.acctA.ms_precision = self.global_config.getdefault('precise_acct', False) self.acctA.setParams(self.username, self.cli, self.cld, self.cGUID, self.cId, self.remote_ip) else: self.acctA = FakeAccounting() # Check that uaA is still in a valid state, send acct stop if not isinstance(self.uaA.state, UasStateTrying): self.acctA.disc(self.uaA, time(), 'caller') return cli = [x[1][4:] for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('CLI:')] if len(cli) > 0: self.cli = cli[0] if len(self.cli) == 0: self.cli = None caller_name = [x[1][5:] for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('CNAM:')] if len(caller_name) > 0: self.caller_name = caller_name[0] if len(self.caller_name) == 0: self.caller_name = None credit_time = [x for x in results[0] if x[0] == 'h323-credit-time'] if len(credit_time) > 0: global_credit_time = int(credit_time[0][1]) else: global_credit_time = None if not self.global_config.has_key('static_route'): routing = [x for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('Routing:')] if len(routing) == 0: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (2)'))) self.state = CCStateDead return routing = [x[1][8:].split(';') for x in routing] else: routing = [self.global_config['static_route'].split(';')] rnum = 0 for route in routing: rnum += 1 if route[0].find('@') != -1: cld, host = route[0].split('@', 1) if len(cld) == 0: # Allow CLD to be forcefully removed by sending `Routing:@host' entry, # as opposed to the Routing:host, which means that CLD should be obtained # from the incoming call leg. cld = None else: cld = self.cld host = route[0] credit_time = global_credit_time expires = None no_progress_expires = None forward_on_fail = False user = None passw = None cli = self.cli parameters = {} parameters['extra_headers'] = self.pass_headers[:] for a, v in [x.split('=', 1) for x in route[1:]]: if a == 'credit-time': credit_time = int(v) if credit_time < 0: credit_time = None elif a == 'expires': expires = int(v) if expires < 0: expires = None elif a == 'hs_scodes': parameters['huntstop_scodes'] = tuple([int(x) for x in v.split(',') if len(x.strip()) > 0]) elif a == 'np_expires': no_progress_expires = int(v) if no_progress_expires < 0: no_progress_expires = None elif a == 'forward_on_fail': forward_on_fail = True elif a == 'auth': user, passw = v.split(':', 1) elif a == 'cli': cli = v if len(cli) == 0: cli = None elif a == 'cnam': caller_name = unquote(v) if len(caller_name) == 0: caller_name = None parameters['caller_name'] = caller_name elif a == 'ash': ash = SipHeader(unquote(v)) parameters['extra_headers'].append(ash) elif a == 'rtpp': parameters['rtpp'] = (int(v) != 0) elif a == 'gt': timeout, skip = v.split(',', 1) parameters['group_timeout'] = (int(timeout), rnum + int(skip)) elif a == 'op': host_port = v.split(':', 1) if len(host_port) == 1: parameters['outbound_proxy'] = (v, 5060) else: parameters['outbound_proxy'] = (host_port[0], int(host_port[1])) else: parameters[a] = v if self.global_config.has_key('max_credit_time'): if credit_time == None or credit_time > self.global_config['max_credit_time']: credit_time = self.global_config['max_credit_time'] if credit_time == 0 or expires == 0: continue self.routes.append((rnum, host, cld, credit_time, expires, no_progress_expires, forward_on_fail, user, \ passw, cli, parameters)) #print 'Got route:', host, cld if len(self.routes) == 0: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (3)'))) self.state = CCStateDead return self.state = CCStateARComplete self.placeOriginate(self.routes.pop(0)) def placeOriginate(self, args): cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData() rnum, host, cld, credit_time, expires, no_progress_expires, forward_on_fail, user, passw, cli, \ parameters = args self.huntstop_scodes = parameters.get('huntstop_scodes', ()) if self.global_config.has_key('static_tr_out'): cld = re_replace(self.global_config['static_tr_out'], cld) if host == 'sip-ua': host = self.source[0] port = self.source[1] else: if host.startswith('['): # IPv6 host = host.split(']', 1) port = host[1].split(':', 1) host = host[0] + ']' if len(port) > 1: port = int(port[1]) else: port = SipConf.default_port else: # IPv4 host = host.split(':', 1) if len(host) > 1: port = int(host[1]) else: port = SipConf.default_port host = host[0] if not forward_on_fail and self.global_config['acct_enable']: self.acctO = RadiusAccounting(self.global_config, 'originate', \ send_start = self.global_config['start_acct_enable'], lperiod = \ self.global_config.getdefault('alive_acct_int', None)) self.acctO.ms_precision = self.global_config.getdefault('precise_acct', False) self.acctO.setParams(parameters.get('bill-to', self.username), parameters.get('bill-cli', cli), \ parameters.get('bill-cld', cld), self.cGUID, self.cId, host) else: self.acctO = None self.acctA.credit_time = credit_time conn_handlers = [self.oConn] disc_handlers = [] if not forward_on_fail and self.global_config['acct_enable']: disc_handlers.append(self.acctO.disc) self.uaO = UA(self.global_config, self.recvEvent, user, passw, (host, port), credit_time, tuple(conn_handlers), \ tuple(disc_handlers), tuple(disc_handlers), dead_cbs = (self.oDead,), expire_time = expires, \ no_progress_time = no_progress_expires, extra_headers = parameters.get('extra_headers', None)) if self.source != parameters.get('outbound_proxy', None): self.uaO.outbound_proxy = parameters.get('outbound_proxy', None) if self.rtp_proxy_session != None and parameters.get('rtpp', True): self.uaO.on_local_sdp_change = self.rtp_proxy_session.on_caller_sdp_change self.uaO.on_remote_sdp_change = self.rtp_proxy_session.on_callee_sdp_change self.rtp_proxy_session.caller_raddress = (host, port) if body != None: body = body.getCopy() body.content += 'a=nortpproxy:yes\r\n' self.proxied = True self.uaO.kaInterval = self.global_config['keepalive_orig'] if parameters.has_key('group_timeout'): timeout, skipto = parameters['group_timeout'] Timeout(self.group_expires, timeout, 1, skipto) if self.global_config.getdefault('hide_call_id', False): cId = SipCallId(md5(str(cId)).hexdigest() + ('-b2b_%d' % rnum)) else: cId += '-b2b_%d' % rnum event = CCEventTry((cId, cGUID, cli, cld, body, auth, \ parameters.get('caller_name', self.caller_name))) event.reason = self.eTry.reason self.uaO.recvEvent(event) def disconnect(self, rtime = None): self.uaA.disconnect(rtime = rtime) def oConn(self, ua, rtime, origin): if self.acctO != None: self.acctO.conn(ua, rtime, origin) def aConn(self, ua, rtime, origin): self.state = CCStateConnected self.acctA.conn(ua, rtime, origin) def aDisc(self, ua, rtime, origin, result = 0): if self.state == CCStateWaitRoute and self.auth_proc != None: self.auth_proc.cancel() self.auth_proc = None if self.uaO != None and self.state != CCStateDead: self.state = CCStateDisconnecting else: self.state = CCStateDead if self.acctA != None: self.acctA.disc(ua, rtime, origin, result) self.rtp_proxy_session = None def aDead(self, ua): if (self.uaO == None or isinstance(self.uaO.state, UaStateDead)): if self.global_config['_cmap'].debug_mode: print('garbadge collecting', self) self.acctA = None self.acctO = None self.global_config['_cmap'].ccmap.remove(self) def oDead(self, ua): if ua == self.uaO and isinstance(self.uaA.state, UaStateDead): if self.global_config['_cmap'].debug_mode: print('garbadge collecting', self) self.acctA = None self.acctO = None self.global_config['_cmap'].ccmap.remove(self) def group_expires(self, skipto): if self.state != CCStateARComplete or len(self.routes) == 0 or self.routes[0][0] > skipto or \ (not isinstance(self.uaA.state, UasStateTrying) and not isinstance(self.uaA.state, UasStateRinging)): return # When the last group in the list has timeouted don't disconnect # the current attempt forcefully. Instead, make sure that if the # current originate call leg fails no more routes will be # processed. if skipto == self.routes[-1][0] + 1: self.routes = [] return while self.routes[0][0] != skipto: self.routes.pop(0) self.uaO.disconnect()
def placeOriginate(self, args): cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData() rnum, host, cld, credit_time, expires, no_progress_expires, forward_on_fail, user, passw, cli, \ parameters = args self.huntstop_scodes = parameters.get('huntstop_scodes', ()) if self.global_config.has_key('static_tr_out'): cld = re_replace(self.global_config['static_tr_out'], cld) if host == 'sip-ua': host = self.source[0] port = self.source[1] else: if host.startswith('['): # IPv6 host = host.split(']', 1) port = host[1].split(':', 1) host = host[0] + ']' if len(port) > 1: port = int(port[1]) else: port = SipConf.default_port else: # IPv4 host = host.split(':', 1) if len(host) > 1: port = int(host[1]) else: port = SipConf.default_port host = host[0] if not forward_on_fail and self.global_config['acct_enable']: self.acctO = RadiusAccounting(self.global_config, 'originate', \ send_start = self.global_config['start_acct_enable'], lperiod = \ self.global_config.getdefault('alive_acct_int', None)) self.acctO.ms_precision = self.global_config.getdefault('precise_acct', False) self.acctO.setParams(parameters.get('bill-to', self.username), parameters.get('bill-cli', cli), \ parameters.get('bill-cld', cld), self.cGUID, self.cId, host) else: self.acctO = None self.acctA.credit_time = credit_time conn_handlers = [self.oConn] disc_handlers = [] if not forward_on_fail and self.global_config['acct_enable']: disc_handlers.append(self.acctO.disc) self.uaO = UA(self.global_config, self.recvEvent, user, passw, (host, port), credit_time, tuple(conn_handlers), \ tuple(disc_handlers), tuple(disc_handlers), dead_cbs = (self.oDead,), expire_time = expires, \ no_progress_time = no_progress_expires, extra_headers = parameters.get('extra_headers', None)) if self.source != parameters.get('outbound_proxy', None): self.uaO.outbound_proxy = parameters.get('outbound_proxy', None) if self.rtp_proxy_session != None and parameters.get('rtpp', True): self.uaO.on_local_sdp_change = self.rtp_proxy_session.on_caller_sdp_change self.uaO.on_remote_sdp_change = self.rtp_proxy_session.on_callee_sdp_change self.rtp_proxy_session.caller_raddress = (host, port) if body != None: body = body.getCopy() body.content += 'a=nortpproxy:yes\r\n' self.proxied = True self.uaO.kaInterval = self.global_config['keepalive_orig'] if parameters.has_key('group_timeout'): timeout, skipto = parameters['group_timeout'] Timeout(self.group_expires, timeout, 1, skipto) if self.global_config.getdefault('hide_call_id', False): cId = SipCallId(md5(str(cId)).hexdigest() + ('-b2b_%d' % rnum)) else: cId += '-b2b_%d' % rnum event = CCEventTry((cId, cGUID, cli, cld, body, auth, \ parameters.get('caller_name', self.caller_name))) event.reason = self.eTry.reason self.uaO.recvEvent(event)
def __init__(self, global_config): self.global_config = global_config self.uaA = UA(self.global_config, self.recvEvent) self.uaO = None
def register_clients(ud): # For each record in UserData list create a registrar UA for (InternalUserId, ExtDisplayName, ExtName, ExtLogin, ExtPassword, ExtDomain, ExtPort) in ud.Data: Ua = UA(global_config, event_cb=recvEvent, username=ExtLogin, password=ExtPassword, conn_cbs=(recvConnect, ), disc_cbs=(recvDisconnect, ), fail_cbs=(recvDisconnect, ), dead_cbs=(recvDead, ), nh_address=(global_config['proxy_address'], global_config['proxy_port'])) if ExtPort == None: Ua.rTarget = SipURL(url="sip:" + ExtName + "@" + ExtDomain) Ua.rUri = SipTo(body="<sip:" + ExtName + "@" + ExtDomain + ">") Ua.lUri = SipFrom(body=ExtDisplayName + " <sip:" + ExtName + "@" + ExtDomain + ">") else: Ua.rTarget = SipURL(url="sip:" + ExtName + "@" + ExtDomain + ":" + ExtPort) Ua.rUri = SipTo(body="<sip:" + ExtName + "@" + ExtDomain + ":" + ExtPort + ">") Ua.lUri = SipFrom(body=ExtDisplayName + " <sip:" + ExtName + "@" + ExtDomain + ":" + ExtPort + ">") Ua.lUri.parse() Ua.lUri.genTag() Ua.lContact = SipContact(body="<sip:" + InternalUserId + "@" + global_config['proxy_address'] + ">") Ua.routes = () Ua.lCSeq = 1 Ua.rCSeq = 1 Ua.cId = SipCallId() req = Ua.genRequest("REGISTER") Ua.changeState((UacStateTrying, )) global_config['_sip_tm'].regConsumer(Ua, str(Ua.cId)) Ua.tr = global_config['_sip_tm'].newTransaction(req, Ua.recvResponse)
class CallController(object): id = 1 uaA = None uaO = None state = None cId = None cld = None eTry = None routes = None remote_ip = None source = None acctA = None acctO = None global_config = None rtp_proxy_session = None huntstop_scodes = None pass_headers = None auth_proc = None proxied = False challenge = None def __init__(self, remote_ip, source, global_config, pass_headers): self.id = CallController.id CallController.id += 1 self.global_config = global_config self.uaA = UA(self.global_config, event_cb = self.recvEvent, conn_cbs = (self.aConn,), disc_cbs = (self.aDisc,), \ fail_cbs = (self.aDisc,), dead_cbs = (self.aDead,)) self.uaA.kaInterval = self.global_config['keepalive_ans'] self.uaA.local_ua = self.global_config['_uaname'] self.state = CCStateIdle self.uaO = None self.routes = [] self.remote_ip = remote_ip self.source = source self.pass_headers = pass_headers def recvEvent(self, event, ua): if ua == self.uaA: if self.state == CCStateIdle: if not isinstance(event, CCEventTry): # Some weird event received self.uaA.recvEvent(CCEventDisconnect(rtime=event.rtime)) return self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name = event.getData( ) self.cGUID = cGUID.hexForm() if self.cld == None: self.uaA.recvEvent( CCEventFail((500, 'Internal Server Error (1)'), rtime=event.rtime)) self.state = CCStateDead return if body != None and '_allowed_pts' in self.global_config: try: body.parse() except: self.uaA.recvEvent( CCEventFail((400, 'Malformed SDP Body'), rtime=event.rtime)) self.state = CCStateDead return allowed_pts = self.global_config['_allowed_pts'] mbody = body.content.sections[0].m_header if mbody.transport.lower() == 'rtp/avp': old_len = len(mbody.formats) mbody.formats = [ x for x in mbody.formats if x in allowed_pts ] if len(mbody.formats) == 0: self.uaA.recvEvent( CCEventFail((488, 'Not Acceptable Here'))) self.state = CCStateDead return if old_len > len(mbody.formats): body.content.sections[0].optimize_a() if self.cld.startswith('nat-'): self.cld = self.cld[4:] if body != None: body.content += 'a=nated:yes\r\n' event.data = (self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name) if 'static_tr_in' in self.global_config: self.cld = re_replace(self.global_config['static_tr_in'], self.cld) event.data = (self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name) if '_rtp_proxy_clients' in self.global_config: self.rtp_proxy_session = Rtp_proxy_session(self.global_config, call_id = self.cId, \ notify_socket = self.global_config['b2bua_socket'], \ notify_tag = quote('r %s' % str(self.id))) self.rtp_proxy_session.callee.raddress = (self.remote_ip, 5060) self.rtp_proxy_session.insert_nortpp = True self.eTry = event self.state = CCStateWaitRoute if not self.global_config['auth_enable']: self.username = self.remote_ip self.rDone(((), 0)) elif auth == None or auth.username == None or len( auth.username) == 0: self.username = self.remote_ip self.auth_proc = self.global_config['_radius_client'].do_auth(self.remote_ip, self.cli, self.cld, self.cGUID, \ self.cId, self.remote_ip, self.rDone) else: self.username = auth.username self.auth_proc = self.global_config[ '_radius_client'].do_auth(auth.username, self.cli, self.cld, self.cGUID, self.cId, self.remote_ip, self.rDone, auth.realm, auth.nonce, auth.uri, auth.response) return if self.state not in (CCStateARComplete, CCStateConnected, CCStateDisconnecting) or self.uaO == None: return self.uaO.recvEvent(event) else: if (isinstance(event, CCEventFail) or isinstance(event, CCEventDisconnect)) and self.state == CCStateARComplete and \ (isinstance(self.uaA.state, UasStateTrying) or isinstance(self.uaA.state, UasStateRinging)) and len(self.routes) > 0: if isinstance(event, CCEventFail): code = event.getData()[0] else: code = None if code == None or code not in self.huntstop_scodes: self.placeOriginate(self.routes.pop(0)) return self.uaA.recvEvent(event) def rDone(self, results): # Check that we got necessary result from Radius if len(results) != 2 or results[1] != 0: if isinstance(self.uaA.state, UasStateTrying): if self.challenge != None: event = CCEventFail((401, 'Unauthorized')) event.extra_header = self.challenge else: event = CCEventFail((403, 'Auth Failed')) self.uaA.recvEvent(event) self.state = CCStateDead return if self.global_config['acct_enable']: self.acctA = RadiusAccounting(self.global_config, 'answer', \ send_start = self.global_config['start_acct_enable'], lperiod = \ self.global_config.getdefault('alive_acct_int', None)) self.acctA.ms_precision = self.global_config.getdefault( 'precise_acct', False) self.acctA.setParams(self.username, self.cli, self.cld, self.cGUID, self.cId, self.remote_ip) else: self.acctA = FakeAccounting() # Check that uaA is still in a valid state, send acct stop if not isinstance(self.uaA.state, UasStateTrying): self.acctA.disc(self.uaA, MonoTime(), 'caller') return cli = [ x[1][4:] for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('CLI:') ] if len(cli) > 0: self.cli = cli[0] if len(self.cli) == 0: self.cli = None caller_name = [ x[1][5:] for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('CNAM:') ] if len(caller_name) > 0: self.caller_name = caller_name[0] if len(self.caller_name) == 0: self.caller_name = None credit_time = [x for x in results[0] if x[0] == 'h323-credit-time'] if len(credit_time) > 0: credit_time = int(credit_time[0][1]) else: credit_time = None if not '_static_route' in self.global_config: routing = [ x for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('Routing:') ] if len(routing) == 0: self.uaA.recvEvent( CCEventFail((500, 'Internal Server Error (2)'))) self.state = CCStateDead return routing = [B2BRoute(x[1][8:]) for x in routing] else: routing = [ self.global_config['_static_route'].getCopy(), ] rnum = 0 for oroute in routing: rnum += 1 max_credit_time = self.global_config.getdefault( 'max_credit_time', None) oroute.customize(rnum, self.cld, self.cli, credit_time, self.pass_headers, \ max_credit_time) if oroute.credit_time == 0 or oroute.expires == 0: continue self.routes.append(oroute) #print 'Got route:', oroute.hostport, oroute.cld if len(self.routes) == 0: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (3)'))) self.state = CCStateDead return self.state = CCStateARComplete self.placeOriginate(self.routes.pop(0)) def placeOriginate(self, oroute): cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData() cld = oroute.cld self.huntstop_scodes = oroute.params.get('huntstop_scodes', ()) if 'static_tr_out' in self.global_config: cld = re_replace(self.global_config['static_tr_out'], cld) if oroute.hostport == 'sip-ua': host = self.source[0] nh_address, same_af = self.source, True else: host = oroute.hostonly nh_address, same_af = oroute.getNHAddr(self.source) if not oroute.forward_on_fail and self.global_config['acct_enable']: self.acctO = RadiusAccounting(self.global_config, 'originate', \ send_start = self.global_config['start_acct_enable'], lperiod = \ self.global_config.getdefault('alive_acct_int', None)) self.acctO.ms_precision = self.global_config.getdefault( 'precise_acct', False) self.acctO.setParams(oroute.params.get('bill-to', self.username), oroute.params.get('bill-cli', oroute.cli), \ oroute.params.get('bill-cld', cld), self.cGUID, self.cId, host) else: self.acctO = None self.acctA.credit_time = oroute.credit_time conn_handlers = [self.oConn] disc_handlers = [] if not oroute.forward_on_fail and self.global_config['acct_enable']: disc_handlers.append(self.acctO.disc) self.uaO = UA(self.global_config, self.recvEvent, oroute.user, oroute.passw, nh_address, oroute.credit_time, tuple(conn_handlers), \ tuple(disc_handlers), tuple(disc_handlers), dead_cbs = (self.oDead,), expire_time = oroute.expires, \ no_progress_time = oroute.no_progress_expires, extra_headers = oroute.extra_headers) self.uaO.local_ua = self.global_config['_uaname'] if self.source != oroute.params.get('outbound_proxy', None): self.uaO.outbound_proxy = oroute.params.get('outbound_proxy', None) if self.rtp_proxy_session != None and oroute.params.get('rtpp', True): self.uaO.on_local_sdp_change = self.rtp_proxy_session.on_caller_sdp_change self.uaO.on_remote_sdp_change = self.rtp_proxy_session.on_callee_sdp_change self.rtp_proxy_session.caller.raddress = nh_address if body != None: body = body.getCopy() self.proxied = True self.uaO.kaInterval = self.global_config['keepalive_orig'] if 'group_timeout' in oroute.params: timeout, skipto = oroute.params['group_timeout'] Timeout(self.group_expires, timeout, 1, skipto) if self.global_config.getdefault('hide_call_id', False): cId = SipCallId( md5(str(cId).encode()).hexdigest() + ('-b2b_%d' % oroute.rnum)) else: cId += '-b2b_%d' % oroute.rnum event = CCEventTry((cId, cGUID, oroute.cli, cld, body, auth, \ oroute.params.get('caller_name', self.caller_name))) if self.eTry.max_forwards != None: event.max_forwards = self.eTry.max_forwards - 1 if event.max_forwards <= 0: self.uaA.recvEvent(CCEventFail((483, 'Too Many Hops'))) self.state = CCStateDead return event.reason = self.eTry.reason self.uaO.recvEvent(event) def disconnect(self, rtime=None): self.uaA.disconnect(rtime=rtime) def oConn(self, ua, rtime, origin): if self.acctO != None: self.acctO.conn(ua, rtime, origin) def aConn(self, ua, rtime, origin): self.state = CCStateConnected self.acctA.conn(ua, rtime, origin) def aDisc(self, ua, rtime, origin, result=0): if self.state == CCStateWaitRoute and self.auth_proc != None: self.auth_proc.cancel() self.auth_proc = None if self.uaO != None and self.state != CCStateDead: self.state = CCStateDisconnecting else: self.state = CCStateDead if self.acctA != None: self.acctA.disc(ua, rtime, origin, result) self.rtp_proxy_session = None def aDead(self, ua): if (self.uaO == None or isinstance(self.uaO.state, UaStateDead)): if self.global_config['_cmap'].debug_mode: print('garbadge collecting', self) self.acctA = None self.acctO = None self.global_config['_cmap'].ccmap.remove(self) def oDead(self, ua): if ua == self.uaO and isinstance(self.uaA.state, UaStateDead): if self.global_config['_cmap'].debug_mode: print('garbadge collecting', self) self.acctA = None self.acctO = None self.global_config['_cmap'].ccmap.remove(self) def group_expires(self, skipto): if self.state != CCStateARComplete or len(self.routes) == 0 or self.routes[0][0] > skipto or \ (not isinstance(self.uaA.state, UasStateTrying) and not isinstance(self.uaA.state, UasStateRinging)): return # When the last group in the list has timeouted don't disconnect # the current attempt forcefully. Instead, make sure that if the # current originate call leg fails no more routes will be # processed. if skipto == self.routes[-1][0] + 1: self.routes = [] return while self.routes[0][0] != skipto: self.routes.pop(0) self.uaO.disconnect()
class CallController(object): id = 1 uaA = None uaO = None state = None cId = None cld = None eTry = None routes = None remote_ip = None source = None acctA = None acctO = None global_config = None rtp_proxy_session = None huntstop_scodes = None pass_headers = None auth_proc = None proxied = False challenge = None def __init__(self, remote_ip, source, global_config, pass_headers): self.id = CallController.id CallController.id += 1 self.global_config = global_config self.uaA = UA(self.global_config, event_cb = self.recvEvent, conn_cbs = (self.aConn,), disc_cbs = (self.aDisc,), \ fail_cbs = (self.aDisc,), dead_cbs = (self.aDead,)) self.uaA.kaInterval = self.global_config['keepalive_ans'] self.uaA.local_ua = self.global_config['_uaname'] self.state = CCStateIdle self.uaO = None self.routes = [] self.remote_ip = remote_ip self.source = source self.pass_headers = pass_headers def recvEvent(self, event, ua): if ua == self.uaA: if self.state == CCStateIdle: if not isinstance(event, CCEventTry): # Some weird event received self.uaA.recvEvent(CCEventDisconnect(rtime = event.rtime)) return self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name = event.getData() self.cGUID = cGUID.hexForm() if self.cld == None: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (1)'), rtime = event.rtime)) self.state = CCStateDead return if body != None and '_allowed_pts' in self.global_config: try: body.parse() except: self.uaA.recvEvent(CCEventFail((400, 'Malformed SDP Body'), rtime = event.rtime)) self.state = CCStateDead return allowed_pts = self.global_config['_allowed_pts'] mbody = body.content.sections[0].m_header if mbody.transport.lower() == 'rtp/avp': old_len = len(mbody.formats) mbody.formats = [x for x in mbody.formats if x in allowed_pts] if len(mbody.formats) == 0: self.uaA.recvEvent(CCEventFail((488, 'Not Acceptable Here'))) self.state = CCStateDead return if old_len > len(mbody.formats): body.content.sections[0].optimize_a() if self.cld.startswith('nat-'): self.cld = self.cld[4:] if body != None: body.content += 'a=nated:yes\r\n' event.data = (self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name) if 'static_tr_in' in self.global_config: self.cld = re_replace(self.global_config['static_tr_in'], self.cld) event.data = (self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name) if '_rtp_proxy_clients' in self.global_config: self.rtp_proxy_session = Rtp_proxy_session(self.global_config, call_id = self.cId, \ notify_socket = self.global_config['b2bua_socket'], \ notify_tag = quote('r %s' % str(self.id))) self.rtp_proxy_session.callee.raddress = (self.remote_ip, 5060) self.rtp_proxy_session.insert_nortpp = True self.eTry = event self.state = CCStateWaitRoute if not self.global_config['auth_enable']: self.username = self.remote_ip self.rDone(((), 0)) elif auth == None or auth.username == None or len(auth.username) == 0: self.username = self.remote_ip self.auth_proc = self.global_config['_radius_client'].do_auth(self.remote_ip, self.cli, self.cld, self.cGUID, \ self.cId, self.remote_ip, self.rDone) else: self.username = auth.username self.auth_proc = self.global_config['_radius_client'].do_auth(auth.username, self.cli, self.cld, self.cGUID, self.cId, self.remote_ip, self.rDone, auth.realm, auth.nonce, auth.uri, auth.response) return if self.state not in (CCStateARComplete, CCStateConnected, CCStateDisconnecting) or self.uaO == None: return self.uaO.recvEvent(event) else: if (isinstance(event, CCEventFail) or isinstance(event, CCEventDisconnect)) and self.state == CCStateARComplete and \ (isinstance(self.uaA.state, UasStateTrying) or isinstance(self.uaA.state, UasStateRinging)) and len(self.routes) > 0: if isinstance(event, CCEventFail): code = event.getData()[0] else: code = None if code == None or code not in self.huntstop_scodes: self.placeOriginate(self.routes.pop(0)) return self.uaA.recvEvent(event) def rDone(self, results): # Check that we got necessary result from Radius if len(results) != 2 or results[1] != 0: if isinstance(self.uaA.state, UasStateTrying): if self.challenge != None: event = CCEventFail((401, 'Unauthorized')) event.extra_header = self.challenge else: event = CCEventFail((403, 'Auth Failed')) self.uaA.recvEvent(event) self.state = CCStateDead return if self.global_config['acct_enable']: self.acctA = RadiusAccounting(self.global_config, 'answer', \ send_start = self.global_config['start_acct_enable'], lperiod = \ self.global_config.getdefault('alive_acct_int', None)) self.acctA.ms_precision = self.global_config.getdefault('precise_acct', False) self.acctA.setParams(self.username, self.cli, self.cld, self.cGUID, self.cId, self.remote_ip) else: self.acctA = FakeAccounting() # Check that uaA is still in a valid state, send acct stop if not isinstance(self.uaA.state, UasStateTrying): self.acctA.disc(self.uaA, MonoTime(), 'caller') return cli = [x[1][4:] for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('CLI:')] if len(cli) > 0: self.cli = cli[0] if len(self.cli) == 0: self.cli = None caller_name = [x[1][5:] for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('CNAM:')] if len(caller_name) > 0: self.caller_name = caller_name[0] if len(self.caller_name) == 0: self.caller_name = None credit_time = [x for x in results[0] if x[0] == 'h323-credit-time'] if len(credit_time) > 0: credit_time = int(credit_time[0][1]) else: credit_time = None if not '_static_route' in self.global_config: routing = [x for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('Routing:')] if len(routing) == 0: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (2)'))) self.state = CCStateDead return routing = [B2BRoute(x[1][8:]) for x in routing] else: routing = [self.global_config['_static_route'].getCopy(),] rnum = 0 for oroute in routing: rnum += 1 max_credit_time = self.global_config.getdefault('max_credit_time', None) oroute.customize(rnum, self.cld, self.cli, credit_time, self.pass_headers, \ max_credit_time) if oroute.credit_time == 0 or oroute.expires == 0: continue self.routes.append(oroute) #print 'Got route:', oroute.hostport, oroute.cld if len(self.routes) == 0: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (3)'))) self.state = CCStateDead return self.state = CCStateARComplete self.placeOriginate(self.routes.pop(0)) def placeOriginate(self, oroute): cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData() cld = oroute.cld self.huntstop_scodes = oroute.params.get('huntstop_scodes', ()) if 'static_tr_out' in self.global_config: cld = re_replace(self.global_config['static_tr_out'], cld) if oroute.hostport == 'sip-ua': host = self.source[0] nh_address, same_af = self.source, True else: host = oroute.hostonly nh_address, same_af = oroute.getNHAddr(self.source) if not oroute.forward_on_fail and self.global_config['acct_enable']: self.acctO = RadiusAccounting(self.global_config, 'originate', \ send_start = self.global_config['start_acct_enable'], lperiod = \ self.global_config.getdefault('alive_acct_int', None)) self.acctO.ms_precision = self.global_config.getdefault('precise_acct', False) self.acctO.setParams(oroute.params.get('bill-to', self.username), oroute.params.get('bill-cli', oroute.cli), \ oroute.params.get('bill-cld', cld), self.cGUID, self.cId, host) else: self.acctO = None self.acctA.credit_time = oroute.credit_time conn_handlers = [self.oConn] disc_handlers = [] if not oroute.forward_on_fail and self.global_config['acct_enable']: disc_handlers.append(self.acctO.disc) self.uaO = UA(self.global_config, self.recvEvent, oroute.user, oroute.passw, nh_address, oroute.credit_time, tuple(conn_handlers), \ tuple(disc_handlers), tuple(disc_handlers), dead_cbs = (self.oDead,), expire_time = oroute.expires, \ no_progress_time = oroute.no_progress_expires, extra_headers = oroute.extra_headers) self.uaO.local_ua = self.global_config['_uaname'] if self.source != oroute.params.get('outbound_proxy', None): self.uaO.outbound_proxy = oroute.params.get('outbound_proxy', None) if self.rtp_proxy_session != None and oroute.params.get('rtpp', True): self.uaO.on_local_sdp_change = self.rtp_proxy_session.on_caller_sdp_change self.uaO.on_remote_sdp_change = self.rtp_proxy_session.on_callee_sdp_change self.rtp_proxy_session.caller.raddress = nh_address if body != None: body = body.getCopy() self.proxied = True self.uaO.kaInterval = self.global_config['keepalive_orig'] if 'group_timeout' in oroute.params: timeout, skipto = oroute.params['group_timeout'] Timeout(self.group_expires, timeout, 1, skipto) if self.global_config.getdefault('hide_call_id', False): cId = SipCallId(md5(str(cId).encode()).hexdigest() + ('-b2b_%d' % oroute.rnum)) else: cId += '-b2b_%d' % oroute.rnum event = CCEventTry((cId, cGUID, oroute.cli, cld, body, auth, \ oroute.params.get('caller_name', self.caller_name))) if self.eTry.max_forwards != None: event.max_forwards = self.eTry.max_forwards - 1 if event.max_forwards <= 0: self.uaA.recvEvent(CCEventFail((483, 'Too Many Hops'))) self.state = CCStateDead return event.reason = self.eTry.reason self.uaO.recvEvent(event) def disconnect(self, rtime = None): self.uaA.disconnect(rtime = rtime) def oConn(self, ua, rtime, origin): if self.acctO != None: self.acctO.conn(ua, rtime, origin) def aConn(self, ua, rtime, origin): self.state = CCStateConnected self.acctA.conn(ua, rtime, origin) def aDisc(self, ua, rtime, origin, result = 0): if self.state == CCStateWaitRoute and self.auth_proc != None: self.auth_proc.cancel() self.auth_proc = None if self.uaO != None and self.state != CCStateDead: self.state = CCStateDisconnecting else: self.state = CCStateDead if self.acctA != None: self.acctA.disc(ua, rtime, origin, result) self.rtp_proxy_session = None def aDead(self, ua): if (self.uaO == None or isinstance(self.uaO.state, UaStateDead)): if self.global_config['_cmap'].debug_mode: print('garbadge collecting', self) self.acctA = None self.acctO = None self.global_config['_cmap'].ccmap.remove(self) def oDead(self, ua): if ua == self.uaO and isinstance(self.uaA.state, UaStateDead): if self.global_config['_cmap'].debug_mode: print('garbadge collecting', self) self.acctA = None self.acctO = None self.global_config['_cmap'].ccmap.remove(self) def group_expires(self, skipto): if self.state != CCStateARComplete or len(self.routes) == 0 or self.routes[0][0] > skipto or \ (not isinstance(self.uaA.state, UasStateTrying) and not isinstance(self.uaA.state, UasStateRinging)): return # When the last group in the list has timeouted don't disconnect # the current attempt forcefully. Instead, make sure that if the # current originate call leg fails no more routes will be # processed. if skipto == self.routes[-1][0] + 1: self.routes = [] return while self.routes[0][0] != skipto: self.routes.pop(0) self.uaO.disconnect()
def recvEvent(self, event): self.sdp_session.fixup_version(event) return UA.recvEvent(self, event)
def placeOriginate(self, args): cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData() rnum, host, cld, credit_time, expires, no_progress_expires, forward_on_fail, user, passw, cli, \ parameters = args self.huntstop_scodes = parameters.get('huntstop_scodes', ()) if self.global_config.has_key('static_tr_out'): cld = re_replace(self.global_config['static_tr_out'], cld) if host == 'sip-ua': host = self.source[0] port = self.source[1] else: if host.startswith('['): # IPv6 host = host.split(']', 1) port = host[1].split(':', 1) host = host[0] + ']' if len(port) > 1: port = int(port[1]) else: port = SipConf.default_port else: # IPv4 host = host.split(':', 1) if len(host) > 1: port = int(host[1]) else: port = SipConf.default_port host = host[0] if not forward_on_fail and self.global_config['acct_enable']: self.acctO = RadiusAccounting(self.global_config, 'originate', \ send_start = self.global_config['start_acct_enable'], lperiod = \ self.global_config.getdefault('alive_acct_int', None)) self.acctO.ms_precision = self.global_config.getdefault('precise_acct', False) self.acctO.setParams(parameters.get('bill-to', self.username), parameters.get('bill-cli', cli), \ parameters.get('bill-cld', cld), self.cGUID, self.cId, host) else: self.acctO = None self.acctA.credit_time = credit_time conn_handlers = [self.oConn] disc_handlers = [] if not forward_on_fail and self.global_config['acct_enable']: disc_handlers.append(self.acctO.disc) self.uaO = UA(self.global_config, self.recvEvent, user, passw, (host, port), credit_time, tuple(conn_handlers), \ tuple(disc_handlers), tuple(disc_handlers), dead_cbs = (self.oDead,), expire_time = expires, \ no_progress_time = no_progress_expires, extra_headers = parameters.get('extra_headers', None)) if self.rtp_proxy_session != None and parameters.get('rtpp', True): self.uaO.on_local_sdp_change = self.rtp_proxy_session.on_caller_sdp_change self.uaO.on_remote_sdp_change = self.rtp_proxy_session.on_callee_sdp_change self.rtp_proxy_session.caller_raddress = (host, port) body = body.getCopy() body.content += 'a=nortpproxy:yes\r\n' self.proxied = True self.uaO.kaInterval = self.global_config['keepalive_orig'] if parameters.has_key('group_timeout'): timeout, skipto = parameters['group_timeout'] Timeout(self.group_expires, timeout, 1, skipto) if self.global_config.getdefault('hide_call_id', False): cId = SipCallId(md5(str(cId)).hexdigest() + ('-b2b_%d' % rnum)) else: cId += '-b2b_%d' % rnum event = CCEventTry((cId, cGUID, cli, cld, body, auth, \ parameters.get('caller_name', self.caller_name))) event.reason = self.eTry.reason self.uaO.recvEvent(event)
class CallController(object): id = 1 uaA = None uaO = None state = None cId = None cld = None eTry = None routes = None remote_ip = None source = None acctA = None acctO = None global_config = None rtp_proxy_session = None huntstop_scodes = None pass_headers = None auth_proc = None proxied = False challenge = None def __init__(self, remote_ip, source, global_config, pass_headers, username = None): self.id = CallController.id CallController.id += 1 self.global_config = global_config if remote_ip: self.uaA = UA(self.global_config, event_cb = self.recvEvent, conn_cbs = (self.aConn,), disc_cbs = (self.aDisc,), \ fail_cbs = (self.aDisc,), dead_cbs = (self.aDead,)) self.uaA.kaInterval = self.global_config['ka_ans'] self.state = CCStateIdle self.uaO = None self.routes = [] self.remote_ip = remote_ip self.source = source self.pass_headers = pass_headers self.username = username def recvEvent(self, event, ua): who = 'uaA' if ua == self.uaA else 'uaO' print who, 'received event', event, 'in state', self.state.sname if self.uaA: print 'self.uaA.state:', self.uaA.state if self.uaO: print 'self.uaO.state:', self.uaO.state if ua == self.uaA: if self.state == CCStateIdle: if not isinstance(event, CCEventTry): # Some weird event received self.uaA.recvEvent(CCEventDisconnect(rtime = event.rtime)) return self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name = event.getData() print 'auth:', auth self.cGUID = cGUID.hexForm() if not self.cld: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (1)'), rtime = event.rtime)) self.state = CCStateDead return if not body: self.uaA.recvEvent(CCEventFail((500, 'Body-less INVITE is not supported'), rtime = event.rtime)) self.state = CCStateDead return if self.global_config.has_key('allowed_pts'): try: body.parse() except: self.uaA.recvEvent(CCEventFail((400, 'Malformed SDP Body'), rtime = event.rtime)) self.state = CCStateDead return allowed_pts = self.global_config['allowed_pts'] mbody = body.content.sections[0].m_header if mbody.transport.lower() == 'rtp/avp': mbody.formats = [x for x in mbody.formats if x in allowed_pts] if not mbody.formats: self.uaA.recvEvent(CCEventFail((488, 'Not Acceptable Here'))) self.state = CCStateDead return if self.cld.startswith('nat-'): self.cld = self.cld[4:] body.content += 'a=nated:yes\r\n' event = CCEventTry((self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name), \ rtime = event.rtime, origin = event.origin) if self.global_config.has_key('static_tr_in'): self.cld = re_replace(self.global_config['static_tr_in'], self.cld) event = CCEventTry((self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name), \ rtime = event.rtime, origin = event.origin) if self.global_config.has_key('rtp_proxy_clients'): self.rtp_proxy_session = Rtp_proxy_session(self.global_config, call_id = self.cId, \ notify_socket = global_config['b2bua_socket'], \ notify_tag = quote('r %s' % str(self.id))) self.eTry = event self.state = CCStateWaitRoute if not self.global_config['auth_enable']: self.username = self.remote_ip self.rDone(((), 0)) elif not auth or not auth.username: print 'setting username to remote ip ', self.remote_ip self.username = self.remote_ip self.auth_proc = self.global_config['radius_client'].do_auth(self.remote_ip, self.cli, self.cld, self.cGUID, \ self.cId, self.remote_ip, self.rDone) else: print 'setting username auth username ', auth.username self.username = auth.username self.auth_proc = self.global_config['radius_client'].do_auth(auth.username, self.cli, self.cld, self.cGUID, self.cId, self.remote_ip, self.rDone, auth.realm, auth.nonce, auth.uri, auth.response) return if self.state == CCStateUpdatingA and isinstance(event, CCEventConnect): self.state = CCStateConnected #TODO: rad acct start if self.state == CCStateWaitRouteA and isinstance(event, CCEventConnect): # Command 'make call'. # The left phone answered. # An INVITE should be sent to the right phone. #TODO: move to a subroutine self.cli, self.cld = self.cld, self.cli body = self.uaA.rSDP #TODO: a get method()? print 'body:\n', body self.cId = SipCallId() self.caller_name = self.cli auth = None ev = CCEventTry((self.cId, self.cGUID, self.cli, self.cld, body, auth, self.cli), origin = self.cld) self.eTry = ev self.state = CCStateWaitRouteO if self.global_config['auth_enable']: self.auth_proc = self.global_config['radius_client'].do_auth(self.cli, self.cli, self.cld, self.cGUID, \ self.cId, self.remote_ip, self.rDone) else: self.rDone(((), 0)) if self.state == CCStateDead and (isinstance(event, CCEventFail) or (isinstance(event, CCEventDisconnect))) and self.routes: if isinstance(event, CCEventFail): code = event.getData()[0] else: code = None if not code or code not in self.huntstop_scodes: self.state = CCStateWaitRouteA self.uaA = self.placeAnswer(self.routes.pop(0)) if self.state not in (CCStateARComplete, CCStateConnected, CCStateDisconnecting) or not self.uaO: return self.uaO.recvEvent(event) else: if self.state == CCStateARComplete and isinstance(event, CCEventConnect) and not isinstance(self.uaO.state, UaStateConnected): if not self.global_config.has_key('rtp_proxy_clients'): self.state = CCStateUpdatingA body = self.uaO.rSDP #TODO: a get method()? event = CCEventUpdate(body) self.uaO.delayed_remote_sdp_update(event, body) else: self.state = CCStateConnected return elif (isinstance(event, CCEventFail) or isinstance(event, CCEventDisconnect)) and self.state == CCStateARComplete and \ (isinstance(self.uaA.state, UasStateTrying) or isinstance(self.uaA.state, UasStateRinging) \ or isinstance(self.uaA.state, UaStateConnected)) and self.routes: if isinstance(event, CCEventFail): code = event.getData()[0] else: code = None if not code or code not in self.huntstop_scodes: cb = self.oConnA if isinstance(self.uaA.state, UaStateConnected) else self.oConn self.uaO = self.placeOriginate(self.routes.pop(0), cb) return self.uaA.recvEvent(event) def rDone(self, results): # Check that we got necessary result from Radius if len(results) != 2 or results[1] != 0: if self.uaA and isinstance(self.uaA.state, UasStateTrying): if self.challenge: event = CCEventFail((401, 'Unauthorized')) event.extra_header = self.challenge else: event = CCEventFail((403, 'Auth Failed')) self.uaA.recvEvent(event) self.state = CCStateDead return if not self.state == CCStateWaitRouteA and not self.state == CCStateWaitRouteO: if self.global_config['acct_enable']: print 'creating self.acctA' self.acctA = RadiusAccounting(self.global_config, 'answer', \ send_start = self.global_config['start_acct_enable'], itime = self.eTry.rtime) self.acctA.setParams(self.username, self.cli, self.cld, self.cGUID, self.cId, self.remote_ip) else: self.acctA = FakeAccounting() # Check that uaA is still in a valid state, send acct stop if not self.state == CCStateWaitRouteA and not self.state == CCStateWaitRouteO and not isinstance(self.uaA.state, UasStateTrying): print 'sending acct stop A 2' self.acctA.disc(self.uaA, time(), 'caller') return cli = [x[1][4:] for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('CLI:')] if cli: self.cli = cli[0] if not self.cli: self.cli = None caller_name = [x[1][5:] for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('CNAM:')] if caller_name: self.caller_name = caller_name[0] if not self.caller_name: self.caller_name = None credit_time = [x for x in results[0] if x[0] == 'h323-credit-time'] if credit_time: global_credit_time = int(credit_time[0][1]) else: global_credit_time = None if not self.global_config.has_key('static_route'): routing = [x for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('Routing:')] if not routing: if self.uaA: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (2)'))) self.state = CCStateDead return routing = [x[1][8:].split(';') for x in routing] else: routing = [self.global_config['static_route'].split(';')] rnum = 0 self.routes = [] for route in routing: rnum += 1 if '@' in route[0]: cld, host = route[0].split('@') if not cld: # Allow CLD to be forcefully removed by sending `Routing:@host' entry, # as opposed to the Routing:host, which means that CLD should be obtained # from the incoming call leg. cld = None else: cld = self.cld host = route[0] credit_time = global_credit_time expires = None no_progress_expires = None forward_on_fail = False user = None passw = None cli = self.cli parameters = {} parameters['extra_headers'] = self.pass_headers[:] for a, v in [x.split('=') for x in route[1:]]: if a == 'credit-time': credit_time = int(v) if credit_time < 0: credit_time = None elif a == 'expires': expires = int(v) if expires < 0: expires = None elif a == 'hs_scodes': parameters['huntstop_scodes'] = tuple([int(x) for x in v.split(',') if len(x.strip()) > 0]) elif a == 'np_expires': no_progress_expires = int(v) if no_progress_expires < 0: no_progress_expires = None elif a == 'forward_on_fail': forward_on_fail = True elif a == 'auth': user, passw = v.split(':', 1) elif a == 'cli': cli = v if not cli: cli = None elif a == 'cnam': caller_name = unquote(v) if not caller_name: caller_name = None parameters['caller_name'] = caller_name elif a == 'ash': ash = SipHeader(unquote(v)) parameters['extra_headers'].append(ash) elif a == 'rtpp': parameters['rtpp'] = (int(v) != 0) elif a == 'gt': timeout, skip = v.split(',', 1) parameters['group_timeout'] = (int(timeout), rnum + int(skip)) else: parameters[a] = v if self.global_config.has_key('max_credit_time'): if credit_time == None or credit_time > self.global_config['max_credit_time']: credit_time = self.global_config['max_credit_time'] if credit_time == 0 or expires == 0: continue print 'append route, cli=' + cli + ', cld=' + cld self.routes.append((rnum, host, cld, credit_time, expires, no_progress_expires, forward_on_fail, user, \ passw, cli, parameters)) #print 'Got route:', host, cld if not self.routes: if self.uaA: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (3)'))) self.state = CCStateDead return print 'self.state:', self.state if self.state == CCStateWaitRouteA: # Make call. Got radius auth for the A phone. self.uaA = self.placeAnswer(self.routes.pop(0)) elif self.state == CCStateWaitRouteO: # Make call. Got radius auth for the O phone. self.state = CCStateARComplete print 'self.eTry.getData():', self.eTry.getData() self.uaO = self.placeOriginate(self.routes.pop(0), self.oConnA) else: # Regular call. Got radius auth for the O phone. self.state = CCStateARComplete self.uaO = self.placeOriginate(self.routes.pop(0), self.oConn) def placeAnswer(self, args): cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData() #TODO: move to a subroutine rnum, host, cld, credit_time, expires, no_progress_expires, forward_on_fail, user, passw, cli, \ parameters = args self.huntstop_scodes = parameters.get('huntstop_scodes', ()) if self.global_config.has_key('static_tr_out'): cld = re_replace(self.global_config['static_tr_out'], cld) if host == 'sip-ua': host = self.source[0] port = self.source[1] else: host = host.split(':', 1) if len(host) > 1: port = int(host[1]) else: port = SipConf.default_port host = host[0] if not forward_on_fail and self.global_config['acct_enable']: self.acctA = RadiusAccounting(self.global_config, 'answer', send_start = self.global_config['start_acct_enable']) self.acctA.setParams(parameters.get('bill-to', self.username), parameters.get('bill-cli', cli), \ parameters.get('bill-cld', cld), self.cGUID, self.cId, host, credit_time) print 'adding acct stop cb' else: self.acctA = FakeAccounting() ua = UA(self.global_config, self.recvEvent, user, passw, (host, port), credit_time, \ (self.aConnA,), (self.aDisc,), (self.aDisc,), dead_cbs = (self.aDead,), \ expire_time = expires, no_progress_time = no_progress_expires, \ extra_headers = parameters.get('extra_headers', None)) if self.rtp_proxy_session and parameters.get('rtpp', True): print 'placeAnswer() registering on sdp change callbacks' ua.on_local_sdp_change = self.rtp_proxy_session.on_callee_sdp_change ua.on_remote_sdp_change = self.rtp_proxy_session.on_caller_sdp_change body = body.getCopy() body.content += 'a=nortpproxy:yes\r\n' self.proxied = True ua.kaInterval = self.global_config['ka_ans'] #TODO: is this okay for uaA? if parameters.has_key('group_timeout'): timeout, skipto = parameters['group_timeout'] Timeout(self.group_expires, timeout, 1, skipto) ua.recvEvent(CCEventTry((cId + '-b2b_%d' % rnum, cGUID, cli, cld, body, auth, \ parameters.get('caller_name', self.caller_name)))) return ua def placeOriginate(self, args, conn_cbs): cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData() rnum, host, cld, credit_time, expires, no_progress_expires, forward_on_fail, user, passw, cli, \ parameters = args self.huntstop_scodes = parameters.get('huntstop_scodes', ()) if self.global_config.has_key('static_tr_out'): cld = re_replace(self.global_config['static_tr_out'], cld) if host == 'sip-ua': host = self.source[0] port = self.source[1] else: host = host.split(':', 1) if len(host) > 1: port = int(host[1]) else: port = SipConf.default_port host = host[0] disc_cbs = [] if not forward_on_fail and self.global_config['acct_enable']: self.acctO = RadiusAccounting(self.global_config, 'originate', send_start = self.global_config['start_acct_enable']) self.acctO.setParams(parameters.get('bill-to', self.username), parameters.get('bill-cli', cli), \ parameters.get('bill-cld', cld), self.cGUID, self.cId, host, credit_time) print 'adding acct stop cb' disc_cbs.append(self.acctO.disc) else: self.acctO = None self.acctA.credit_time = credit_time ua = UA(self.global_config, self.recvEvent, user, passw, (host, port), credit_time, \ (conn_cbs,), tuple(disc_cbs), tuple(disc_cbs), dead_cbs = (self.oDead,), \ expire_time = expires, no_progress_time = no_progress_expires, \ extra_headers = parameters.get('extra_headers', None)) if self.rtp_proxy_session and parameters.get('rtpp', True): ua.on_local_sdp_change = self.rtp_proxy_session.on_caller_sdp_change ua.on_remote_sdp_change = self.rtp_proxy_session.on_callee_sdp_change body = body.getCopy() body.content += 'a=nortpproxy:yes\r\n' self.proxied = True ua.kaInterval = self.global_config['ka_orig'] if parameters.has_key('group_timeout'): timeout, skipto = parameters['group_timeout'] Timeout(self.group_expires, timeout, 1, skipto) ua.recvEvent(CCEventTry((cId + '-b2b_%d' % rnum, cGUID, cli, cld, body, auth, \ parameters.get('caller_name', self.caller_name)))) return ua def disconnect(self, rtime = None): self.uaA.disconnect(rtime = rtime) def oConn(self, ua, rtime, origin): print 'oConn(): self.state:', self.state, ', self.uaA.state:', self.uaA.state # traceback.print_stack(file = sys.stdout) if self.acctO: self.acctO.conn(ua, rtime, origin) def oConnA(self, ua, rtime, origin): print 'oConnA(): self.state:', self.state, ', self.uaA.state:', self.uaA.state # traceback.print_stack(file = sys.stdout) # make call. # The right phone answered. # A re-INVITE should be sent to the left phone. if self.acctO: self.acctO.conn(ua, rtime, origin) if not self.global_config.has_key('rtp_proxy_clients'): self.state = CCStateUpdatingA body = self.uaO.rSDP #TODO: a get method()? event = CCEventUpdate(body) self.uaO.delayed_remote_sdp_update(event, body) else: self.state = CCStateConnected def aConn(self, ua, rtime, origin): print 'aConn(): self.state:', self.state # traceback.print_stack(file = sys.stdout) self.state = CCStateConnected self.acctA.conn(ua, rtime, origin) def aConnA(self, ua, rtime, origin): print 'aConnA(): self.state:', self.state, ', self.uaA.state:', self.uaA.state # traceback.print_stack(file = sys.stdout) # Command 'make call'. # The left phone answered. # An INVITE should be sent to the right phone. #TODO: move to a subroutine self.acctA.conn(ua, rtime, origin) def aDisc(self, ua, rtime, origin, result = 0): print 'aDisc()' if self.state == CCStateWaitRoute and self.auth_proc: self.auth_proc.cancel() self.auth_proc = None if self.uaO and self.state != CCStateDead: self.state = CCStateDisconnecting else: self.state = CCStateDead if self.acctA: print 'sending acct stop A' self.acctA.disc(ua, rtime, origin, result) print 'sent acct stop A' if self.uaO: self.uaO.recvEvent(CCEventDisconnect(rtime = rtime, origin = origin)) # self.rtp_proxy_session = None #TODO: what for? def aDead(self, ua): if (not self.uaO or isinstance(self.uaO.state, UaStateDead)): if self.global_config['cmap'].debug_mode: print 'garbadge collecting', self self.acctA = None self.acctO = None if self in self.global_config['cmap'].ccmap: self.global_config['cmap'].ccmap.remove(self) def oDead(self, ua): if ua == self.uaO and isinstance(self.uaA.state, UaStateDead): if self.global_config['cmap'].debug_mode: print 'garbadge collecting', self self.acctA = None self.acctO = None self.global_config['cmap'].ccmap.remove(self) def group_expires(self, skipto): if self.state != CCStateARComplete or len(self.routes) == 0 or self.routes[0][0] > skipto or \ (not isinstance(self.uaA.state, UasStateTrying) and not isinstance(self.uaA.state, UasStateRinging)): return # When the last group in the list has timeouted don't disconnect # the current attempt forcefully. Instead, make sure that if the # current originate call leg fails no more routes will be # processed. if skipto == self.routes[-1][0] + 1: self.routes = [] return while self.routes[0][0] != skipto: self.routes.pop(0) self.uaO.disconnect() def makeCall(self, fr, to): self.cGUID = SipCiscoGUID() self.cli = to self.cld = fr self.cId = SipCallId() self.caller_name = self.cli auth = None if self.global_config.has_key('rtp_proxy_clients'): self.rtp_proxy_session = Rtp_proxy_session(self.global_config, call_id = self.cId, \ notify_socket = global_config['b2bua_socket'], \ notify_tag = quote('r %s' % str(self.id))) ev = CCEventTry((self.cId, self.cGUID, self.cli, self.cld, MsgBody(), auth, self.cli), origin = self.cld) self.eTry = ev self.state = CCStateWaitRouteA if self.global_config['auth_enable']: self.auth_proc = self.global_config['radius_client'].do_auth(fr, self.cli, self.cld, self.cGUID, \ self.cId, self.remote_ip, self.rDone) else: self.rDone(((), 0)) return self.cGUID
class CallController(object): id = 1 global_config = None uaA = None uaO = None cId = None # 主叫 cli = None # 被叫 cld = None # 小号 _number = None _invite_event = None _media = None time_invite = None nh_addr = None def __init__(self, global_config): self.id = CallController.id CallController.id += 1 self.global_config = global_config # self.invite_session = global_config['_invite_session'] self.session = global_config['_request_session'] self.uaA = UA(self.global_config, event_cb=self.recvEvent, conn_cbs=(self.aConn, ), ring_cbs=(self.aRing, ), disc_cbs=(self.aDisc, ), fail_cbs=(self.aDisc, )) self.uaO = None def addRequest(self, task): cli, cld, number, state = task root = 'http://218.104.49.221:8801' if root.startswith('11888857'): root = 'http://218.104.49.217:8801' url = root + '/api/fs/calling?caller=%s&called=%s&number=%s&state=%s' % ( cli, cld, number, state) try: if state == 'invite': self.session.get(url, timeout=8, hooks=dict(response=self.requestCallback)) else: self.session.get(url, timeout=3, hooks=dict(response=self.requestCallback)) except Exception as e: self.createUa0({state: "0", "url": url, "error": e}) def aRing(self, ua, rtime, origin, result=0): if ua.lSDP != None and self._media == None: self._media = 1 self.addRequest((self.cli, self.cld, self._number, 'media')) def aDisc(self, ua, rtime, origin, result=0): if self._number != '0': self.addRequest((self.cli, self.cld, self._number, 'hangup')) def aConn(self, ua, rtime, origin): self.addRequest((self.cli, self.cld, self._number, 'answer')) def requestCallback(self, resp, *args, **kwargs): query = parse_qs(resp.url) param = { query['state'][0]: resp.text, "url": resp.url, "diff": round(time.time() * 1000) - self.time_invite } print('threading.currentThread =>', threading.currentThread().ident) ED2.callFromThread(self.createUa0, param) def createUa0(self, param): self.global_config['_sip_logger'].write( 'requestCallback %s==>' % (self.id), param) res = param.get('invite') if (res == None): return if res == "0": self._number = res self.uaA.recvEvent( CCEventFail((480, 'No Number'), rtime=self._invite_event.rtime)) else: self._number, _type, _gateway, _vos_ip = res.split("|") cId, cGUID, cli, cld, body, auth, caller_name = self._invite_event.getData( ) oli = self.cli if _type == "3": oli = cli + cld[8:] event = self._invite_event event.data = (SipCallId(), cGUID, oli, self._number, body, auth, caller_name) parts = _vos_ip.split(':') port = '5060' if len(parts) == 2: port = parts[1] self.uaO = UA(self.global_config, event_cb=self.recvEvent, nh_address=tuple([parts[0], int(port)])) self.uaO.recvEvent(event) def recvEvent(self, event, ua): if ua == self.uaA: if self.uaO == None and self._invite_event == None: if not isinstance(event, CCEventTry) or self._number != None: # Some weird event received self.uaA.recvEvent(CCEventDisconnect()) return self.cId, cGUID, self.cli, self.cld, body, auth, caller_name = event.getData( ) self._invite_event = event self.global_config['_sip_logger'].write( 'recvEvent %s==>%s|%s' % (self.id, self.cli, self.cld)) self.time_invite = int(round(time.time() * 1000)) self.addRequest((self.cli, self.cld, '0', 'invite')) elif self.uaO != None: self.uaO.recvEvent(event) else: self.uaA.recvEvent(event)
def placeOriginate(self, oroute): cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData() cld = oroute.cld self.huntstop_scodes = oroute.params.get('huntstop_scodes', ()) if self.global_config.has_key('static_tr_out'): cld = re_replace(self.global_config['static_tr_out'], cld) if oroute.hostport == 'sip-ua': host = self.source[0] nh_address, same_af = self.source, True else: host = oroute.hostonly nh_address, same_af = oroute.getNHAddr(self.source) if not oroute.forward_on_fail and self.global_config['acct_enable']: self.acctO = RadiusAccounting( self.global_config, 'originate', send_start=self.global_config['start_acct_enable'], lperiod=self.global_config.getdefault('alive_acct_int', None)) self.acctO.ms_precision = self.global_config.getdefault( 'precise_acct', False) self.acctO.setParams(oroute.params.get('bill-to', self.username), oroute.params.get('bill-cli', oroute.cli), \ oroute.params.get('bill-cld', cld), self.cGUID, self.cId, host) else: self.acctO = None self.acctA.credit_time = oroute.credit_time conn_handlers = [self.oConn] disc_handlers = [] if not oroute.forward_on_fail and self.global_config['acct_enable']: disc_handlers.append(self.acctO.disc) self.uaO = UA(self.global_config, self.recvEvent, oroute.user, oroute.passw, nh_address, oroute.credit_time, tuple(conn_handlers), tuple(disc_handlers), tuple(disc_handlers), dead_cbs=(self.oDead, ), expire_time=oroute.expires, no_progress_time=oroute.no_progress_expires, extra_headers=oroute.extra_headers) self.uaO.local_ua = self.global_config['_uaname'] if self.source != oroute.params.get('outbound_proxy', None): self.uaO.outbound_proxy = oroute.params.get('outbound_proxy', None) if self.rtp_proxy_session != None and oroute.params.get('rtpp', True): self.uaO.on_local_sdp_change = self.rtp_proxy_session.on_caller_sdp_change self.uaO.on_remote_sdp_change = self.rtp_proxy_session.on_callee_sdp_change self.rtp_proxy_session.caller.raddress = nh_address if body != None: body = body.getCopy() self.proxied = True self.uaO.kaInterval = self.global_config['keepalive_orig'] if oroute.params.has_key('group_timeout'): timeout, skipto = oroute.params['group_timeout'] Timeout(self.group_expires, timeout, 1, skipto) if self.global_config.getdefault('hide_call_id', False): cId = SipCallId( md5(str(cId)).hexdigest() + ('-b2b_%d' % oroute.rnum)) else: cId += '-b2b_%d' % oroute.rnum event = CCEventTry((cId, cGUID, oroute.cli, cld, body, auth, oroute.params.get('caller_name', self.caller_name))) if self.eTry.max_forwards != None: event.max_forwards = self.eTry.max_forwards - 1 if event.max_forwards <= 0: self.uaA.recvEvent(CCEventFail((483, 'Too Many Hops'))) self.state = CCStateDead return event.reason = self.eTry.reason self.uaO.recvEvent(event)
class IoTUAC(object): global_config = None ua = None cli = 'pel150_uac' cld = 'pel150_uas' authname = None authpass = None body = None rgen = None rserv = None def __init__(self, global_config): self.global_config = global_config SipTransactionManager.nworkers_udp = 1 global_config['_sip_tm'] = SipTransactionManager(global_config) self.body = MsgBody(body_txt) self.body.parse() def sess_started(self): print('started') self.ua = UA(self.global_config, event_cb = self.recvEvent, \ nh_address = tuple(self.global_config['nh_addr']), disc_cbs = (self.sess_term,)) self.ua.username = self.authname self.ua.password = self.authpass rtp_laddr = local4remote(self.global_config['nh_addr'][0]) rserv_opts = Udp_server_opts((rtp_laddr, 0), self.rtp_received) rserv_opts.nworkers = 1 self.rserv = Udp_server({}, rserv_opts) sect = self.body.content.sections[0] sect.c_header.addr = self.rserv.uopts.laddress[0] sect.m_header.port = self.rserv.uopts.laddress[1] self.body.content.o_header = SdpOrigin() event = CCEventTry((SipCallId(), SipCiscoGUID(), self.cli, self.cld, self.body, \ None, 'PEL 150-2')) self.rgen = RTPGen() self.ua.recvEvent(event) return (self.rgen.enqueue) def sess_term(self, ua, rtime, origin, result = 0): print('disconnected', origin) if origin == 'IoTUAC': return self.rgen.suspend() self.ua = UA(self.global_config, event_cb = self.recvEvent, \ nh_address = tuple(self.global_config['nh_addr']), disc_cbs = (self.sess_term,)) self.ua.username = self.authname self.ua.password = self.authpass self.body.content.o_header = SdpOrigin() event = CCEventTry((SipCallId(), SipCiscoGUID(), self.cli, self.cld, self.body, \ None, 'PEL 150-2')) self.ua.recvEvent(event) def sess_ended(self): print('ended') event = CCEventDisconnect(origin = 'IoTUAC') self.ua.recvEvent(event) self.rgen.stop() self.rserv.shutdown() self.rgen = None def rtp_received(self, data, address, udp_server, rtime): pass def recvEvent(self, event, ua): print('recvEvent', event, ua) if isinstance(event, CCEventRing) or isinstance(event, CCEventConnect) or \ isinstance(event, CCEventPreConnect): code, reason, sdp_body = event.getData() if sdp_body == None: return sdp_body.parse() sect = sdp_body.content.sections[0] rtp_target = (sect.c_header.addr, sect.m_header.port) self.rgen.start(self.rserv, rtp_target)
def register_clients(ud): # For each record in UserData list create a registrar UA for (InternalUserId, ExtDisplayName, ExtName, ExtLogin, ExtPassword, ExtDomain, ExtPort) in ud.Data: Ua = UA( global_config, event_cb = recvEvent, username = ExtLogin, password = ExtPassword, conn_cbs = (recvConnect,), disc_cbs = (recvDisconnect,), fail_cbs = (recvDisconnect,), dead_cbs = (recvDead,), nh_address = (global_config['proxy_address'], global_config['proxy_port']) ) if ExtPort == None: Ua.rTarget = SipURL(url = "sip:" + ExtName + "@" + ExtDomain) Ua.rUri = SipTo(body = "<sip:" + ExtName + "@" + ExtDomain + ">") Ua.lUri = SipFrom(body = ExtDisplayName + " <sip:" + ExtName + "@" + ExtDomain + ">") else: Ua.rTarget = SipURL(url = "sip:" + ExtName + "@" + ExtDomain + ":" + ExtPort) Ua.rUri = SipTo(body = "<sip:" + ExtName + "@" + ExtDomain + ":" + ExtPort + ">") Ua.lUri = SipFrom(body = ExtDisplayName + " <sip:" + ExtName + "@" + ExtDomain + ":" + ExtPort + ">") Ua.lUri.parse() Ua.lUri.genTag() Ua.lContact = SipContact(body = "<sip:" + InternalUserId + "@" + global_config['proxy_address'] + ">") Ua.routes = () Ua.lCSeq = 1 Ua.rCSeq = 1 Ua.cId = SipCallId() req = Ua.genRequest("REGISTER") Ua.changeState((UacStateTrying,)) global_config['_sip_tm'].regConsumer(Ua, str(Ua.cId)) Ua.tr = global_config['_sip_tm'].newTransaction(req, Ua.recvResponse)
class CallController(object): id = 1 uaA = None uaO = None state = None cId = None cld = None eTry = None routes = None remote_ip = None source = None acctA = None acctO = None global_config = None rtp_proxy_session = None huntstop_scodes = None pass_headers = None auth_proc = None proxied = False challenge = None def __init__(self, remote_ip, source, global_config, pass_headers): self.id = CallController.id CallController.id += 1 self.global_config = global_config self.uaA = UA(self.global_config, event_cb = self.recvEvent, conn_cbs = (self.aConn,), disc_cbs = (self.aDisc,), \ fail_cbs = (self.aDisc,), dead_cbs = (self.aDead,)) self.uaA.kaInterval = self.global_config['keepalive_ans'] self.state = CCStateIdle self.uaO = None self.routes = [] self.remote_ip = remote_ip self.source = source self.pass_headers = pass_headers def recvEvent(self, event, ua): if ua == self.uaA: if self.state == CCStateIdle: if not isinstance(event, CCEventTry): # Some weird event received self.uaA.recvEvent(CCEventDisconnect(rtime = event.rtime)) return self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name = event.getData() self.cGUID = cGUID.hexForm() if self.cld == None: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (1)'), rtime = event.rtime)) self.state = CCStateDead return if body == None: self.uaA.recvEvent(CCEventFail((500, 'Body-less INVITE is not supported'), rtime = event.rtime)) self.state = CCStateDead return if self.global_config.has_key('_allowed_pts'): try: body.parse() except: self.uaA.recvEvent(CCEventFail((400, 'Malformed SDP Body'), rtime = event.rtime)) self.state = CCStateDead return allowed_pts = self.global_config['_allowed_pts'] mbody = body.content.sections[0].m_header if mbody.transport.lower() == 'rtp/avp': mbody.formats = [x for x in mbody.formats if x in allowed_pts] if len(mbody.formats) == 0: self.uaA.recvEvent(CCEventFail((488, 'Not Acceptable Here'))) self.state = CCStateDead return if self.cld.startswith('nat-'): self.cld = self.cld[4:] body.content += 'a=nated:yes\r\n' event.data = (self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name) if self.global_config.has_key('static_tr_in'): self.cld = re_replace(self.global_config['static_tr_in'], self.cld) event.data = (self.cId, cGUID, self.cli, self.cld, body, auth, self.caller_name) if self.global_config.has_key('_rtp_proxy_clients'): self.rtp_proxy_session = Rtp_proxy_session(self.global_config, call_id = self.cId, \ notify_socket = global_config['b2bua_socket'], \ notify_tag = quote('r %s' % str(self.id))) self.rtp_proxy_session.callee_raddress = (self.remote_ip, 5060) self.eTry = event self.state = CCStateWaitRoute if not self.global_config['auth_enable']: self.username = self.remote_ip self.rDone(((), 0)) elif auth == None or auth.username == None or len(auth.username) == 0: self.username = self.remote_ip self.auth_proc = self.global_config['_radius_client'].do_auth(self.remote_ip, self.cli, self.cld, self.cGUID, \ self.cId, self.remote_ip, self.rDone) else: self.username = auth.username self.auth_proc = self.global_config['_radius_client'].do_auth(auth.username, self.cli, self.cld, self.cGUID, self.cId, self.remote_ip, self.rDone, auth.realm, auth.nonce, auth.uri, auth.response) return if self.state not in (CCStateARComplete, CCStateConnected, CCStateDisconnecting) or self.uaO == None: return self.uaO.recvEvent(event) else: if (isinstance(event, CCEventFail) or isinstance(event, CCEventDisconnect)) and self.state == CCStateARComplete and \ (isinstance(self.uaA.state, UasStateTrying) or isinstance(self.uaA.state, UasStateRinging)) and len(self.routes) > 0: if isinstance(event, CCEventFail): code = event.getData()[0] else: code = None if code == None or code not in self.huntstop_scodes: self.placeOriginate(self.routes.pop(0)) return self.uaA.recvEvent(event) def rDone(self, results): # Check that we got necessary result from Radius if len(results) != 2 or results[1] != 0: if isinstance(self.uaA.state, UasStateTrying): if self.challenge != None: event = CCEventFail((401, 'Unauthorized')) event.extra_header = self.challenge else: event = CCEventFail((403, 'Auth Failed')) self.uaA.recvEvent(event) self.state = CCStateDead return if self.global_config['acct_enable']: self.acctA = RadiusAccounting(self.global_config, 'answer', \ send_start = self.global_config['start_acct_enable'], lperiod = \ self.global_config.getdefault('alive_acct_int', None)) self.acctA.ms_precision = self.global_config.getdefault('precise_acct', False) self.acctA.setParams(self.username, self.cli, self.cld, self.cGUID, self.cId, self.remote_ip) else: self.acctA = FakeAccounting() # Check that uaA is still in a valid state, send acct stop if not isinstance(self.uaA.state, UasStateTrying): self.acctA.disc(self.uaA, time(), 'caller') return cli = [x[1][4:] for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('CLI:')] if len(cli) > 0: self.cli = cli[0] if len(self.cli) == 0: self.cli = None caller_name = [x[1][5:] for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('CNAM:')] if len(caller_name) > 0: self.caller_name = caller_name[0] if len(self.caller_name) == 0: self.caller_name = None credit_time = [x for x in results[0] if x[0] == 'h323-credit-time'] if len(credit_time) > 0: global_credit_time = int(credit_time[0][1]) else: global_credit_time = None if not self.global_config.has_key('static_route'): routing = [x for x in results[0] if x[0] == 'h323-ivr-in' and x[1].startswith('Routing:')] if len(routing) == 0: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (2)'))) self.state = CCStateDead return routing = [x[1][8:].split(';') for x in routing] else: routing = [self.global_config['static_route'].split(';')] rnum = 0 for route in routing: rnum += 1 if route[0].find('@') != -1: cld, host = route[0].split('@') if len(cld) == 0: # Allow CLD to be forcefully removed by sending `Routing:@host' entry, # as opposed to the Routing:host, which means that CLD should be obtained # from the incoming call leg. cld = None else: cld = self.cld host = route[0] credit_time = global_credit_time expires = None no_progress_expires = None forward_on_fail = False user = None passw = None cli = self.cli parameters = {} parameters['extra_headers'] = self.pass_headers[:] for a, v in [x.split('=') for x in route[1:]]: if a == 'credit-time': credit_time = int(v) if credit_time < 0: credit_time = None elif a == 'expires': expires = int(v) if expires < 0: expires = None elif a == 'hs_scodes': parameters['huntstop_scodes'] = tuple([int(x) for x in v.split(',') if len(x.strip()) > 0]) elif a == 'np_expires': no_progress_expires = int(v) if no_progress_expires < 0: no_progress_expires = None elif a == 'forward_on_fail': forward_on_fail = True elif a == 'auth': user, passw = v.split(':', 1) elif a == 'cli': cli = v if len(cli) == 0: cli = None elif a == 'cnam': caller_name = unquote(v) if len(caller_name) == 0: caller_name = None parameters['caller_name'] = caller_name elif a == 'ash': ash = SipHeader(unquote(v)) parameters['extra_headers'].append(ash) elif a == 'rtpp': parameters['rtpp'] = (int(v) != 0) elif a == 'gt': timeout, skip = v.split(',', 1) parameters['group_timeout'] = (int(timeout), rnum + int(skip)) else: parameters[a] = v if self.global_config.has_key('max_credit_time'): if credit_time == None or credit_time > self.global_config['max_credit_time']: credit_time = self.global_config['max_credit_time'] if credit_time == 0 or expires == 0: continue self.routes.append((rnum, host, cld, credit_time, expires, no_progress_expires, forward_on_fail, user, \ passw, cli, parameters)) #print 'Got route:', host, cld if len(self.routes) == 0: self.uaA.recvEvent(CCEventFail((500, 'Internal Server Error (3)'))) self.state = CCStateDead return self.state = CCStateARComplete self.placeOriginate(self.routes.pop(0)) def placeOriginate(self, args): cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData() rnum, host, cld, credit_time, expires, no_progress_expires, forward_on_fail, user, passw, cli, \ parameters = args self.huntstop_scodes = parameters.get('huntstop_scodes', ()) if self.global_config.has_key('static_tr_out'): cld = re_replace(self.global_config['static_tr_out'], cld) if host == 'sip-ua': host = self.source[0] port = self.source[1] else: if host.startswith('['): # IPv6 host = host.split(']', 1) port = host[1].split(':', 1) host = host[0] + ']' if len(port) > 1: port = int(port[1]) else: port = SipConf.default_port else: # IPv4 host = host.split(':', 1) if len(host) > 1: port = int(host[1]) else: port = SipConf.default_port host = host[0] if not forward_on_fail and self.global_config['acct_enable']: self.acctO = RadiusAccounting(self.global_config, 'originate', \ send_start = self.global_config['start_acct_enable'], lperiod = \ self.global_config.getdefault('alive_acct_int', None)) self.acctO.ms_precision = self.global_config.getdefault('precise_acct', False) self.acctO.setParams(parameters.get('bill-to', self.username), parameters.get('bill-cli', cli), \ parameters.get('bill-cld', cld), self.cGUID, self.cId, host) else: self.acctO = None self.acctA.credit_time = credit_time conn_handlers = [self.oConn] disc_handlers = [] if not forward_on_fail and self.global_config['acct_enable']: disc_handlers.append(self.acctO.disc) self.uaO = UA(self.global_config, self.recvEvent, user, passw, (host, port), credit_time, tuple(conn_handlers), \ tuple(disc_handlers), tuple(disc_handlers), dead_cbs = (self.oDead,), expire_time = expires, \ no_progress_time = no_progress_expires, extra_headers = parameters.get('extra_headers', None)) if self.rtp_proxy_session != None and parameters.get('rtpp', True): self.uaO.on_local_sdp_change = self.rtp_proxy_session.on_caller_sdp_change self.uaO.on_remote_sdp_change = self.rtp_proxy_session.on_callee_sdp_change self.rtp_proxy_session.caller_raddress = (host, port) body = body.getCopy() body.content += 'a=nortpproxy:yes\r\n' self.proxied = True self.uaO.kaInterval = self.global_config['keepalive_orig'] if parameters.has_key('group_timeout'): timeout, skipto = parameters['group_timeout'] Timeout(self.group_expires, timeout, 1, skipto) if self.global_config.getdefault('hide_call_id', False): cId = SipCallId(md5(str(cId)).hexdigest() + ('-b2b_%d' % rnum)) else: cId += '-b2b_%d' % rnum event = CCEventTry((cId, cGUID, cli, cld, body, auth, \ parameters.get('caller_name', self.caller_name))) event.reason = self.eTry.reason self.uaO.recvEvent(event) def disconnect(self, rtime = None): self.uaA.disconnect(rtime = rtime) def oConn(self, ua, rtime, origin): if self.acctO != None: self.acctO.conn(ua, rtime, origin) def aConn(self, ua, rtime, origin): self.state = CCStateConnected self.acctA.conn(ua, rtime, origin) def aDisc(self, ua, rtime, origin, result = 0): if self.state == CCStateWaitRoute and self.auth_proc != None: self.auth_proc.cancel() self.auth_proc = None if self.uaO != None and self.state != CCStateDead: self.state = CCStateDisconnecting else: self.state = CCStateDead if self.acctA != None: self.acctA.disc(ua, rtime, origin, result) self.rtp_proxy_session = None def aDead(self, ua): if (self.uaO == None or isinstance(self.uaO.state, UaStateDead)): if self.global_config['_cmap'].debug_mode: print 'garbadge collecting', self self.acctA = None self.acctO = None self.global_config['_cmap'].ccmap.remove(self) def oDead(self, ua): if ua == self.uaO and isinstance(self.uaA.state, UaStateDead): if self.global_config['_cmap'].debug_mode: print 'garbadge collecting', self self.acctA = None self.acctO = None self.global_config['_cmap'].ccmap.remove(self) def group_expires(self, skipto): if self.state != CCStateARComplete or len(self.routes) == 0 or self.routes[0][0] > skipto or \ (not isinstance(self.uaA.state, UasStateTrying) and not isinstance(self.uaA.state, UasStateRinging)): return # When the last group in the list has timeouted don't disconnect # the current attempt forcefully. Instead, make sure that if the # current originate call leg fails no more routes will be # processed. if skipto == self.routes[-1][0] + 1: self.routes = [] return while self.routes[0][0] != skipto: self.routes.pop(0) self.uaO.disconnect()
def __init__(self, *args, **kwargs): origin = SdpOrigin() origin.address = '192.0.2.1' # 192.0.2.0/24 (TEST-NET-1) self.sdp_session = SdpSession(origin) UA.__init__(self, *args, **kwargs)