示例#1
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
示例#2
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)
示例#3
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
示例#4
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)