Пример #1
0
    def rtpp_reply_l(self, rval, sdata):
        #print 'rtpp_reply', sdata
        if rval == 'E71':
            print 'bingo 2'
            Timeout(self.issue_command_l, 2 * random(), 1, sdata)
            return
        if rval == None or rval.startswith('E'):
            print ('rtpp_reply_l: error: %s, original command: %s' % \
              (str(rval), sdata.command_l))
            reactor.stop()
            return

        if random() > 0.5:
            # let 50% of the sessions timeout, disconnect the rest after
            # 8.5-58.5 seconds explicitly
            tout = 8.5 + (50.0 * random())
            if random() > 0.5:
                Timeout(self.issue_command_d, tout, 1, sdata.command_d_b1)
            else:
                Timeout(self.issue_command_d, tout, 1, sdata.command_d_b2)
        self.rcodes.append(rval)
        self.rremain -= 1
        if self.rremain == 0:
            reactor.stop()
        self.issue_command()
Пример #2
0
 def __init__(self, name, global_config, address, cmd_out_address):
     self.call_id_map = []
     self.call_id_map_old = []
     self.name = name
     self.global_config = global_config
     self.asess_filtered = rc_filter(0.9)
     self.cmd_out_address = cmd_out_address
     if cmd_out_address != None:
         bind_address = (cmd_out_address, 0)
     else:
         bind_address = None
     Rtp_proxy_client.__init__(self, global_config, address, bind_address = bind_address)
     self.timer = Timeout(self.call_id_map_aging, 600, -1)
Пример #3
0
 def __init__(self, global_config):
     self.global_config = global_config
     self.ccmap = []
     self.el = Timeout(self.GClector, 60, -1)
     Signal(SIGHUP, self.discAll, SIGHUP)
     Signal(SIGUSR2, self.toggleDebug, SIGUSR2)
     Signal(SIGPROF, self.safeRestart, SIGPROF)
Пример #4
0
 def __init__(self, name, global_config, *args, **kwargs):
     self.call_id_map = []
     self.call_id_map_old = []
     self.name = name
     self.global_config = global_config
     Rtp_proxy_client.__init__(self, global_config, *args, **kwargs)
     self.timer = Timeout(self.call_id_map_aging, 600, -1)
Пример #5
0
 def __init__(self, global_config, bodys, portrange, test_timeout):
     global_config['_sip_tm'] = SipTransactionManager(
         global_config, self.recvRequest)
     Timeout(self.timeout, test_timeout, 1)
     self.bodys = bodys
     self.global_config = global_config
     self.portrange = portrange
Пример #6
0
 def placeOriginate(self, oroute):
     cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData()
     cld = oroute.cld
     self.huntstop_scodes = oroute.params.get('huntstop_scodes', ())
     if self.global_config.has_key('static_tr_out'):
         cld = re_replace(self.global_config['static_tr_out'], cld)
     if oroute.hostport == 'sip-ua':
         host = self.source[0]
         nh_address, same_af = self.source, True
     else:
         host = oroute.hostonly
         nh_address, same_af = oroute.getNHAddr(self.source)
     if not oroute.forward_on_fail and self.global_config['acct_enable']:
         self.acctO = RadiusAccounting(self.global_config, 'originate', \
           send_start = self.global_config['start_acct_enable'], lperiod = \
           self.global_config.getdefault('alive_acct_int', None))
         self.acctO.ms_precision = self.global_config.getdefault(
             'precise_acct', False)
         self.acctO.setParams(oroute.params.get('bill-to', self.username), oroute.params.get('bill-cli', oroute.cli), \
           oroute.params.get('bill-cld', cld), self.cGUID, self.cId, host)
     else:
         self.acctO = None
     self.acctA.credit_time = oroute.credit_time
     conn_handlers = [self.oConn]
     disc_handlers = []
     if not oroute.forward_on_fail and self.global_config['acct_enable']:
         disc_handlers.append(self.acctO.disc)
     self.uaO = UA(self.global_config, self.recvEvent, oroute.user, oroute.passw, nh_address, oroute.credit_time, tuple(conn_handlers), \
       tuple(disc_handlers), tuple(disc_handlers), dead_cbs = (self.oDead,), expire_time = oroute.expires, \
       no_progress_time = oroute.no_progress_expires, extra_headers = oroute.extra_headers)
     self.uaO.local_ua = self.global_config['_uaname']
     if self.source != oroute.params.get('outbound_proxy', None):
         self.uaO.outbound_proxy = oroute.params.get('outbound_proxy', None)
     if self.rtp_proxy_session != None and oroute.params.get('rtpp', True):
         self.uaO.on_local_sdp_change = self.rtp_proxy_session.on_caller_sdp_change
         self.uaO.on_remote_sdp_change = self.rtp_proxy_session.on_callee_sdp_change
         self.rtp_proxy_session.caller.raddress = nh_address
         if body != None:
             body = body.getCopy()
         self.proxied = True
     self.uaO.kaInterval = self.global_config['keepalive_orig']
     if oroute.params.has_key('group_timeout'):
         timeout, skipto = oroute.params['group_timeout']
         Timeout(self.group_expires, timeout, 1, skipto)
     if self.global_config.getdefault('hide_call_id', False):
         cId = SipCallId(
             md5(str(cId)).hexdigest() + ('-b2b_%d' % oroute.rnum))
     else:
         cId += '-b2b_%d' % oroute.rnum
     event = CCEventTry((cId, cGUID, oroute.cli, cld, body, auth, \
       oroute.params.get('caller_name', self.caller_name)))
     if self.eTry.max_forwards != None:
         event.max_forwards = self.eTry.max_forwards - 1
         if event.max_forwards <= 0:
             self.uaA.recvEvent(CCEventFail((483, 'Too Many Hops')))
             self.state = CCStateDead
             return
     event.reason = self.eTry.reason
     self.uaO.recvEvent(event)
