示例#1
0
 def keepAliveResp(self, resp):
     if self.ua.state != self:
         return
     code, reason = resp.getSCode()
     if code == 401 and resp.countHFs('www-authenticate') != 0 and \
       self.ua.username != None and self.ua.password != None and not self.triedauth:
         challenge = resp.getHFBody('www-authenticate')
         req = self.ua.genRequest('INVITE', self.ua.lSDP, challenge.getNonce(), challenge.getRealm())
         self.ua.lCSeq += 1
         self.ka_tr = self.ua.global_config['_sip_tm'].newTransaction(req, self.keepAliveResp, \
           laddress = self.ua.source_address)
         self.triedauth = True
         return
     if code == 407 and resp.countHFs('proxy-authenticate') != 0 and \
       self.ua.username != None and self.ua.password != None and not self.triedauth:
         challenge = resp.getHFBody('proxy-authenticate')
         req = self.ua.genRequest('INVITE', self.ua.lSDP, challenge.getNonce(), challenge.getRealm(), SipProxyAuthorization)
         self.ua.lCSeq += 1
         self.ka_tr = self.ua.global_config['_sip_tm'].newTransaction(req, self.keepAliveResp, \
           laddress = self.ua.source_address)
         self.triedauth = True
         return
     if code < 200:
         return
     self.ka_tr = None
     self.keepalives += 1
     if code in (408, 481, 486):
         if self.keepalives == 1:
             print '%s: Remote UAS at %s:%d does not support re-INVITES, disabling keep alives' % (self.ua.cId, self.ua.rAddr[0], self.ua.rAddr[1])
             Timeout(self.ua.disconnect, 600)
             return
         print '%s: Received %d response to keep alive from %s:%d, disconnecting the call' % (self.ua.cId, code, self.ua.rAddr[0], self.ua.rAddr[1])
         self.ua.disconnect()
         return
     Timeout(self.keepAlive, self.ua.kaInterval)
示例#2
0
 def __init__(self, ua):
     UaStateGeneric.__init__(self, ua)
     ua.on_local_sdp_change = None
     ua.on_remote_sdp_change = None
     # 300 provides good estimate on the amount of time during which
     # we can wait for receiving non-negative response to CANCELled
     # INVITE transaction.
     self.te = Timeout(self.goIdle, 300.0)
示例#3
0
 def __init__(self, msg, timeout, next_screen, fine_print = False):
     Screen.__init__(self)
     self.msg = msg
     timer = Timeout(timeout, self)
     self.next_screen = next_screen
     self.fine_print = fine_print
     #stop input
     Foodputer.Foodputer.accept_input = False 
     timer.start()
示例#4
0
 def sendResponse(self, resp, t=None, retrans=False, ack_cb=None):
     #print self.tserver
     if t == None:
         tid = resp.getTId(wBRN=True)
         t = self.tserver[tid]
     if t.state not in (TRYING, RINGING) and not retrans:
         raise ValueError(
             'BUG: attempt to send reply on already finished transaction!!!'
         )
     scode = resp.getSCode()[0]
     toHF = resp.getHFBody('to')
     if scode > 100 and toHF.getTag() == None:
         toHF.genTag()
     t.data = resp.localStr(*t.userv.uopts.laddress, compact=t.compact)
     t.address = resp.getHFBody('via').getTAddr()
     self.transmitData(t.userv, t.data, t.address, t.checksum)
     if scode < 200:
         t.state = RINGING
         if self.provisional_retr > 0 and scode > 100:
             if t.teF != None:
                 t.teF.cancel()
             t.teF = Timeout(self.timerF, self.provisional_retr, 1, t)
     else:
         t.state = COMPLETED
         if t.teE != None:
             t.teE.cancel()
             t.teE = None
         if t.teF != None:
             t.teF.cancel()
             t.teF = None
         if t.needack:
             # Schedule removal of the transaction
             t.ack_cb = ack_cb
             t.teD = Timeout(self.timerD, 32.0, 1, t)
             if scode >= 200:
                 # Black magick to allow proxy send us another INVITE
                 # same branch and From tag. Use To tag to match
                 # ACK transaction after this point. Branch tag in ACK
                 # could differ as well.
                 del self.tserver[t.tid]
                 t.tid = list(t.tid[:-1])
                 t.tid.append(resp.getHFBody('to').getTag())
                 t.tid = tuple(t.tid)
                 self.tserver[t.tid] = t
             # Install retransmit timer if necessary
             t.tout = 0.5
             t.teA = Timeout(self.timerA, t.tout, 1, t)
         else:
             # We have done with the transaction
             del self.tserver[t.tid]
             t.cleanup()
