def __init__(self, buf=None): self.headers = [] if buf == None: return # Locate a body self.__mbody = None for bdel in ('\r\n\r\n', '\r\r', '\n\n'): boff = buf.find(bdel) if boff != -1: self.__mbody = buf[boff + len(bdel):] buf = buf[:boff] if len(self.__mbody) == 0: self.__mbody = None break # Split message into lines and put aside start line lines = buf.splitlines() self.setSL(lines[0]) i = 2 while i < len(lines): if lines[i][0] in (' ', '\t'): lines[i - 1] += ' ' + lines[i].strip() del lines[i] else: i += 1 # Parse headers self.__content_type = None self.__content_length = None header_names = [] for line in lines[1:]: try: header = SipHeader(line, fixname=True) if header.name == 'content-type': self.__content_type = header elif header.name == 'content-length': self.__content_length = header else: self.headers.append(header) header_names.append(header.name) except ESipHeaderCSV as einst: for body in einst.bodys: header = SipHeader(name=einst.name, bodys=body) if header.name == 'content-type': self.__content_type = header elif header.name == 'content-length': self.__content_length = header else: self.headers.append(header) header_names.append(header.name) except ESipHeaderIgnore: continue if 'via' not in header_names: raise Exception('Via HF is missed') if 'to' not in header_names: raise Exception('To HF is missed') if 'from' not in header_names: raise Exception('From HF is missed') if 'cseq' not in header_names: raise Exception('CSeq HF is missed')
def gotreply(self, resp): if self.dead: return if resp.scode < 200: return if resp.scode >= 200 and resp.scode < 300 and resp.reason != 'Auth Failed': contact = None if resp.countHFs('contact') > 0: contact = resp.getHFBody('contact') if contact != None and 'expires' in contact.address.params: tout = int(contact.address.params['expires']) elif resp.countHFs('expires') > 0: tout = resp.getHFBody('expires').getNum() else: tout = 180 timer = Timeout(self.doregister, tout) if self.rok_cb != None: self.rok_cb(timer.etime.realt, contact, self.cb_arg) self.atries = 0 return if resp.scode == 401 and resp.countHFs('www-authenticate') != 0 and \ self.user != None and self.passw != None and self.atries < 3: challenge = resp.getHFBody('www-authenticate') auth = SipAuthorization(realm=challenge.getRealm(), nonce=challenge.getNonce(), method='REGISTER', uri=str(self.rmsg.ruri), username=self.user, password=self.passw) for authorization in self.rmsg.getHFs('authorization'): self.rmsg.removeHeader(authorization) self.rmsg.appendHeader(SipHeader(name='authorization', body=auth)) self.atries += 1 self.doregister() return if resp.scode == 407 and resp.countHFs('proxy-authenticate') != 0 and \ self.user != None and self.passw != None and self.atries < 3: challenge = resp.getHFBody('proxy-authenticate') auth = SipProxyAuthorization(realm=challenge.getRealm(), nonce=challenge.getNonce(), method='REGISTER', uri=str(self.rmsg.ruri), username=self.user, password=self.passw) for authorization in self.rmsg.getHFs('proxy-authorization'): self.rmsg.removeHeader(authorization) self.rmsg.appendHeader( SipHeader(name='proxy-authorization', body=auth)) self.atries += 1 self.doregister() return if self.rfail_cb != None: self.rfail_cb(resp.getSL(), self.cb_arg) Timeout(self.doregister, 60) self.atries = 0
def recvRequest(self, req): if req.getHFBody('to').getTag() != None: # Request within dialog, but no such dialog return (req.genResponse(481, 'Call Leg/Transaction Does Not Exist'), None, None) if req.getMethod() == 'INVITE': # New dialog if req.countHFs('via') > 1: via = req.getHFBody('via', 1) else: via = req.getHFBody('via', 0) remote_ip = via.getTAddr()[0] source = req.getSource() # First check if request comes from IP that # we want to accept our traffic from if '_accept_ips' in self.global_config and \ not source[0] in self.global_config['_accept_ips']: resp = req.genResponse(403, 'Forbidden') return (resp, None, None) challenge = None if self.global_config['auth_enable']: # Prepare challenge if no authorization header is present. # Depending on configuration, we might try remote ip auth # first and then challenge it or challenge immediately. if self.global_config['digest_auth'] and \ req.countHFs('authorization') == 0: challenge = SipHeader(name='www-authenticate') challenge.getBody().realm = req.getRURI().host # Send challenge immediately if digest is the # only method of authenticating if challenge != None and self.global_config.getdefault( 'digest_auth_only', False): resp = req.genResponse(401, 'Unauthorized') resp.appendHeader(challenge) return (resp, None, None) pass_headers = [] for header in self.global_config['_pass_headers']: hfs = req.getHFs(header) if len(hfs) > 0: pass_headers.extend(hfs) cc = CallController(remote_ip, source, self.global_config, pass_headers) cc.challenge = challenge rval = cc.uaA.recvRequest(req) self.ccmap.append(cc) return rval if req.getMethod() in ('NOTIFY', 'PING'): # Whynot? return (req.genResponse(200, 'OK'), None, None) return (req.genResponse(501, 'Not Implemented'), None, None)
def recvRequest(self, req): if req.getHFBody('to').getTag() != None: # Request within dialog, but no such dialog return (req.genResponse(481, 'Call Leg/Transaction Does Not Exist'), None, None) if req.getMethod() == 'INVITE': # New dialog if req.countHFs('via') > 1: via = req.getHFBody('via', 1) else: via = req.getHFBody('via', 0) remote_ip = via.getTAddr()[0] source = req.getSource() # First check if request comes from IP that # we want to accept our traffic from if self.global_config.has_key('_accept_ips') and \ not source[0] in self.global_config['_accept_ips']: resp = req.genResponse(403, 'Forbidden') return (resp, None, None) challenge = None if self.global_config['auth_enable']: # Prepare challenge if no authorization header is present. # Depending on configuration, we might try remote ip auth # first and then challenge it or challenge immediately. if self.global_config['digest_auth'] and \ req.countHFs('authorization') == 0: challenge = SipHeader(name = 'www-authenticate') challenge.getBody().realm = req.getRURI().host # Send challenge immediately if digest is the # only method of authenticating if challenge != None and self.global_config.getdefault('digest_auth_only', False): resp = req.genResponse(401, 'Unauthorized') resp.appendHeader(challenge) return (resp, None, None) pass_headers = [] for header in self.global_config['_pass_headers']: hfs = req.getHFs(header) if len(hfs) > 0: pass_headers.extend(hfs) cc = CallController(remote_ip, source, self.global_config, pass_headers) cc.challenge = challenge rval = cc.uaA.recvRequest(req) self.ccmap.append(cc) return rval if req.getMethod() in ('NOTIFY', 'PING'): # Whynot? return (req.genResponse(200, 'OK'), None, None) return (req.genResponse(501, 'Not Implemented'), None, None)
def sendUasResponse(self, scode, reason, body = None, contacts = None, \ reason_rfc3326 = None, extra_headers = None, ack_wait = False): uasResp = self.uasResp.getCopy() uasResp.setSCode(scode, reason) uasResp.setBody(body) if contacts != None: for contact in contacts: uasResp.appendHeader(SipHeader(name='contact', body=contact)) if reason_rfc3326 != None: uasResp.appendHeader(SipHeader(body=reason_rfc3326)) if extra_headers != None: uasResp.appendHeaders(extra_headers) if ack_wait: ack_cb = self.recvACK else: ack_cb = None self.global_config['_sip_tm'].sendResponse(uasResp, ack_cb = ack_cb, \ lossemul = self.uas_lossemul)
def cancelTransaction(self, t, reason=None): # If we got at least one provisional reply then (state == RINGING) # then start CANCEL transaction, otherwise deffer it if t.state != RINGING: t.cancelPending = True else: if reason != None: t.cancel.appendHeader(SipHeader(body=reason)) self.newTransaction(t.cancel, userv=t.userv)
def recvRequest(self, req): via0 = SipVia() via0.genBranch() via1 = req.getHF('via') req.insertHeaderBefore(via1, SipHeader(name='via', body=via0)) req.setTarget(self.destination) print(req) self.global_config['_sip_tm'].newTransaction(req, self.recvResponse) return (None, None, None)
def genRequest(self, method, body = None, nonce = None, realm = None, SipXXXAuthorization = SipAuthorization, \ reason = None, max_forwards = None): if self.outbound_proxy != None: target = self.outbound_proxy else: target = self.rAddr if max_forwards != None: max_forwards_hf = SipMaxForwards(number=max_forwards) else: max_forwards_hf = None req = SipRequest(method=method, ruri=self.rTarget, to=self.rUri, fr0m=self.lUri, cseq=self.lCSeq, callid=self.cId, contact=self.lContact, routes=self.routes, target=target, cguid=self.cGUID, user_agent=self.local_ua, maxforwards=max_forwards_hf) if nonce != None and realm != None and self.username != None and self.password != None: auth = SipXXXAuthorization(realm=realm, nonce=nonce, method=method, uri=str(self.rTarget), username=self.username, password=self.password) req.appendHeader(SipHeader(body=auth)) if body != None: req.setBody(body) if self.extra_headers != None: req.appendHeaders(self.extra_headers) if reason != None: req.appendHeader(SipHeader(body=reason)) self.reqs[self.lCSeq] = req return req
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 __init__(self, sroute = None, cself = None): if cself != None: self.rnum = cself.rnum self.addrinfo = cself.addrinfo self.cld = cself.cld self.cld_set = cself.cld_set self.hostport = cself.hostport self.hostonly = cself.hostonly self.credit_time = cself.credit_time self.crt_set = cself.crt_set self.expires = cself.expires self.no_progress_expires = cself.no_progress_expires self.no_reply_expires = cself.no_reply_expires self.forward_on_fail = cself.forward_on_fail self.user = cself.user self.passw = cself.passw self.cli = cself.cli self.cli_set = cself.cli_set self.params = dict(cself.params) self.ainfo = cself.ainfo if cself.extra_headers != None: self.extra_headers = tuple([x.getCopy() for x in cself.extra_headers]) return route = sroute.split(';') if route[0].find('@') != -1: self.cld, self.hostport = route[0].split('@', 1) if len(self.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. self.cld = None self.cld_set = True else: self.hostport = route[0] if not self.hostport.startswith('['): hostport = self.hostport.split(':', 1) af = 0 self.hostonly = hostport[0] else: hostport = self.hostport[1:].split(']', 1) if len(hostport) > 1: if len(hostport[1]) == 0: del hostport[1] else: hostport[1] = hostport[1][1:] af = AF_INET6 self.hostonly = '[%s]' % hostport[0] if len(hostport) == 1: port = SipConf.default_port else: port = int(hostport[1]) self.ainfo = getaddrinfo(hostport[0], port, af, SOCK_STREAM) self.params = {} extra_headers = [] for a, v in [x.split('=', 1) for x in route[1:]]: if a == 'credit-time': self.credit_time = int(v) if self.credit_time < 0: self.credit_time = None self.crt_set = True elif a == 'expires': self.expires = int(v) if self.expires < 0: self.expires = None elif a == 'hs_scodes': self.params['huntstop_scodes'] = tuple([int(x) for x in v.split(',') if len(x.strip()) > 0]) elif a == 'np_expires': self.no_progress_expires = int(v) if self.no_progress_expires < 0: self.no_progress_expires = None elif a == 'nr_expires': self.no_reply_expires = int(v) if self.no_reply_expires < 0: self.no_reply_expires = None elif a == 'forward_on_fail': self.forward_on_fail = True elif a == 'auth': self.user, self.passw = v.split(':', 1) elif a == 'cli': self.cli = v if len(self.cli) == 0: self.cli = None self.cli_set = True elif a == 'cnam': caller_name = unquote(v) if len(caller_name) == 0: caller_name = None self.params['caller_name'] = caller_name elif a == 'ash': ash = SipHeader(unquote(v)) extra_headers.append(ash) elif a == 'rtpp': self.params['rtpp'] = (int(v) != 0) elif a == 'op': host_port = v.split(':', 1) if len(host_port) == 1: self.params['outbound_proxy'] = (v, 5060) else: self.params['outbound_proxy'] = (host_port[0], int(host_port[1])) else: self.params[a] = v if len(extra_headers) > 0: self.extra_headers = tuple(extra_headers)
def setWarning(self, eistr): self.warning = SipHeader(body=SipWarning(text=eistr))
def __init__(self, buf = None, method = None, ruri = None, sipver = 'SIP/2.0', to = None, fr0m = None, via = None, cseq = None, \ callid = None, maxforwards = None, body = None, contact = None, routes = (), target = None, cguid = None, user_agent = None, expires = None): SipMsg.__init__(self, buf) if buf != None: try: SipMsg.init_body(self) except ESipParseException as e: try: e.sip_response = self.genResponse( 400, 'Bad Request - %s' % str(e)) except Exception as e1: print('BUG: Double exception, should not be happening:\n', str(e1)) raise e return self.method = method self.ruri = ruri if target == None: if len(routes) == 0: self.setTarget(self.ruri.getAddr()) else: self.setTarget(routes[0].getAddr()) else: self.setTarget(target) self.sipver = sipver self.appendHeader(SipHeader(name='via', body=via)) if via == None: self.getHFBody('via').genBranch() self.appendHeaders([SipHeader(name='route', body=x) for x in routes]) self.appendHeader(SipHeader(name='max-forwards', body=maxforwards)) self.appendHeader(SipHeader(name='from', body=fr0m)) if to == None: to = SipTo(address=SipAddress(url=ruri)) self.appendHeader(SipHeader(name='to', body=to)) self.appendHeader(SipHeader(name='call-id', body=callid)) self.appendHeader( SipHeader(name='cseq', body=SipCSeq(cseq=cseq, method=method))) if contact != None: self.appendHeader(SipHeader(name='contact', body=contact)) if expires == None and method == 'INVITE': expires = SipHeader(name='expires') self.appendHeader(expires) elif expires != None: expires = SipHeader(name='expires', body=expires) self.appendHeader(expires) if user_agent != None: self.user_agent = user_agent self.appendHeader(SipHeader(name='user-agent', bodys=user_agent)) else: self.appendHeader(SipHeader(name='user-agent')) if cguid != None: self.appendHeader(SipHeader(name='cisco-guid', body=cguid)) self.appendHeader(SipHeader(name='h323-conf-id', body=cguid)) if body != None: self.setBody(body)
def incomingResponse(self, msg, t, checksum): # In those two states upper level already notified, only do ACK retransmit # if needed if t.state == TERMINATED: return if t.state == TRYING: # Stop timers if t.teA != None: t.teA.cancel() t.teA = None if t.state in (TRYING, RINGING): if t.teB != None: t.teB.cancel() t.teB = None if msg.getSCode()[0] < 200: # Privisional response - leave everything as is, except that # change state and reload timeout timer if t.state == TRYING: t.state = RINGING if t.cancelPending: self.newTransaction(t.cancel, userv=t.userv) t.cancelPending = False t.teB = Timeout(self.timerB, t.expires, 1, t) self.l1rcache[checksum] = SipTMRetransmitO() if t.resp_cb != None: if t.cb_ifver == 1: t.resp_cb(msg) else: t.resp_cb(msg, t) else: # Final response - notify upper layer and remove transaction if t.resp_cb != None: if t.cb_ifver == 1: t.resp_cb(msg) else: t.resp_cb(msg, t) if t.needack: # Prepare and send ACK if necessary fcode = msg.getSCode()[0] tag = msg.getHFBody('to').getTag() if tag != None: t.ack.getHFBody('to').setTag(tag) rAddr = None if msg.getSCode()[0] >= 200 and msg.getSCode()[0] < 300: # Some hairy code ahead if msg.countHFs('contact') > 0: rTarget = msg.getHFBody( 'contact').getUrl().getCopy() else: rTarget = None routes = [ x.getCopy() for x in msg.getHFBodys('record-route') ] routes.reverse() if len(routes) > 0: if not routes[0].getUrl().lr: if rTarget != None: routes.append( SipRoute(address=SipAddress( url=rTarget))) rTarget = routes.pop(0).getUrl() rAddr = rTarget.getAddr() else: rAddr = routes[0].getAddr() elif rTarget != None: rAddr = rTarget.getAddr() if rTarget != None: t.ack.setRURI(rTarget) if rAddr != None: t.ack.setTarget(rAddr) t.ack.delHFs('route') t.ack.appendHeaders( [SipHeader(name='route', body=x) for x in routes]) if fcode >= 200 and fcode < 300: t.ack.getHFBody('via').genBranch() if rAddr == None: rAddr = t.address if not t.uack: self.transmitMsg(t.userv, t.ack, rAddr, checksum, t.compact) if t.req_out_cb != None: t.req_out_cb(t.ack) else: t.state = UACK t.ack_rAddr = rAddr t.ack_checksum = checksum self.l1rcache[checksum] = SipTMRetransmitO() t.teG = Timeout(self.timerG, 64, 1, t) return else: self.l1rcache[checksum] = SipTMRetransmitO() del self.tclient[t.tid] t.cleanup()
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