Пример #7
0
 def connect(self, ua):
     #if random() > 0.3:
     #    ua.recvEvent(CCEventFail((666, 'Random Failure')))
     #    return
     event = CCEventConnect((200, 'OK', self.body), origin='switch')
     Timeout(self.disconnect, self.disconnect_ival, 1, ua)
     ua.recvEvent(event)
     self.connect_done = True
Пример #8
0
    def rtpp_reply_u(self, rval, sdata):
        #print 'rtpp_reply'
        if rval == 'E72':
            print 'bingo 1'
            Timeout(self.issue_command, 3 * random())
            return
        if rval == None or rval.startswith('E'):
            print ('rtpp_reply_u: error: %s, original command: %s' % \
              (str(rval), sdata.command_u))
            reactor.stop()
            return

        self.rcodes.append(rval)

        if random() < 0.1:
             Timeout(self.issue_command_d, 10 * random(), 1, sdata.command_d_c)
             self.issue_command()
        else:
             self.issue_command_l(sdata)
Пример #9
0
 def __init__(self, global_config, name, address = '/var/run/rtpproxy.sock', dry_run = False):
     self.active = []
     self.pending = []
     self.l1rcache = {}
     self.l2rcache = {}
     if len(address) == 2:
         if not dry_run:
             uopts = Udp_server_opts(address, self.up_command_udp)
             self.ccm = Udp_server(global_config, uopts)
     else:
         sown = global_config.get('_rtpc_sockowner', None)
         if not dry_run:
             self.ccm = Cli_server_local(self.up_command, address, sown)
             self.ccm.protocol.expect_lf = False
     self.global_config = global_config
     self.name = name
     self.address = address
     self.commands_inflight = []
     self.cache_purge_el = Timeout(self.rCachePurge, 10, -1)
Пример #10
0
    def rtpp_reply_u(self, rval, sdata):
        #print 'rtpp_reply'
        if rval == 'E72':
            print 'bingo 1'
            Timeout(self.issue_command, 3 * random())
            return
        if rval == None or rval.startswith('E'):
            print('error: %s' % str(rval))
            reactor.stop()
            return

        self.rcodes.append(rval)
        self.issue_command_l(sdata)
Пример #11
0
    def __init__(self, global_config, body, portrange, tests, test_timeout):
        global_config['_sip_tm'] = SipTransactionManager(
            global_config, self.recvRequest)

        for subtest_class in ALL_TESTS * 2:
            if subtest_class.cli not in tests:
                continue
            sdp_body = body.getCopy()
            fillhostport(sdp_body, portrange, subtest_class.atype)
            subtest = subtest_class(global_config, sdp_body, self.subtest_done,
                                    portrange)
            self.nsubtests_running += 1
        self.rval = self.nsubtests_running
        Timeout(self.timeout, test_timeout, 1)
Пример #12
0
 def answer(self, global_config, body, req, sip_t):
     in_body = req.getBody()
     in_body.parse()
     if not checkhostport(in_body, self.portrange, self.atype):
         self.nerrs += 1
         raise ValueError('Bob(%s): hostport validation has failed' %
                          str(self.__class__))
     # New dialog
     uaA = UA(global_config, self.recvEvent, disc_cbs = (self.disconnected,), \
       fail_cbs = (self.disconnected,), dead_cbs = (self.alldone,))
     uaA.godead_timeout = 10
     uaA.compact_sip = self.compact_sip
     Timeout(self.ring, self.ring_ival, 1, uaA)
     self.body = body
     return uaA.recvRequest(req, sip_t)