示例#5
0
 def newTransaction(self, msg, resp_cb = None, laddress = None, userv = None, \
   cb_ifver = 1, compact = False):
     t = SipTransaction()
     t.rtime = time()
     t.compact = compact
     t.method = msg.getMethod()
     t.cb_ifver = cb_ifver
     t.tid = msg.getTId(True, True)
     if self.tclient.has_key(t.tid):
         raise ValueError(
             'BUG: Attempt to initiate transaction with the same TID as existing one!!!'
         )
     t.tout = 0.5
     t.fcode = None
     t.address = msg.getTarget()
     if userv == None:
         if laddress == None:
             t.userv = self.l4r.getServer(t.address)
         else:
             t.userv = self.l4r.getServer(laddress, is_local=True)
     else:
         t.userv = userv
     t.data = msg.localStr(*t.userv.uopts.laddress, compact=t.compact)
     if t.method == 'INVITE':
         try:
             t.expires = msg.getHFBody('expires').getNum()
             if t.expires <= 0:
                 t.expires = 300
         except IndexError:
             t.expires = 300
         t.needack = True
         t.ack = msg.genACK()
         t.cancel = msg.genCANCEL()
     else:
         t.expires = 32
         t.needack = False
         t.ack = None
         t.cancel = None
     t.cancelPending = False
     t.resp_cb = resp_cb
     t.teA = Timeout(self.timerA, t.tout, 1, t)
     if resp_cb != None:
         t.r408 = msg.genResponse(408, 'Request Timeout')
     t.teB = Timeout(self.timerB, 32.0, 1, t)
     t.teC = None
     t.state = TRYING
     self.tclient[t.tid] = t
     self.transmitData(t.userv, t.data, t.address)
     return t
示例#6
0
 def __init__(self, ua):
     self.keepalives = 0
     self.ka_tr = None
     UaStateGeneric.__init__(self, ua)
     self.ua.branch = None
     if self.ua.kaInterval > 0:
         Timeout(self.keepAlive, self.ua.kaInterval)
示例#7
0
 def heartbeat_reply(self, stats):
     #print 'heartbeat_reply', self.address, stats, self.online
     if self.shut_down:
         return
     if not self.online:
         return
     if stats == None:
         self.active_sessions = None
         self.go_offline()
     else:
         sessions_created = active_sessions = active_streams = preceived = ptransmitted = 0
         for line in stats.splitlines():
             line_parts = line.split(':', 1)
             if line_parts[0] == 'sessions created':
                 sessions_created = int(line_parts[1])
             elif line_parts[0] == 'active sessions':
                 active_sessions = int(line_parts[1])
             elif line_parts[0] == 'active streams':
                 active_streams = int(line_parts[1])
             elif line_parts[0] == 'packets received':
                 preceived = int(line_parts[1])
             elif line_parts[0] == 'packets transmitted':
                 ptransmitted = int(line_parts[1])
             self.update_active(active_sessions, sessions_created,
                                active_streams, preceived, ptransmitted)
     Timeout(self.heartbeat, randomize(self.hrtb_ival, 0.1))
示例#8
0
 def send_command(self,
                  command,
                  result_callback=None,
                  *callback_parameters):
     cookie = md5(str(random()) + str(time())).hexdigest()
     next_retr = self.delay_flt.lastval * 4.0
     rtime = 3.0
     if isinstance(command, Rtp_proxy_cmd):
         if command.type == 'I':
             rtime = 10.0
         if command.type == 'G':
             rtime = 1.0
         nretr = command.nretr
         command = str(command)
     else:
         if command.startswith('I'):
             rtime = 10.0
         elif command.startswith('G'):
             rtime = 1.0
         nretr = None
     if nretr == None:
         nretr = getnretrans(next_retr, rtime)
     command = '%s %s' % (cookie, command)
     timer = Timeout(self.retransmit, next_retr, 1, cookie)
     stime = MonoTime()
     self.worker.send_to(command, self.address)
     nretr -= 1
     self.pending_requests[cookie] = (next_retr, nretr, timer, command,
                                      result_callback, stime,
                                      callback_parameters)
示例#9
0
 def go_offline(self):
     if self.shut_down:
         return
     #print 'go_offline', self.address, self.online
     if self.online:
         self.online = False
         Timeout(self.version_check, randomize(self.hrtb_retr_ival, 0.1))
