def connect(self, ua): if self.connect_done or self.disconnect_done: return event = CCEventFail((503, 'Post-early-session Failure'), \ origin = 'switch') ua.recvEvent(event) self.connect_done = True
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'] self.uaO.no_reply_time = oroute.no_reply_expires 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 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 connect(self, ua): if self.connect_done or self.connect_done: return event = CCEventFail((501, 'Post-ring Failure'), \ origin = 'switch') ua.recvEvent(event) self.connect_done = True
def ring(self, ua): if self.connect_done or self.disconnect_done: return event = CCEventFail((502, 'Pre-ring Failure'), \ origin = 'switch') ua.recvEvent(event) self.ring_done = True self.connect_done = True
def recvEvent(self, event, ua): if not isinstance(event, CCEventUpdate): return (b_test_reinvite.recvEvent(self, event, ua)) if self.debug_lvl > 0: print('Bob(%s): Incoming event: %s, generating failure' % (self.cli, str(event))) event = CCEventFail((408, 'Nobody is Home')) ua.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 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 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 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 recvResponse(self, resp, tr): body = resp.getBody() code, reason = resp.getSCode() scode = (code, reason, body) self.ua.last_scode = code if self.ua.no_reply_timer != None: self.ua.no_reply_timer.cancel() self.ua.no_reply_timer = None if code == 100 and self.ua.no_progress_time != None: self.ua.no_progress_timer = TimeoutAbsMono( self.ua.no_progress_expires, self.ua.no_progress_time) elif code < 200 and self.ua.expire_time != None: self.ua.expire_timer = TimeoutAbsMono(self.ua.expires, self.ua.expire_time) if code == 100: if self.ua.p100_ts == None: self.ua.p100_ts = resp.rtime self.ua.equeue.append( CCEventRing(scode, rtime=resp.rtime, origin=self.ua.origin)) return None if self.ua.no_progress_timer != None: self.ua.no_progress_timer.cancel() self.ua.no_progress_timer = None if code < 200 and self.ua.expire_time != None: self.ua.expire_timer = TimeoutAbsMono(self.ua.expires, self.ua.expire_time) if code < 200: event = CCEventRing(scode, rtime=resp.rtime, origin=self.ua.origin) if body != None: if self.ua.on_remote_sdp_change != None: self.ua.on_remote_sdp_change( body, lambda x: self.ua.delayed_remote_sdp_update(event, x)) self.ua.p1xx_ts = resp.rtime return (UacStateRinging, self.ua.ring_cbs, resp.rtime, self.ua.origin, code) else: self.ua.rSDP = body.getCopy() else: self.ua.rSDP = None self.ua.equeue.append(event) self.ua.p1xx_ts = resp.rtime return (UacStateRinging, self.ua.ring_cbs, resp.rtime, self.ua.origin, code) if self.ua.expire_timer != None: self.ua.expire_timer.cancel() self.ua.expire_timer = None if code >= 200 and code < 300: if resp.countHFs('contact') > 0: self.ua.rTarget = resp.getHFBody('contact').getUrl().getCopy() self.ua.routes = [ x.getCopy() for x in resp.getHFBodys('record-route') ] self.ua.routes.reverse() if len(self.ua.routes) > 0: if not self.ua.routes[0].getUrl().lr: self.ua.routes.append( SipRoute(address=SipAddress(url=self.ua.rTarget))) self.ua.rTarget = self.ua.routes.pop(0).getUrl() self.ua.rAddr = self.ua.rTarget.getAddr() elif self.ua.outbound_proxy != None: self.ua.routes.append( SipRoute(address=SipAddress(url=self.ua.rTarget))) self.ua.rTarget = self.ua.routes[0].getUrl().getCopy() self.ua.rTarget.lr = False self.ua.rTarget.other = tuple() self.ua.rTarget.headers = tuple() else: self.ua.rAddr = self.ua.routes[0].getAddr() else: self.ua.rAddr = self.ua.rTarget.getAddr() tag = resp.getHFBody('to').getTag() if tag == None: print('tag-less 200 OK, disconnecting') scode = (502, 'Bad Gateway') self.ua.equeue.append( CCEventFail(scode, rtime=resp.rtime, origin=self.ua.origin)) # Generate and send BYE if resp.countHFs('contact') > 0: self.ua.rTarget = resp.getHFBody( 'contact').getUrl().getCopy() self.ua.routes = [ x.getCopy() for x in resp.getHFBodys('record-route') ] self.ua.routes.reverse() if len(self.ua.routes) > 0: if not self.ua.routes[0].getUrl().lr: self.ua.routes.append( SipRoute(address=SipAddress(url=self.ua.rTarget))) self.ua.rTarget = self.ua.routes.pop(0).getUrl() self.ua.rAddr = self.ua.rTarget.getAddr() elif self.ua.outbound_proxy != None: self.ua.routes.append( SipRoute(address=SipAddress(url=self.ua.rTarget))) self.ua.rTarget = self.ua.routes[0].getUrl().getCopy() self.ua.rTarget.lr = False self.ua.rTarget.other = tuple() self.ua.rTarget.headers = tuple() else: self.ua.rAddr = self.ua.routes[0].getAddr() else: self.ua.rAddr = self.ua.rTarget.getAddr() req = self.ua.genRequest('BYE') self.ua.lCSeq += 1 self.ua.global_config['_sip_tm'].newTransaction(req, \ laddress = self.ua.source_address, compact = self.ua.compact_sip) return (UaStateFailed, self.ua.fail_cbs, resp.rtime, self.ua.origin, scode[0]) self.ua.rUri.setTag(tag) if not self.ua.late_media or body == None: self.ua.late_media = False event = CCEventConnect(scode, rtime=resp.rtime, origin=self.ua.origin) self.ua.startCreditTimer(resp.rtime) self.ua.connect_ts = resp.rtime rval = (UaStateConnected, self.ua.conn_cbs, resp.rtime, self.ua.origin) else: event = CCEventPreConnect(scode, rtime=resp.rtime, origin=self.ua.origin) tr.uack = True self.ua.pending_tr = tr rval = (UaStateConnected, ) if body != None: if self.ua.on_remote_sdp_change != None: self.ua.on_remote_sdp_change( body, lambda x: self.ua.delayed_remote_sdp_update(event, x)) return rval else: self.ua.rSDP = body.getCopy() else: self.ua.rSDP = None self.ua.equeue.append(event) return rval if code in (301, 302) and resp.countHFs('contact') > 0: scode = (code, reason, body, (resp.getHFBody('contact').getUri().getCopy(), )) self.ua.equeue.append( CCEventRedirect(scode, rtime=resp.rtime, origin=self.ua.origin)) elif code == 300 and resp.countHFs('contact') > 0: redirects = tuple(x.getUri().getCopy() for x in resp.getHFBodys('contact')) scode = (code, reason, body, redirects) self.ua.equeue.append( CCEventRedirect(scode, rtime=resp.rtime, origin=self.ua.origin)) else: event = CCEventFail(scode, rtime=resp.rtime, origin=self.ua.origin) if self.ua.pass_auth: if code == 401 and resp.countHFs('www-authenticate') != 0: event.challenge = resp.getHF('www-authenticate').getCopy() elif code == 407 and resp.countHFs('proxy-authenticate') != 0: event.challenge = resp.getHF( 'proxy-authenticate').getCopy() if resp.countHFs('reason') != 0: event.reason = resp.getHFBody('reason').getCopy() self.ua.equeue.append(event) self.ua.disconnect_ts = resp.rtime return (UaStateFailed, self.ua.fail_cbs, resp.rtime, self.ua.origin, code)
def recvEvent(self, event): if isinstance(event, CCEventDisconnect) or isinstance( event, CCEventFail) or isinstance(event, CCEventRedirect): #print 'event', event, 'received in the Connected state sending BYE' redirect = None if isinstance(event, CCEventDisconnect): redirect = event.getData() elif isinstance(event, CCEventRedirect): redirects = event.getData() if redirects != None: redirect = redirects[0] if redirect != None and self.ua.useRefer: req = self.ua.genRequest('REFER', reason=event.reason) self.ua.lCSeq += 1 also = SipReferTo(address=redirect) req.appendHeader(SipHeader(name='refer-to', body=also)) rby = SipReferredBy(address=SipAddress( url=self.ua.lUri.getUrl())) req.appendHeader(SipHeader(name='referred-by', body=rby)) self.ua.global_config['_sip_tm'].newTransaction(req, self.rComplete, \ laddress = self.ua.source_address, compact = self.ua.compact_sip) else: req = self.ua.genRequest('BYE', reason=event.reason) self.ua.lCSeq += 1 if redirect != None: also = SipAlso(address=redirect) req.appendHeader(SipHeader(name='also', body=also)) self.ua.global_config['_sip_tm'].newTransaction(req, \ laddress = self.ua.source_address, compact = self.ua.compact_sip) self.ua.cancelCreditTimer() self.ua.disconnect_ts = event.rtime return (UaStateDisconnected, self.ua.disc_cbs, event.rtime, event.origin) if isinstance(event, CCEventUpdate): body = event.getData() if str(self.ua.lSDP) == str(body): if self.ua.rSDP != None: self.ua.equeue.append(CCEventConnect((200, 'OK', self.ua.rSDP.getCopy()), \ rtime = event.rtime, origin = event.origin)) else: self.ua.equeue.append(CCEventConnect((200, 'OK', None), rtime = event.rtime, \ origin = event.origin)) return None if body != None and self.ua.on_local_sdp_change != None and body.needs_update: try: self.ua.on_local_sdp_change( body, lambda x: self.ua.recvEvent(event), en_excpt=True) except Exception as e: event = CCEventFail((400, 'Malformed SDP Body'), rtime=event.rtime) event.setWarning(str(e)) self.ua.equeue.append(event) return None if event.max_forwards != None: if event.max_forwards <= 0: self.ua.equeue.append( CCEventFail((483, 'Too Many Hops'), rtime=event.rtime)) return None max_forwards_hf = SipMaxForwards(number=event.max_forwards - 1) else: max_forwards_hf = None req = self.ua.genRequest('INVITE', body, reason = event.reason, \ max_forwards = max_forwards_hf) self.ua.lCSeq += 1 self.ua.lSDP = body self.ua.tr = self.ua.global_config['_sip_tm'].newTransaction(req, self.ua.recvResponse, \ laddress = self.ua.source_address, cb_ifver = 2, compact = self.ua.compact_sip) return (UacStateUpdating, ) if isinstance(event, CCEventInfo): body = event.getData() req = self.ua.genRequest('INFO', reason=event.reason) req.setBody(body) self.ua.lCSeq += 1 self.ua.global_config['_sip_tm'].newTransaction(req, None, \ laddress = self.ua.source_address, compact = self.ua.compact_sip) return None if self.ua.pending_tr != None and isinstance(event, CCEventConnect): if self.ua.expire_timer != None: self.ua.expire_timer.cancel() self.ua.expire_timer = None code, reason, body = event.getData() if body != None and self.ua.on_local_sdp_change != None and body.needs_update: self.ua.on_local_sdp_change(body, lambda x: self.ua.recvEvent(event)) return None self.ua.startCreditTimer(event.rtime) self.ua.connect_ts = event.rtime self.ua.lSDP = body self.ua.pending_tr.ack.setBody(body) self.ua.global_config['_sip_tm'].sendACK(self.ua.pending_tr) self.ua.pending_tr = None for callback in self.ua.conn_cbs: callback(self.ua, event.rtime, self.ua.origin) return None #print 'wrong event %s in the Connected state' % event return None
def recvResponse(self, resp, tr): body = resp.getBody() code, reason = resp.getSCode() scode = (code, reason, body) if code < 200: self.ua.equeue.append( CCEventRing(scode, rtime=resp.rtime, origin=self.ua.origin)) return None if code >= 200 and code < 300: event = CCEventConnect(scode, rtime=resp.rtime, origin=self.ua.origin) if body != None: if self.ua.on_remote_sdp_change != None: cb_func = lambda x: self.ua.delayed_remote_sdp_update( event, x) try: self.ua.on_remote_sdp_change(body, cb_func, en_excpt=True) except Exception as e: event = CCEventFail((502, 'Bad Gateway'), rtime=event.rtime) event.setWarning('Malformed SDP Body received from ' \ 'downstream: "%s"' % str(e)) return self.updateFailed(event) return (UaStateConnected, ) else: self.ua.rSDP = body.getCopy() else: self.ua.rSDP = None self.ua.equeue.append(event) return (UaStateConnected, ) if code in (301, 302) and resp.countHFs('contact') > 0: scode = (code, reason, body, (resp.getHFBody('contact').getUri().getCopy(), )) event = CCEventRedirect(scode, rtime=resp.rtime, origin=self.ua.origin) elif code == 300 and resp.countHFs('contact') > 0: redirects = tuple(x.getUri().getCopy() for x in resp.getHFBodys('contact')) scode = (code, reason, body, redirects) event = CCEventRedirect(scode, rtime=resp.rtime, origin=self.ua.origin) else: event = CCEventFail(scode, rtime=resp.rtime, origin=self.ua.origin) try: event.reason = resp.getHFBody('reason') except: pass if code in (408, 481): # If the response for a request within a dialog is a 481 # (Call/Transaction Does Not Exist) or a 408 (Request Timeout), the # UAC SHOULD terminate the dialog. A UAC SHOULD also terminate a # dialog if no response at all is received for the request (the # client transaction would inform the TU about the timeout.) return self.updateFailed(event) self.ua.equeue.append(event) return (UaStateConnected, )