Пример #13
0
    def rtpp_reply_l(self, rval, sdata):
        #print 'rtpp_reply'
        if rval == 'E71':
            print 'bingo 2'
            Timeout(self.issue_command_l, 2 * random(), 1, sdata)
            return
        if rval == None or rval.startswith('E'):
            print('error: %s' % str(rval))
            reactor.stop()
            return

        self.rcodes.append(rval)
        self.rremain -= 1
        if self.rremain == 0:
            reactor.stop()
        self.issue_command()
Пример #14
0
class Rtp_cluster_member(Rtp_proxy_client):
    name = None
    status = 'ACTIVE'
    capacity = 4000
    weight = 100
    wan_address = None
    lan_address = None
    call_id_map = None
    call_id_map_old = None
    on_state_change = None
    on_active_update = None
    timer = None
    global_config = None
    asess_filtered = None
    cmd_out_address = None

    def __init__(self, name, global_config, address, cmd_out_address):
        self.call_id_map = []
        self.call_id_map_old = []
        self.name = name
        self.global_config = global_config
        self.asess_filtered = rc_filter(0.9)
        self.cmd_out_address = cmd_out_address
        if cmd_out_address != None:
            bind_address = (cmd_out_address, 0)
        else:
            bind_address = None
        Rtp_proxy_client.__init__(self, global_config, address, bind_address = bind_address)
        self.timer = Timeout(self.call_id_map_aging, 600, -1)

    def reconnect(self, address):
        if self.cmd_out_address != None:
            bind_address = (self.cmd_out_address, 0)
        else:
            bind_address = None
        Rtp_proxy_client.reconnect(self, address, bind_address = bind_address)

    def isYours(self, call_id):
        if call_id in self.call_id_map:
            self.call_id_map.remove(call_id)
            self.call_id_map.insert(0, call_id)
            return True
        if call_id not in self.call_id_map_old:
            return False
        self.call_id_map_old.remove(call_id)
        self.call_id_map.insert(0, call_id)
        return True

    def bind_session(self, call_id, cmd_type):
        if cmd_type != 'D':
            self.call_id_map.insert(0, call_id)
        else:
            self.call_id_map_old.insert(0, call_id)

    def unbind_session(self, call_id):
        self.call_id_map.remove(call_id)
        self.call_id_map_old.insert(0, call_id)

    def go_online(self):
        #print 'go_online', self
        if not self.online:
            self.global_config['_sip_logger'].write('RTPproxy "%s" has changed ' \
              'status from offline to online' % self.name)
            if self.on_state_change != None:
                self.on_state_change(self, True)
        Rtp_proxy_client.go_online(self)

    def go_offline(self):
        #print 'go_offline', self
        if self.online:
            self.global_config['_sip_logger'].write('RTPproxy "%s" has changed ' \
              'status from online to offline' % self.name)
            if self.on_state_change != None:
                self.on_state_change(self, False)
        Rtp_proxy_client.go_offline(self)

    def update_active(self, active_sessions, *more_args):
        self.asess_filtered.apply(active_sessions)
        if self.active_sessions != active_sessions and self.on_active_update != None:
            self.on_active_update(self, active_sessions)
        Rtp_proxy_client.update_active(self, active_sessions, *more_args)

    def call_id_map_aging(self):
        if self.shutdown:
            self.timer.cancel()
            return
        if len(self.call_id_map) < 1000:
            # Do not age if there are less than 1000 calls in the list
            self.call_id_map_old = []
            return
        self.call_id_map_old = self.call_id_map[len(self.call_id_map) / 2:]
        del self.call_id_map[len(self.call_id_map) / 2:]

    def get_caputil(self):
        return (self.asess_filtered.get() / self.capacity)