示例#10
0
 def sendResponse(self, resp, t=None, retrans=False):
     #print self.tserver
     if t == None:
         tid = resp.getTId()
         t = self.tserver[tid]
     if t.state not in (TRYING, RINGING) and not retrans:
         raise ValueError(
             'BUG: attempt to send reply on already finished transaction!!!'
         )
     scode = resp.getSCode()[0]
     toHF = resp.getHFBody('to')
     if scode > 100 and toHF.getTag() == None:
         toHF.genTag()
     t.data = resp.localStr(t.userv.laddress[0], t.userv.laddress[1])
     t.address = resp.getHFBody('via').getTAddr()
     self.transmitData(t.userv, t.data, t.address, t.checksum)
     if scode < 200:
         t.state = RINGING
         if self.provisional_retr > 0 and scode > 100:
             if t.teF != None:
                 t.teF.cancel()
             t.teF = Timeout(self.timerF, self.provisional_retr, 1, t)
     else:
         t.state = COMPLETED
         if t.teE != None:
             t.teE.cancel()
             t.teE = None
         if t.teF != None:
             t.teF.cancel()
             t.teF = None
         if t.needack:
             # Schedule removal of the transaction
             t.teD = Timeout(self.timerD, 32.0, 1, t)
             if scode >= 300:
                 # Black magick to allow proxy send us another INVITE with diffetent branch
                 del self.tserver[t.tid]
                 t.tid = list(t.tid)
                 t.tid.append(t.branch)
                 t.tid = tuple(t.tid)
                 self.tserver[t.tid] = t
             # Install retransmit timer if necessary
             t.tout = 0.5
             t.teA = Timeout(self.timerA, t.tout, 1, t)
         else:
             # We have done with the transaction
             del self.tserver[t.tid]
             t.cleanup()
示例#11
0
 def conn(self, ua, rtime, origin):
     if self.crec:
         return
     self.crec = True
     self.iTime = ua.setup_ts
     self.cTime = ua.connect_ts
     if ua.remote_ua != None and self.user_agent == None:
         self.user_agent = ua.remote_ua
     if ua.p1xx_ts != None:
         self.p1xx_ts = ua.p1xx_ts
     if ua.p100_ts != None:
         self.p100_ts = ua.p100_ts
     if self.send_start:
         self.asend('Start', rtime, origin, ua)
     self._attributes.extend((('h323-voice-quality', 0), ('Acct-Terminate-Cause', 'User-Request')))
     if self.lperiod != None and self.lperiod > 0:
         self.el = Timeout(self.asend, self.lperiod, -1, 'Alive')
示例#12
0
 def __init__(self, ua):
     UaStateGeneric.__init__(self, ua)
     ua.on_local_sdp_change = None
     ua.on_remote_sdp_change = None
     # 300 provides good estimate on the amount of time during which
     # we can wait for receiving non-negative response to CANCELled
     # INVITE transaction.
     self.te = Timeout(self.goIdle, 300.0)
示例#13
0
 def version_check_reply(self, version):
     if self.shut_down:
         return
     if version == '20040107':
         self.go_online()
     elif self.online:
         self.go_offline()
     else:
         Timeout(self.version_check, randomize(self.hrtb_retr_ival, 0.1))
示例#14
0
 def version_check_reply(self, version):
     if self.shutdown:
         self.worker.shutdown()
         return
     if version == '20040107':
         self.go_online()
     elif self.online:
         self.go_offline()
     else:
         Timeout(self.version_check, 60)
示例#15
0
 def __init__(self, global_config, req_cb=None):
     self.global_config = global_config
     self.l4r = local4remote(global_config, self.handleIncoming)
     self.tclient = {}
     self.tserver = {}
     self.req_cb = req_cb
     self.l1rcache = {}
     self.l2rcache = {}
     self.req_consumers = {}
     Timeout(self.rCachePurge, 32, -1)
示例#16
0
 def conn(self, ua, rtime, origin):
     if self.crec:
         return
     self.crec = True
     self.cTime = rtime
     if self.send_start:
         self.asend('Start', rtime, origin)
     self._attributes.extend((('h323-voice-quality', 0), ('Acct-Terminate-Cause', 'User-Request')))
     if self.lperiod != None:
         self.el = Timeout(self.asend, self.lperiod, -1, 'Alive')
示例#17
0
 def send_command(self,
                  command,
                  result_callback=None,
                  *callback_parameters):
     cookie = md5(str(random()) + str(time())).hexdigest()
     command = '%s %s' % (cookie, command)
     timer = Timeout(self.retransmit, 1, -1, cookie)
     self.pending_requests[cookie] = [
         3, timer, command, result_callback, callback_parameters
     ]
     self.udp_server.send_to(command, self.address)
