def recvResponse(self, resp, tr): code, reason = resp.getSCode() if code < 200: return None if self.te != None: self.te.cancel() self.te = None # When the final response arrives make sure to send BYE # if response is positive 200 OK and move into # UaStateDisconnected to catch any in-flight BYE from the # called party. # # If the response is negative or redirect go to the UaStateDead # immediately, since this means that we won't receive any more # requests from the calling party. XXX: redirects should probably # somehow reported to the upper level, but it will create # significant additional complexity there, since after signalling # Failure/Disconnect calling party don't expect any more # events to be delivered from the called one. In any case, # this should be fine, since we are in this state only when # caller already has declared his wilingless to end the session, # so that he is probably isn't interested in redirects anymore. 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() self.ua.rUri.setTag(resp.getHFBody('to').getTag()) req = self.ua.genRequest('BYE') self.ua.lCSeq += 1 self.ua.global_config['_sip_tm'].newTransaction(req, \ laddress = self.ua.source_address) return (UaStateDisconnected, ) return (UaStateDead, )
def recvRequest(self, req): if req.getMethod() != 'INVITE': #print 'wrong request %s in the Trying state' % req.getMethod() return None self.ua.origin = 'caller' #print 'INVITE received in the Idle state, going to the Trying state' if req.countHFs('cisco-guid') != 0: try: self.ua.cGUID = req.getHFBody('cisco-guid').getCopy() except: self.ua.cGUID = SipCiscoGUID() elif req.countHFs('h323-conf-id') != 0: try: self.ua.cGUID = req.getHFBody('h323-conf-id').getCopy() except: self.ua.cGUID = SipCiscoGUID() else: self.ua.cGUID = SipCiscoGUID() self.ua.uasResp = req.genResponse(100, 'Trying', server=self.ua.local_ua) self.ua.lCSeq = 100 # XXX: 100 for debugging so that incorrect CSeq generation will be easily spotted if self.ua.lContact == None: self.ua.lContact = SipContact() self.ua.rTarget = req.getHFBody('contact').getUrl().getCopy() self.ua.routes = [ x.getCopy() for x in self.ua.uasResp.getHFBodys('record-route') ] 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() self.ua.rAddr0 = self.ua.rAddr self.ua.global_config['_sip_tm'].sendResponse( self.ua.uasResp, lossemul=self.ua.uas_lossemul) self.ua.uasResp.getHFBody('to').setTag(self.ua.lTag) self.ua.lUri = SipFrom( address=self.ua.uasResp.getHFBody('to').getUri()) self.ua.rUri = SipTo( address=self.ua.uasResp.getHFBody('from').getUri()) self.ua.cId = self.ua.uasResp.getHFBody('call-id') self.ua.global_config['_sip_tm'].regConsumer( self.ua, str(self.ua.cId), compact=self.ua.compact_sip) if req.countHFs('authorization') == 0: auth = None else: auth = req.getHFBody('authorization').getCopy() body = req.getBody() self.ua.branch = req.getHFBody('via').getBranch() event = CCEventTry((self.ua.cId, self.ua.cGUID, self.ua.rUri.getUrl().username, req.getRURI().username, body, auth, \ self.ua.rUri.getUri().name), rtime = req.rtime, origin = self.ua.origin) try: event.reason = req.getHFBody('reason') except: pass try: event.max_forwards = req.getHFBody('max-forwards').getNum() except: pass if self.ua.expire_time != None: self.ua.expire_time += event.rtime if self.ua.no_progress_time != None: self.ua.no_progress_time += event.rtime if self.ua.expire_time != None and self.ua.no_progress_time >= self.ua.expire_time: self.ua.no_progress_time = None if self.ua.no_progress_time != None: self.ua.no_progress_timer = TimeoutAbs(self.ua.no_progress_expires, self.ua.no_progress_time) elif self.ua.expire_time != None: self.ua.expire_timer = TimeoutAbs(self.ua.expires, self.ua.expire_time) 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.setup_ts = req.rtime return (UasStateTrying, ) else: self.ua.rSDP = body.getCopy() else: self.ua.rSDP = None self.ua.equeue.append(event) self.ua.setup_ts = req.rtime return (UasStateTrying, )
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] = (None, None, None) 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) else: t.state = UACK t.ack_rAddr = rAddr t.ack_checksum = checksum self.l1rcache[checksum] = (None, None, None) t.teG = Timeout(self.timerG, 64, 1, t) return else: self.l1rcache[checksum] = (None, None, None) del self.tclient[t.tid] t.cleanup()
def recvResponse(self, resp): body = resp.getBody() code, reason = resp.getSCode() scode = (code, reason, body) 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 = TimeoutAbs( self.ua.no_progress_expires, self.ua.no_progress_time) elif code < 200 and self.ua.expire_time != None: self.ua.expire_timer = TimeoutAbs(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 = TimeoutAbs(self.ua.expires, self.ua.expire_time) if code < 200: self.ua.last_scode = code 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.getCopy()))) self.ua.rTarget = self.ua.routes.pop(0).getUrl() self.ua.rAddr = self.ua.rTarget.getAddr() else: self.ua.rAddr = self.ua.routes[0].getAddr() else: self.ua.rAddr = self.ua.rTarget.getAddr() self.ua.rUri.setTag(resp.getHFBody('to').getTag()) event = CCEventConnect(scode, rtime=resp.rtime, origin=self.ua.origin) self.ua.startCreditTimer(resp.rtime) 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.connect_ts = resp.rtime return (UaStateConnected, self.ua.conn_cbs, resp.rtime, self.ua.origin) else: self.ua.rSDP = body.getCopy() else: self.ua.rSDP = None self.ua.equeue.append(event) self.ua.connect_ts = resp.rtime return (UaStateConnected, self.ua.conn_cbs, resp.rtime, self.ua.origin) if code in (301, 302) and resp.countHFs('contact') > 0: scode = (code, reason, body, resp.getHFBody('contact').getUrl().getCopy()) self.ua.equeue.append( 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 self.ua.equeue.append(event) self.ua.disconnect_ts = resp.rtime return (UaStateFailed, self.ua.fail_cbs, resp.rtime, self.ua.origin, code)
def recvResponse(self, resp, tr): body = resp.getBody() code, reason = resp.getSCode() scode = (code, reason, body) if code < 200: if self.ua.p1xx_ts == None: self.ua.p1xx_ts = resp.rtime self.ua.last_scode = code event = CCEventRing(scode, rtime=resp.rtime, origin=self.ua.origin) for ring_cb in self.ua.ring_cbs: ring_cb(self.ua, resp.rtime, self.ua.origin, code) 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 None else: self.ua.rSDP = body.getCopy() else: self.ua.rSDP = None self.ua.equeue.append(event) return None 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)) 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) 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').getUrl().getCopy()) self.ua.equeue.append( 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 self.ua.equeue.append(event) self.ua.disconnect_ts = resp.rtime return (UaStateFailed, self.ua.fail_cbs, resp.rtime, self.ua.origin, code)