Пример #15
0
 def placeOriginate(self, args):
     cId, cGUID, cli, cld, body, auth, caller_name = self.eTry.getData()
     rnum, host, cld, credit_time, expires, no_progress_expires, forward_on_fail, user, passw, cli, \
       parameters = args
     self.huntstop_scodes = parameters.get('huntstop_scodes', ())
     if self.global_config.has_key('static_tr_out'):
         cld = re_replace(self.global_config['static_tr_out'], cld)
     if host == 'sip-ua':
         host = self.source[0]
         port = self.source[1]
     else:
         if host.startswith('['):
             # IPv6
             host = host.split(']', 1)
             port = host[1].split(':', 1)
             host = host[0] + ']'
             if len(port) > 1:
                 port = int(port[1])
             else:
                 port = SipConf.default_port
         else:
             # IPv4
             host = host.split(':', 1)
             if len(host) > 1:
                 port = int(host[1])
             else:
                 port = SipConf.default_port
             host = host[0]
     if not forward_on_fail and self.global_config['acct_enable']:
         self.acctO = RadiusAccounting(self.global_config, 'originate', \
           send_start = self.global_config['start_acct_enable'], lperiod = \
           self.global_config.getdefault('alive_acct_int', None))
         self.acctO.ms_precision = self.global_config.getdefault('precise_acct', False)
         self.acctO.setParams(parameters.get('bill-to', self.username), parameters.get('bill-cli', cli), \
           parameters.get('bill-cld', cld), self.cGUID, self.cId, host)
     else:
         self.acctO = None
     self.acctA.credit_time = credit_time
     conn_handlers = [self.oConn]
     disc_handlers = []
     if not forward_on_fail and self.global_config['acct_enable']:
         disc_handlers.append(self.acctO.disc)
     self.uaO = UA(self.global_config, self.recvEvent, user, passw, (host, port), credit_time, tuple(conn_handlers), \
       tuple(disc_handlers), tuple(disc_handlers), dead_cbs = (self.oDead,), expire_time = expires, \
       no_progress_time = no_progress_expires, extra_headers = parameters.get('extra_headers', None))
     if self.source != parameters.get('outbound_proxy', None):
         self.uaO.outbound_proxy = parameters.get('outbound_proxy', None)
     if self.rtp_proxy_session != None and parameters.get('rtpp', True):
         self.uaO.on_local_sdp_change = self.rtp_proxy_session.on_caller_sdp_change
         self.uaO.on_remote_sdp_change = self.rtp_proxy_session.on_callee_sdp_change
         self.rtp_proxy_session.caller_raddress = (host, port)
         if body != None:
             body = body.getCopy()
             body.content += 'a=nortpproxy:yes\r\n'
         self.proxied = True
     self.uaO.kaInterval = self.global_config['keepalive_orig']
     if parameters.has_key('group_timeout'):
         timeout, skipto = parameters['group_timeout']
         Timeout(self.group_expires, timeout, 1, skipto)
     if self.global_config.getdefault('hide_call_id', False):
         cId = SipCallId(md5(str(cId)).hexdigest() + ('-b2b_%d' % rnum))
     else:
         cId += '-b2b_%d' % rnum
     event = CCEventTry((cId, cGUID, cli, cld, body, auth, \
       parameters.get('caller_name', self.caller_name)))
     event.reason = self.eTry.reason
     self.uaO.recvEvent(event)
Пример #16
0
 def connected(self, ua, rtime, origin):
     Timeout(self.disconnect, self.disconnect_ival, 1, ua)
     self.connect_done = True
Пример #17
0
class Rtp_cluster_member(Rtp_proxy_client):
    name = None
    status = 'ACTIVE'
    capacity = 4000
    weight = 100
    wan_address = None
    lan_address = None
    call_id_map = None
    call_id_map_old = None
    on_state_change = None
    on_active_update = None
    timer = None
    global_config = None
    asess_filtered = None
    cmd_out_address = None
    stats_cache = None

    def __init__(self, name, global_config, address, cmd_out_address):
        self.call_id_map = []
        self.call_id_map_old = []
        self.name = name
        self.global_config = global_config
        self.asess_filtered = rc_filter(0.9)
        self.cmd_out_address = cmd_out_address
        self.stats_cache = {}
        if cmd_out_address != None:
            bind_address = (cmd_out_address, 0)
        else:
            bind_address = None
        Rtp_proxy_client.__init__(self,
                                  global_config,
                                  address,
                                  bind_address=bind_address)
        self.timer = Timeout(self.call_id_map_aging, 600, -1)

    def reconnect(self, address):
        if self.cmd_out_address != None:
            bind_address = (self.cmd_out_address, 0)
        else:
            bind_address = None
        Rtp_proxy_client.reconnect(self, address, bind_address=bind_address)

    def isYours(self, call_id):
        if call_id in self.call_id_map:
            self.call_id_map.remove(call_id)
            self.call_id_map.insert(0, call_id)
            return True
        if call_id not in self.call_id_map_old:
            return False
        self.call_id_map_old.remove(call_id)
        self.call_id_map.insert(0, call_id)
        return True

    def bind_session(self, call_id, cmd_type):
        if cmd_type != 'D':
            self.call_id_map.insert(0, call_id)
        else:
            self.call_id_map_old.insert(0, call_id)

    def unbind_session(self, call_id):
        self.call_id_map.remove(call_id)
        self.call_id_map_old.insert(0, call_id)

    def go_online(self):
        #print 'go_online', self
        if not self.online:
            self.global_config['_sip_logger'].write('RTPproxy "%s" has changed ' \
              'status from offline to online' % self.name)
            if self.on_state_change != None:
                self.on_state_change(self, True)
        Rtp_proxy_client.go_online(self)

    def go_offline(self):
        #print 'go_offline', self
        if self.online:
            self.global_config['_sip_logger'].write('RTPproxy "%s" has changed ' \
              'status from online to offline' % self.name)
            self.stats_cache = {}
            if self.on_state_change != None:
                self.on_state_change(self, False)
        Rtp_proxy_client.go_offline(self)

    def update_active(self, active_sessions, *more_args):
        self.asess_filtered.apply(active_sessions)
        if self.active_sessions != active_sessions and self.on_active_update != None:
            self.on_active_update(self, active_sessions)
        Rtp_proxy_client.update_active(self, active_sessions, *more_args)

    def call_id_map_aging(self):
        if self.shut_down:
            self.timer.cancel()
            return
        if len(self.call_id_map) < 1000:
            # Do not age if there are less than 1000 calls in the list
            self.call_id_map_old = []
            return
        self.call_id_map_old = self.call_id_map[len(self.call_id_map) / 2:]
        del self.call_id_map[len(self.call_id_map) / 2:]

    def get_caputil(self):
        return (self.asess_filtered.get() / self.capacity)