示例#18
0
 def version_check_reply(self, version):
     if self.shutdown:
         if self.worker != None:
             self.worker.shutdown()
             self.worker = None
         return
     if version == '20040107':
         self.go_online()
     elif self.online:
         self.go_offline()
     else:
         Timeout(self.version_check, randomize(60, 0.1))
示例#19
0
 def timerB(self, t):
     #print 'timerB', t
     t.teB = None
     if t.teA != None:
         t.teA.cancel()
         t.teA = None
     t.state = TERMINATED
     #print '2: Timeout(self.timerC, 32.0, 1, t)', t
     t.teC = Timeout(self.timerC, 32.0, 1, t)
     if t.resp_cb == None:
         return
     t.r408.rtime = time()
     t.resp_cb(t.r408)
示例#20
0
 def retransmit(self, cookie):
     preq = self.pending_requests[cookie]
     # print('command to %s timeout %s cookie %s triesleft %d' % (str(self.address), preq.command, cookie, preq.triesleft))
     if preq.triesleft <= 0 or self.worker == None:
         del self.pending_requests[cookie]
         self.go_offline()
         if preq.result_callback != None:
             preq.result_callback(None, *preq.callback_parameters)
         return
     preq.retransmits += 1
     preq.next_retr *= 2
     preq.timer = Timeout(self.retransmit, preq.next_retr, 1, cookie)
     self.worker.send_to(preq.command, self.address)
     preq.triesleft -= 1
示例#21
0
 def timerB(self, t):
     #print 'timerB', t
     t.teB = None
     if t.teA != None:
         t.teA.cancel()
         t.teA = None
     t.state = TERMINATED
     #print '2: Timeout(self.timerC, 32.0, 1, t)', t
     t.teC = Timeout(self.timerC, 32.0, 1, t)
     if t.resp_cb == None:
         return
     fake_resp = SipRequest(t.data).genResponse(408, 'Request Timeout')
     fake_resp.rtime = time()
     t.resp_cb(fake_resp)
示例#22
0
    def execute(self, timeout=60):
        """
        execute()

        Connect to the URL and send POST-data.  The returned data will
        be passed to ConfusaParser, and either an array of
        dictionary-entries or None will be returned.

        """
        # Get the result and parse it
        opener  = urllib2.build_opener(self.https_client)
        t = Timeout(timeout)
        try:
            res = opener.open(self.url, self.data)
        except xml.sax._exceptions.SAXParseException:
            t.cancel_timeout()
            return None
        except TimeoutException:
            print "Did not receive a timely answer (%s seconds), aborting" % (timeout)
            return None

        t.cancel_timeout()
        return Parser.Parser(res)
示例#23
0
 def heartbeat_reply(self, stats):
     #print 'heartbeat_reply', self.address, stats, self.online
     if self.shutdown:
         self.udp_server.shutdown()
         return
     if not self.online:
         return
     if stats == None:
         self.active_sessions = None
         self.go_offline()
     else:
         for line in stats.splitlines():
             if not line.startswith('active sessions'):
                 continue
             self.update_active(int(line.split(':', 1)[1]))
     Timeout(self.heartbeat, 10)
示例#24
0
 def handle_read(self, data, address, rtime, delayed=False):
     if len(data) > 0 and self.uopts.data_callback != None:
         self.stats[2] += 1
         if self.uopts.ploss_in_rate > 0.0 and not delayed:
             if random() < self.uopts.ploss_in_rate:
                 return
         if self.uopts.pdelay_in_max > 0.0 and not delayed:
             pdelay = self.uopts.pdelay_in_max * random()
             Timeout(self.handle_read, pdelay, 1, data, address, rtime + pdelay, True)
             return
         try:
             self.uopts.data_callback(data, address, self, rtime)
         except:
             print(datetime.now(), 'Udp_server: unhandled exception when processing incoming data')
             print('-' * 70)
             traceback.print_exc(file=sys.stdout)
             print('-' * 70)
             sys.stdout.flush()
示例#25
0
 def retransmit(self, cookie):
     next_retr, triesleft, timer, command, result_callback, stime, callback_parameters = self.pending_requests[
         cookie]
     #print 'command to %s timeout %s cookie %s triesleft %d' % (str(self.address), command, cookie, triesleft)
     if triesleft <= 0 or self.worker == None:
         del self.pending_requests[cookie]
         self.go_offline()
         if result_callback != None:
             result_callback(None, *callback_parameters)
         return
     #next_retr *= 2
     timer = Timeout(self.retransmit, next_retr, 1, cookie)
     stime = MonoTime()
     self.worker.send_to(command, self.address)
     triesleft -= 1
     self.pending_requests[cookie] = (next_retr, triesleft, timer, command,
                                      result_callback, stime,
                                      callback_parameters)
示例#26
0
 def send_to(self, data, address, delayed=False):
     if not isinstance(address, tuple):
         raise Exception('Invalid address, not a tuple: %s' % str(address))
     if self.uopts.ploss_out_rate > 0.0 and not delayed:
         if random() < self.uopts.ploss_out_rate:
             return
     if self.uopts.pdelay_out_max > 0.0 and not delayed:
         pdelay = self.uopts.pdelay_out_max * random()
         Timeout(self.send_to, pdelay, 1, data, address, True)
         return
     addr, port = address
     if self.uopts.family == socket.AF_INET6:
         if not addr.startswith('['):
             raise Exception('Invalid IPv6 address: %s' % addr)
         address = (addr[1:-1], port)
     self.wi_available.acquire()
     self.wi.append((data, address))
     self.wi_available.notify()
     self.wi_available.release()
示例#27
0
class RadiusAccounting(object):
    global_config = None
    drec = None
    crec = None
    iTime = None
    cTime = None
    credit_time = None
    sip_cid = None
    origin = None
    lperiod = None
    el = None
    send_start = None
    complete = False

    def __init__(self, global_config, origin, lperiod = None, send_start = False, itime = None):
        if not itime:
            self.iTime = time()
        else:
            self.iTime = itime
        self.global_config = global_config
        self._attributes = [('h323-call-origin', origin), ('h323-call-type', 'VoIP'), \
          ('h323-session-protocol', 'sipv2'), ('h323-setup-time', ftime(self.iTime))]
        self.drec = False
        self.crec = False
        self.origin = origin
        self.lperiod = lperiod
        self.send_start = send_start

    def setParams(self, username, caller, callee, h323_cid, sip_cid, remote_ip, \
      credit_time = None, h323_in_cid = None):
        if caller == None:
            caller = ''
        self._attributes.extend((('User-Name', username), ('Calling-Station-Id', caller), \
          ('Called-Station-Id', callee), ('h323-conf-id', h323_cid), ('call-id', sip_cid), \
          ('Acct-Session-Id', sip_cid), ('h323-remote-address', remote_ip)))
        if h323_in_cid != None and h323_in_cid != h323_cid:
            self._attributes.append(('h323-incoming-conf-id', h323_in_cid))
        self.credit_time = credit_time
        self.sip_cid = str(sip_cid)
        self.complete = True

    def conn(self, ua, rtime, origin):
        if self.crec:
            return
        self.crec = True
        self.cTime = rtime
        if self.send_start:
            self.asend('Start', rtime, origin)
        self._attributes.extend((('h323-voice-quality', 0), ('Acct-Terminate-Cause', 'User-Request')))
        if self.lperiod != None:
            self.el = Timeout(self.asend, self.lperiod, -1, 'Alive')

    def disc(self, ua, rtime, origin, result = 0):
        if self.drec:
            return
        self.drec = True
        if self.el:
            self.el.cancel()
            self.el = None
        self.asend('Stop', rtime, origin, result)

    def asend(self, type, rtime = None, origin = None, result = 0):
        if not self.complete:
            return
        if not rtime:
            rtime = time()
        attributes = self._attributes[:]
        if type != 'Start':
            if self.cTime:
                duration = rtime - self.cTime
                delay = self.cTime - self.iTime
            else:
                duration = 0
                delay = rtime - self.iTime
            if self.credit_time != None and duration > self.credit_time and duration < self.credit_time + 10:
                duration = self.credit_time
            if result >= 400:
                try:
                    dc = sipErrToH323Err[result][0]
                except:
                    dc = '7f'
            elif result < 200:
                dc = '10'
            else:
                dc = '0'
            attributes.extend((('h323-disconnect-time', ftime(self.iTime + delay + duration)), \
              ('h323-connect-time', ftime(self.iTime + delay)), ('Acct-Session-Time', int(duration)), \
              ('h323-disconnect-cause', dc)))
        else:
            attributes.append(('h323-connect-time', ftime(self.cTime)))
        if type == 'Stop':
            if origin == 'caller':
                release_source = '2'
            elif origin == 'callee':
                release_source = '4'
            else:
                release_source = '8'
            attributes.append(('release-source', release_source))
        attributes.append(('Acct-Status-Type', type))
        pattributes = ['%-32s = \'%s\'\n' % (x[0], str(x[1])) for x in attributes]
        pattributes.insert(0, 'sending Acct %s (%s):\n' % (type, self.origin.capitalize()))
        self.global_config['sip_logger'].write(call_id = self.sip_cid, *pattributes)
        self.global_config['radius_client'].do_acct(attributes, self._process_result, self.sip_cid, time())

    def _process_result(self, results, sip_cid, btime):
        delay = time() - btime
        rcode = results[1]
        if rcode in (0, 1):
            if rcode == 0:
                message = 'Acct/%s request accepted (delay is %.3f)\n' % (self.origin, delay)
            else:
                message = 'Acct/%s request rejected (delay is %.3f)\n' % (self.origin, delay)
        else:
            message = 'Error sending Acct/%s request (delay is %.3f)\n' % (self.origin, delay)
        self.global_config['sip_logger'].write(message, call_id = sip_cid)