Пример #18
0
 def ring(self, ua):
     event = CCEventRing((180, 'Ringing', None), origin='switch')
     Timeout(self.connect, self.answer_ival, 1, ua)
     ua.recvEvent(event)
     self.ring_done = True
Пример #19
0
 def __init__(self, name, *args, **kwargs):
     self.call_id_map = []
     self.call_id_map_old = []
     self.name = name
     Rtp_proxy_client.__init__(self, *args, **kwargs)
     self.timer = Timeout(self.call_id_map_aging, 600, -1)
Пример #20
0
            continue
        if o == '-S':
            sippy_path = a.strip()
            continue
        if o == '-o':
            fname = a.strip()
            if fname == '-':
                file_out = sys.stdout
            else:
                file_out = file(fname, 'w')
        if o == '-t':
            timeout = float(a.strip())
            continue

    if sippy_path != None:
        sys.path.insert(0, sippy_path)

    from sippy.Cli_server_local import Cli_server_local
    from sippy.Cli_server_tcp import Cli_server_tcp
    from sippy.Timeout import Timeout

    ch = cli_handler(file_out)
    if stype == 'unix':
        cs = Cli_server_local(ch.command_received, spath)
    else:
        cs = Cli_server_tcp(ch.command_received, spath)
    if timeout != None:
        Timeout(ch.done, timeout)
    reactor.run(installSignalHandlers=1)
    sys.exit(ch.rval)
Пример #21
0
class Rtp_cluster_member(Rtp_proxy_client):
    name = None
    status = "ACTIVE"
    capacity = 4000
    weight = 100
    wan_address = None
    call_id_map = None
    call_id_map_old = None
    on_state_change = None
    on_active_update = None
    timer = None

    def __init__(self, name, *args, **kwargs):
        self.call_id_map = []
        self.call_id_map_old = []
        self.name = name
        Rtp_proxy_client.__init__(self, *args, **kwargs)
        self.timer = Timeout(self.call_id_map_aging, 600, -1)

    def isYours(self, call_id):
        if call_id in self.call_id_map:
            self.call_id_map.remove(call_id)
            self.call_id_map.insert(0, call_id)
            return True
        if call_id not in self.call_id_map_old:
            return False
        self.call_id_map_old.remove(call_id)
        self.call_id_map.insert(0, call_id)
        return True

    def bind_session(self, call_id, cmd_type):
        if cmd_type != "D":
            self.call_id_map.insert(0, call_id)
        else:
            self.call_id_map_old.insert(0, call_id)

    def unbind_session(self, call_id):
        self.call_id_map.remove(call_id)
        self.call_id_map_old.insert(0, call_id)

    def go_online(self):
        # print 'go_online', self
        if not self.online and self.on_state_change != None:
            self.on_state_change(self, True)
        Rtp_proxy_client.go_online(self)

    def go_offline(self):
        # print 'go_offline', self
        if self.online and self.on_state_change != None:
            self.on_state_change(self, False)
        Rtp_proxy_client.go_offline(self)

    def update_active(self, active_sessions):
        if self.active_sessions != active_sessions and self.on_active_update != None:
            self.on_active_update(self, active_sessions)
        Rtp_proxy_client.update_active(self, active_sessions)

    def call_id_map_aging(self):
        if self.shutdown:
            self.timer.cancel()
            return
        if len(self.call_id_map) < 1000:
            # Do not age if there are less than 1000 calls in the list
            self.call_id_map_old = []
            return
        self.call_id_map_old = self.call_id_map[len(self.call_id_map) / 2 :]
        del self.call_id_map[len(self.call_id_map) / 2 :]