示例#28
0
    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()
示例#29
0
class UacStateCancelling(UaStateGeneric):
    sname = 'Cancelling(UAC)'

    def __init__(self, ua):
        UaStateGeneric.__init__(self, ua)
        ua.on_local_sdp_change = None
        ua.on_remote_sdp_change = None
        # 300 provides good estimate on the amount of time during which
        # we can wait for receiving non-negative response to CANCELled
        # INVITE transaction.
        self.te = Timeout(self.goIdle, 300.0)

    def goIdle(self):
        # print 'Time in Cancelling state expired, going to the Dead state'
        self.te = None
        self.ua.changeState((UaStateDead,))

    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,
                                                            compact=self.ua.compact_sip)
            return (UaStateDisconnected,)
        return (UaStateDead,)

    def recvEvent(self, event):
        # print 'wrong event %s in the Cancelling state' % event
        return None
示例#30
0
 def incomingRequest(self, msg, checksum, tids, server):
     for tid in tids:
         if self.tclient.has_key(tid):
             t = self.tclient[tid]
             resp = msg.genResponse(482, 'Loop Detected')
             self.transmitMsg(server, resp, resp.getHFBody('via').getTAddr(), checksum, \
               t.compact)
             return
     if msg.getMethod() != 'ACK':
         tid = msg.getTId(wBRN=True)
     else:
         tid = msg.getTId(wTTG=True)
     t = self.tserver.get(tid, None)
     if t != None:
         #print 'existing transaction'
         if msg.getMethod() == t.method:
             # Duplicate received, check that we have sent any response on this
             # request already
             if t.data != None:
                 self.transmitData(t.userv, t.data, t.address, checksum)
             return
         elif msg.getMethod() == 'CANCEL':
             # RFC3261 says that we have to reply 200 OK in all cases if
             # there is such transaction
             resp = msg.genResponse(200, 'OK')
             self.transmitMsg(t.userv, resp, resp.getHFBody('via').getTAddr(), checksum, \
               t.compact)
             if t.state in (TRYING, RINGING):
                 self.doCancel(t, msg.rtime, msg)
         elif msg.getMethod() == 'ACK' and t.state == COMPLETED:
             t.state = CONFIRMED
             if t.teA != None:
                 t.teA.cancel()
                 t.teA = None
             t.teD.cancel()
             # We have done with the transaction, no need to wait for timeout
             del self.tserver[t.tid]
             if t.ack_cb != None:
                 t.ack_cb(msg)
             t.cleanup()
             self.l1rcache[checksum] = (None, None, None)
     elif msg.getMethod() == 'ACK':
         # Some ACK that doesn't match any existing transaction.
         # Drop and forget it - upper layer is unlikely to be interested
         # to seeing this anyway.
         print datetime.now(), 'unmatched ACK transaction - ignoring'
         sys.stdout.flush()
         self.l1rcache[checksum] = (None, None, None)
     elif msg.getMethod() == 'CANCEL':
         resp = msg.genResponse(481, 'Call Leg/Transaction Does Not Exist')
         self.transmitMsg(server, resp,
                          resp.getHFBody('via').getTAddr(), checksum)
     else:
         #print 'new transaction', msg.getMethod()
         t = SipTransaction()
         t.tid = tid
         t.state = TRYING
         t.teA = None
         t.teD = None
         t.teE = None
         t.teF = None
         t.teG = None
         t.method = msg.getMethod()
         t.rtime = msg.rtime
         t.data = None
         t.address = None
         t.noack_cb = None
         t.ack_cb = None
         t.cancel_cb = None
         t.checksum = checksum
         if server.uopts.laddress[0] not in ('0.0.0.0', '[::]'):
             t.userv = server
         else:
             # For messages received on the wildcard interface find
             # or create more specific server.
             t.userv = self.l4r.getServer(msg.getSource())
         if msg.getMethod() == 'INVITE':
             t.r487 = msg.genResponse(487, 'Request Terminated')
             t.needack = True
             t.branch = msg.getHFBody('via').getBranch()
             try:
                 e = msg.getHFBody('expires').getNum()
                 if e <= 0:
                     e = 300
             except IndexError:
                 e = 300
             t.teE = Timeout(self.timerE, e, 1, t)
         else:
             t.r487 = None
             t.needack = False
             t.branch = None
         self.tserver[t.tid] = t
         for consumer in self.req_consumers.get(t.tid[0], ()):
             cobj = consumer.cobj.isYours(msg)
             if cobj != None:
                 t.compact = consumer.compact
                 rval = cobj.recvRequest(msg, t)
                 break
         else:
             rval = self.req_cb(msg, t)
         if rval == None:
             if t.teA != None or t.teD != None or t.teE != None or t.teF != None:
                 return
             if self.tserver.has_key(t.tid):
                 del self.tserver[t.tid]
             t.cleanup()
             return
         resp, t.cancel_cb, t.noack_cb = rval
         if resp != None:
             self.sendResponse(resp, t)
示例#31
0
class UacStateCancelling(UaStateGeneric):
    sname = 'Cancelling(UAC)'

    def __init__(self, ua):
        UaStateGeneric.__init__(self, ua)
        ua.on_local_sdp_change = None
        ua.on_remote_sdp_change = None
        # 300 provides good estimate on the amount of time during which
        # we can wait for receiving non-negative response to CANCELled
        # INVITE transaction.
        self.te = Timeout(self.goIdle, 300.0)

    def goIdle(self):
        #print 'Time in Cancelling state expired, going to the Dead state'
        self.te = None
        self.ua.changeState((UaStateDead,))

    def recvResponse(self, resp):
        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.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())
            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 recvEvent(self, event):
        #print 'wrong event %s in the Cancelling state' % event
        return None
示例#32
0
 def go_offline(self):
     #print 'go_offline', self.address, self.online
     if self.online:
         self.online = False
         Timeout(self.version_check, 60)
示例#33
0
 def __init__(self, ua):
     UaStateGeneric.__init__(self, ua)
     ua.on_local_sdp_change = None
     ua.on_remote_sdp_change = None
     Timeout(self.goDead, ua.godead_timeout)
示例#34
0
class RadiusAccounting(object):
    global_config = None
    drec = None
    crec = None
    iTime = None
    cTime = None
    sip_cid = None
    origin = None
    lperiod = None
    el = None
    send_start = None
    complete = False
    ms_precision = False
    user_agent = None
    p1xx_ts = None
    p100_ts = None

    def __init__(self, global_config, origin, lperiod = None, send_start = False):
        self.global_config = global_config
        self._attributes = [('h323-call-origin', origin), ('h323-call-type', 'VoIP'), \
          ('h323-session-protocol', 'sipv2')]
        self.drec = False
        self.crec = False
        self.origin = origin
        self.lperiod = lperiod
        self.send_start = send_start

    def setParams(self, username, caller, callee, h323_cid, sip_cid, remote_ip, \
      h323_in_cid = None):
        if caller == None:
            caller = ''
        self._attributes.extend((('User-Name', username), ('Calling-Station-Id', caller), \
          ('Called-Station-Id', callee), ('h323-conf-id', h323_cid), ('call-id', sip_cid), \
          ('Acct-Session-Id', sip_cid), ('h323-remote-address', remote_ip)))
        if h323_in_cid != None and h323_in_cid != h323_cid:
            self._attributes.append(('h323-incoming-conf-id', h323_in_cid))
        self.sip_cid = str(sip_cid)
        self.complete = True

    def conn(self, ua, rtime, origin):
        if self.crec:
            return
        self.crec = True
        self.iTime = ua.setup_ts
        self.cTime = ua.connect_ts
        if ua.remote_ua != None and self.user_agent == None:
            self.user_agent = ua.remote_ua
        if ua.p1xx_ts != None:
            self.p1xx_ts = ua.p1xx_ts
        if ua.p100_ts != None:
            self.p100_ts = ua.p100_ts
        if self.send_start:
            self.asend('Start', rtime, origin, ua)
        self._attributes.extend((('h323-voice-quality', 0), ('Acct-Terminate-Cause', 'User-Request')))
        if self.lperiod != None and self.lperiod > 0:
            self.el = Timeout(self.asend, self.lperiod, -1, 'Alive')

    def disc(self, ua, rtime, origin, result = 0):
        if self.drec:
            return
        self.drec = True
        if self.el != None:
            self.el.cancel()
            self.el = None
        if self.iTime == None:
            self.iTime = ua.setup_ts
        if self.cTime == None:
            self.cTime = rtime
        if ua.remote_ua != None and self.user_agent == None:
            self.user_agent = ua.remote_ua
        if ua.p1xx_ts != None:
            self.p1xx_ts = ua.p1xx_ts
        if ua.p100_ts != None:
            self.p100_ts = ua.p100_ts
        self.asend('Stop', rtime, origin, result, ua)

    def asend(self, type, rtime = None, origin = None, result = 0, ua = None):
        if not self.complete:
            return
        if rtime == None:
            rtime = time()
        if ua != None:
            duration, delay, connected = ua.getAcct()[:3]
        else:
            # Alive accounting
            duration = rtime - self.cTime
            delay = self.cTime - self.iTime
            connected = True
        if not(self.ms_precision):
            duration = round(duration)
            delay = round(delay)
        attributes = self._attributes[:]
        if type != 'Start':
            if result >= 400:
                try:
                    dc = sipErrToH323Err[result][0]
                except:
                    dc = '7f'
            elif result < 200:
                dc = '10'
            else:
                dc = '0'
            attributes.extend((('h323-disconnect-time', self.ftime(self.iTime + delay + duration)), \
              ('Acct-Session-Time', '%d' % round(duration)), ('h323-disconnect-cause', dc)))
        if type == 'Stop':
            if origin == 'caller':
                release_source = '2'
            elif origin == 'callee':
                release_source = '4'
            else:
                release_source = '8'
            attributes.append(('release-source', release_source))
        attributes.extend((('h323-connect-time', self.ftime(self.iTime + delay)), ('h323-setup-time', self.ftime(self.iTime)), \
          ('Acct-Status-Type', type)))
        if self.user_agent != None:
            attributes.append(('h323-ivr-out', 'sip_ua:' + self.user_agent))
        if self.p1xx_ts != None:
            attributes.append(('Acct-Delay-Time', round(self.p1xx_ts)))
        if self.p100_ts != None:
            attributes.append(('provisional-timepoint', self.ftime(self.p100_ts)))
        pattributes = ['%-32s = \'%s\'\n' % (x[0], str(x[1])) for x in attributes]
        pattributes.insert(0, 'sending Acct %s (%s):\n' % (type, self.origin.capitalize()))
        self.global_config['_sip_logger'].write(call_id = self.sip_cid, *pattributes)
        self.global_config['_radius_client'].do_acct(attributes, self._process_result, self.sip_cid, time())

    def ftime(self, t):
        gt = gmtime(t)
        day = strftime('%d', gt)
        if day[0] == '0':
            day = day[1]
        if self.ms_precision:
            msec = (t % 1) * 1000
        else:
            msec = 0
        return strftime('%%H:%%M:%%S.%.3d GMT %%a %%b %s %%Y' % (msec, day), gt)

    def _process_result(self, results, sip_cid, btime):
        delay = time() - btime
        rcode = results[1]
        if rcode in (0, 1):
            if rcode == 0:
                message = 'Acct/%s request accepted (delay is %.3f)\n' % (self.origin, delay)
            else:
                message = 'Acct/%s request rejected (delay is %.3f)\n' % (self.origin, delay)
        else:
            message = 'Error sending Acct/%s request (delay is %.3f)\n' % (self.origin, delay)
        self.global_config['_sip_logger'].write(message, call_id = sip_cid)
示例#35
0
 def timerA(self, t):
     #print 'timerA', t
     self.transmitData(t.userv, t.data, t.address)
     t.tout *= 2
     t.teA = Timeout(self.timerA, t.tout, 1, t)
示例#36
0
 def timerF(self, t):
     #print 'timerF', t.state
     t.teF = None
     if t.state == RINGING and self.provisional_retr > 0:
         self.transmitData(t.userv, t.data, t.address)
         t.teF = Timeout(self.timerF, self.provisional_retr, 1, t)