Пример #22
0
class Rtp_cluster_member(Rtp_proxy_client):
    name = None
    status = 'ACTIVE'
    capacity = 4000
    weight = 100
    wan_address = None
    call_id_map = None
    call_id_map_old = None
    on_state_change = None
    on_active_update = None
    timer = None

    def __init__(self, name, *args, **kwargs):
        self.call_id_map = []
        self.call_id_map_old = []
        self.name = name
        Rtp_proxy_client.__init__(self, *args, **kwargs)
        self.timer = Timeout(self.call_id_map_aging, 600, -1)

    def isYours(self, call_id):
        if call_id in self.call_id_map:
            self.call_id_map.remove(call_id)
            self.call_id_map.insert(0, call_id)
            return True
        if call_id not in self.call_id_map_old:
            return False
        self.call_id_map_old.remove(call_id)
        self.call_id_map.insert(0, call_id)
        return True

    def bind_session(self, call_id, cmd_type):
        if cmd_type != 'D':
            self.call_id_map.insert(0, call_id)
        else:
            self.call_id_map_old.insert(0, call_id)

    def unbind_session(self, call_id):
        self.call_id_map.remove(call_id)
        self.call_id_map_old.insert(0, call_id)

    def go_online(self):
        #print 'go_online', self
        if not self.online and self.on_state_change != None:
            self.on_state_change(self, True)
        Rtp_proxy_client.go_online(self)

    def go_offline(self):
        #print 'go_offline', self
        if self.online and self.on_state_change != None:
            self.on_state_change(self, False)
        Rtp_proxy_client.go_offline(self)

    def update_active(self, active_sessions):
        if self.active_sessions != active_sessions and self.on_active_update != None:
            self.on_active_update(self, active_sessions)
        Rtp_proxy_client.update_active(self, active_sessions)

    def call_id_map_aging(self):
        if self.shutdown:
            self.timer.cancel()
            return
        if len(self.call_id_map) < 1000:
            # Do not age if there are less than 1000 calls in the list
            self.call_id_map_old = []
            return
        self.call_id_map_old = self.call_id_map[len(self.call_id_map) / 2:]
        del self.call_id_map[len(self.call_id_map) / 2:]
Пример #23
0
class Rtp_cluster(object):
    global_config = None
    address = None
    name = None
    active = None
    pending = None
    ccm = None
    commands_inflight = None
    l1rcache = None
    l2rcache = None
    cache_purge_el = None

    def __init__(self, global_config, name, address = '/var/run/rtpproxy.sock', dry_run = False):
        self.active = []
        self.pending = []
        self.l1rcache = {}
        self.l2rcache = {}
        if len(address) == 2:
            if not dry_run:
                uopts = Udp_server_opts(address, self.up_command_udp)
                self.ccm = Udp_server(global_config, uopts)
        else:
            sown = global_config.get('_rtpc_sockowner', None)
            if not dry_run:
                self.ccm = Cli_server_local(self.up_command, address, sown)
                self.ccm.protocol.expect_lf = False
        self.global_config = global_config
        self.name = name
        self.address = address
        self.commands_inflight = []
        self.cache_purge_el = Timeout(self.rCachePurge, 10, -1)

    def add_member(self, member):
        member.on_state_change = self.rtpp_status_change
        if member.online:
            self.active.append(member)
        else:
            self.pending.append(member)

    def up_command_udp(self, data, address, server, rtime):
        dataparts = data.split(None, 1)
        if len(dataparts) == 1:
            return
        cookie, cmd = dataparts
        if cookie in self.commands_inflight:
            return
        cresp = self.l1rcache.get(cookie, self.l2rcache.get(cookie, None))
        if cresp != None:
            response = '%s %s' % (cookie, cresp)
            server.send_to(response, address)
            print('Rtp_cluster.up_command_udp(): sending cached response "%s" to %s' % \
              (response[:-1], address))
            return
        self.commands_inflight.append(cookie)
        clim = UdpCLIM(address, cookie, server)
        return self.up_command(clim, cmd)

    def up_command(self, clim, orig_cmd):
        #print 'up_command', orig_cmd
        cmd = Rtp_proxy_cmd(orig_cmd)
        #print cmd
        if len(self.active) == 0:
            self.down_command('E999', clim, cmd, None)
            return
        if cmd.type in ('U', 'L', 'D', 'P', 'S', 'R', 'C', 'Q'):
            #print 'up', cmd.call_id, str(cmd)
            for rtpp in self.active:
                if rtpp.isYours(cmd.call_id):
                    break
            else:
                rtpp = None
            if cmd.type == 'U' and cmd.ul_opts.to_tag == None:
                new_session = True
            else:
                new_session = False
            if rtpp == None and not new_session:
                # Existing session, also check if it exists on any of the offline
                # members and try to relay it there, it makes no sense to broadcast
                # the call to every other node in that case
                for rtpp in self.pending:
                    if rtpp.isYours(cmd.call_id):
                        break
                else:
                    rtpp = None
            if rtpp != None and cmd.type == 'D':
                rtpp.unbind_session(cmd.call_id)
            if rtpp == None and new_session:
                # New session
                rtpp = self.pick_proxy(cmd.call_id)
                rtpp.bind_session(cmd.call_id, cmd.type)
            elif rtpp == None:
                # Existing session we know nothing about
                if cmd.type == 'U':
                    # Do a forced lookup
                    orig_cmd = 'L%s' % cmd.ul_opts.getstr(cmd.call_id, swaptags = True)
                active = [x for x in self.active if x.online]
                br = Broadcaster(len(active), clim, cmd)
                for rtpp in active:
                    if cmd.type in ('U', 'L') and rtpp.lan_address != None:
                        out_cmd = Rtp_proxy_cmd(orig_cmd)
                        out_cmd.ul_opts.local_ip = rtpp.lan_address
                        out_cmd = str(out_cmd)
                    else:
                        out_cmd = orig_cmd
                    rtpp.send_command(out_cmd, self.merge_results, br, rtpp)
                return
        elif cmd.type == 'I' and cmd.command_opts == 'b':
            active = [x for x in self.active if x.online]
            sessions_created = active_sessions = active_streams = preceived = ptransmitted = 0
            for rtpp in active:
                if rtpp.active_sessions == None:
                    # There might be some time between "online" and heartbeat reply,
                    # when stats are still empty, or when proxy goes from offline
                    # to online, skip it
                    continue
                sessions_created += rtpp.sessions_created
                active_sessions += rtpp.active_sessions
                active_streams += rtpp.active_streams
                preceived += rtpp.preceived
                ptransmitted += rtpp.ptransmitted
            reply = 'sessions created: %d\nactive sessions: %d\nactive streams: %d\npackets received: %d\npackets transmitted: %d' % \
              (sessions_created, active_sessions, active_streams, preceived, ptransmitted)
            self.down_command(reply, clim, cmd, None)
            return
        elif cmd.type == 'G':
            active = [x for x in self.active if x.online]
            br = Broadcaster(len(active), clim, cmd)
            br.sobj = Rtpp_stats(cmd.args.split())
            if cmd.command_opts != None and cmd.command_opts.lower() == 'v':
                cmd.command_opts = None
                br.sobj.verbose = True
            cmd.nretr = 0
            for rtpp in active:
                rtpp.send_command(cmd, self.merge_stats_results, br, rtpp)
            return
        else:
            rtpp = self.active[0]
            #print 'up', cmd
        #print 'rtpp.send_command'
        if cmd.type in ('U', 'L') and rtpp.lan_address != None:
            out_cmd = Rtp_proxy_cmd(orig_cmd)
            out_cmd.ul_opts.local_ip = rtpp.lan_address
            out_cmd = str(out_cmd)
        else:
            out_cmd = orig_cmd
        rtpp.send_command(out_cmd, self.down_command, clim, cmd, rtpp)

    def down_command(self, result, clim, cmd, rtpp):
        if isinstance(clim, UdpCLIM) and clim.cookie in self.commands_inflight:
            self.commands_inflight.remove(clim.cookie)
        #print 'down', result
        if result == None:
            result = 'E999'
        elif cmd.type in ('U', 'L') and not result[0].upper() == 'E' and \
          rtpp.wan_address != None:
            #print 'down', cmd.ul_opts.destination_ip, rtpp.wan_address
            req_dip = cmd.ul_opts.destination_ip
            req_lip = cmd.ul_opts.local_ip
            if req_dip != None and not is_dst_local(req_dip) and \
              req_lip != rtpp.lan_address:
                result_parts = result.strip().split()
                result = '%s %s' % (result_parts[0], rtpp.wan_address)
            elif req_lip == None:
                result_parts = result.strip().split()
                result = '%s %s' % (result_parts[0], rtpp.wan_address)
        #    result = '%s %s' % (result_parts[0], '192.168.1.22')
        #print 'down clim.send', result
        response = result + '\n'
        clim.send(response)
        if isinstance(clim, UdpCLIM):
            self.l1rcache[clim.cookie] = response
        clim.close()

    def merge_results(self, result, br, rtpp):
        if result == None:
            result = 'E999'
        if br != None and not result[0].upper() == 'E' and not \
          (br.cmd.type in ('U', 'L') and result == '0'):
            br.results.append(result)
        br.bcount -= 1
        if br.bcount > 0:
            # More results to come
            return
        if len(br.results) == 1:
            rtpp.bind_session(br.cmd.call_id, br.cmd.type)
            self.down_command(br.results[0], br.clim, br.cmd, rtpp)
        else:
            # No results or more than one proxy returns positive
            # XXX: more than one result can probably be handled
            if br.cmd.type in ('U', 'L'):
                self.down_command('0', br.clim, br.cmd, rtpp)
            else:
                self.down_command('E999', br.clim, br.cmd, rtpp)

    def merge_stats_results(self, result, br, rtpp):
        #print 'merge_stats_results, result', result
        if result == None:
            result = rtpp.stats_cache.get(br.sobj.all_names, 'E999')
            print 'merge_stats_results: getting from the cache %s' % result
        elif result[0].upper() != 'E':
            rtpp.stats_cache[br.sobj.all_names] = result
        if br != None and not result[0].upper() == 'E':
            try:
                br.sobj.parseAndAdd(result)
                br.ecount -= 1
            except:
                pass
        br.bcount -= 1
        if br.bcount > 0:
            # More results to come
            return
        #print 'merge_stats_results, br.sobj', br.sobj
        if br.ecount == br.nparts:
            rval = 'E999'
        else:
            rval = str(br.sobj)
        self.down_command(rval, br.clim, br.cmd, rtpp)

    def pick_proxy(self, call_id):
        active = [(rtpp, rtpp.weight * (1 - rtpp.get_caputil())) \
          for rtpp in self.active if rtpp.status == 'ACTIVE' and rtpp.online]
        available = [(rtpp, weight) for rtpp, weight in active if weight > 0]
        if len(available) > 0:
            # Normal case, there are some proxies that are loaded below their capacities
            total_weight = sum([x[1] for x in available])
            thr_weight = (random() * total_weight) % total_weight
            #print total_weight, thr_weight
            for rtpp, weight in available:
                thr_weight -= weight
                if thr_weight < 0:
                    break
            #print 'pick_proxyNG: picked up %s for the call %s (normal)' % (rtpp.name, call_id)
            return rtpp
        elif len(active) > 0:
            max_rtpp, max_weight = active[0] 
            for rtpp, weight in active[1:]:
                if weight > max_weight:
                    max_rtpp, max_weight = rtpp, weight
            #print 'pick_proxyNG: picked up %s for the call %s (overload)' % (max_rtpp.name, call_id)
            return max_rtpp
        print 'pick_proxyNG: OUCH, no proxies to pickup from for the call %s' % (call_id,)
        return None

    def rtpp_status_change(self, rtpp, online):
        #print 'rtpp_status_change', self, rtpp, online
        if online and rtpp in self.pending:
            self.pending.remove(rtpp)
            self.active.append(rtpp)
        if not online and rtpp in self.active:
            self.active.remove(rtpp)
            self.pending.append(rtpp)

    def bring_down(self, rtpp):
        if rtpp in self.active:
            if rtpp.active_sessions in (0, None):
                self.active.remove(rtpp)
                return
            rtpp.status = 'DRAINING'
            rtpp.on_active_update = self.rtpp_active_change
            return
        self.pending.remove(rtpp)

    def rtpp_active_change(self, rtpp, active_sessions):
        if rtpp.status == 'DRAINING' and active_sessions == 0:
            if rtpp in self.pending:
                self.pending.remove(rtpp)
            else:
                self.active.remove(rtpp)
            rtpp.shutdown()

    def rtpp_by_name(self, name):
        idx = 0
        for rtpp in self.active + self.pending:
            if rtpp.name == name:
                return (rtpp, idx)
            idx += 1
        return (None, None)

    def shutdown(self):
        for rtpp in self.active + self.pending:
            rtpp.shutdown()
        if self.ccm != None:
            self.ccm.shutdown()
        if self.cache_purge_el != None:
            self.cache_purge_el.cancel()
        self.active = None
        self.pending = None
        self.ccm = None
        self.cache_purge_el = None

    def all_members(self):
        return tuple(self.active + self.pending)

    def rCachePurge(self):
        self.l2rcache = self.l1rcache
        self.l1rcache = {}
Пример #24
0
 def __init__(self, name, *args, **kwargs):
     self.call_id_map = []
     self.call_id_map_old = []
     self.name = name
     Rtp_proxy_client.__init__(self, *args, **kwargs)
     self.timer = Timeout(self.call_id_map_aging, 600, -1)
Пример #25
0
 def ring(self, ua):
     event = CCEventRing((183, 'Session Progress', self.body), \
       origin = 'switch')
     Timeout(self.connect, self.answer_ival, 1, ua)
     ua.recvEvent(event)
     self.ring_done = True