Esempio n. 1
0
 def until_callback(m):
     if later.active():
         later.cancel()
         try:
             raise AbandonedException(m)
         except:
             d.errback(failure.Failure())
Esempio n. 2
0
def dtmf_etc(client_yate, server_yate, testid, targetid, callid, remoteid,
             test):
    """
    Defines incall activity. Activity is defined in a string, according
    to the following rules:
      1-9,*,#     - sends x as dtmf
      connected?  - waits for test.checkpoint message with check==connected
      connected?x - waits for test.checkpoint message with check==connected for x secs
      error!      - raise exception on test.checkpoint message with check==error
      s:x,c:y     - does chan.attach with source==s and consumer==c
      _           - 1s break, _*x - x times 1s
      ...         - ends tester thread but does not drop connection
    Example: _,1,1? - waits 1 second, sends 1, waits for 1 checkpoint.
    """

    end = [server_yate.onwatch("chan.hangup", lambda m: m["id"] == remoteid)]
    ignore_hangup = [False]

    def one_step(step):
        if "c:" in step or "s:" in step:
            media = step.split("|")
            consumer = None
            source = None
            for m in media:
                if m.startswith("c:"):
                    consumer = m[2:]
                elif m.startswith("s:"):
                    source = m[2:]
            if source or consumer:
                attrs = {"message": "chan.attach", "id": callid}
                if source:
                    attrs["source"] = source
                if consumer:
                    attrs["consumer"] = consumer
                client_yate.msg("chan.masquerade", attrs).enqueue()
        elif step == "...":
            logger.debug("[%d] call %s extended" % (testid, callid))
            #tester.extended_calls.append(callid)
            return

        elif "?" in step:
            i = step.find("?")
            check = step[:i]

            timeout = None
            if len(step) > i + 1:
                timeout = int(step[i + 1:])

            check_def = server_yate.onwatch(
                "test.checkpoint",
                lambda m: m["id"] == remoteid and m["check"] == check,
                until=end[0])

            if timeout:
                logger.debug(
                    "[%d] waiting for: %ds for checkpoint: %s on: %s" % \
                             (testid, timeout, check, remoteid))
                yield XOR(check_def, sleep(timeout))
                what, _ = getResult()
                if what > 0:
                    logger.warn(
                        "[%d] timeout while waiting %d s for checkpoint: %s on: %s" % \
                        (testid, timeout, check, remoteid))
                    ##                     client_yate.msg("call.drop", {"id": callid}).enqueue()
                    ##                     logger.debug(
                    ##                         "[%d] dropping connection because of timeout: %s" % (testid, remoteid))
                    raise Exception("Timeout while waiting %d s for checkpoint: %s on: %s" % \
                        (timeout, check, remoteid))
                logger.debug(
                    "[%d] checkpoint: %s on: %s passed" % \
                    (testid, check, remoteid))
            else:
                logger.debug(
                    "[%d] Waiting for checkpoint: '%s' on: %s" % \
                        (testid, check, remoteid))
                yield check_def
                getResult()
        elif "!" in step:
            check = step[:-1]
            error = server_yate.onwatch(
                "test.checkpoint",
                lambda m: m["id"] == remoteid and m["check"] == check,
                until=end[0])
            end[0] = OR(end[0], error)

        elif step in [
                "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "#", "*"
        ]:
            logger.debug("[%d] Sending dtmf: %s to %s" %
                         (testid, step, targetid))
            client_yate.msg("chan.dtmf", {
                "id": callid,
                "targetid": targetid,
                "text": step
            }).enqueue()
        elif "&" in step:
            timeout = int(step[1:])
            ignore_hangup[0] = True
            logger.debug(
                "[%d] Waiting for 'end' checkpoint after hangup for: %d s." %
                (testid, timeout))
            yield OR(end[0], sleep(timeout), patient=False)
            getResult()
            raise AbandonedException("Timeout while waiting for end.")
        else:
            t = 1
            if "*" in step:
                try:
                    t = int(step[2:])
                except ValueError:
                    pass
            logger.debug("[%d] Sleeping for: %d s." % (testid, t))
            yield OR(end[0], sleep(t), patient=False)
            getResult()

    def parse(toparse):
        last = None
        for t in toparse:
            if t == ",":

                def x(a, b):
                    yield go(a)
                    getResult()
                    yield go(b)
                    getResult()

                last = (x(last, parse(toparse)))
            elif t == "(":
                last = parse(toparse)
                if next(toparse) != ")":
                    raise Exception("Unmatched bracket!")
            elif t == ")":
                toparse.back(t)
                break
            elif t == "|":

                def x(a, b):
                    yield OR(go(a), go(b))
                    r = getResult()

                last = x(last, parse(toparse))
            else:
                last = one_step(t)

        if last:
            return last
        else:
            return None

    try:
        yield go(parse(peep(tokenize(test))))
        getResult()

        yield sleep(0.1)
        getResult()
    except Exception as e:
        logger.info("[%d] dropping: %s" % (testid, callid))

        d = OR(
            client_yate.msg("call.drop", {
                "id": callid
            }).dispatch(),
            server_yate.msg("call.drop", {
                "id": remoteid
            }).dispatch())

        if type(e) == type(AbandonedException("")) and ignore_hangup[0]:
            yield server_yate.onwatch(
                "test.checkpoint",
                lambda m: m["id"] == remoteid and m["check"] == "end",
                until=sleep(1))
            getResult()
            logger.debug("[%d] call %s finished" % (testid, callid))
            return

        yield d
        getResult()

        logger.debug("[%d] call %s finished" % (testid, callid))

        raise e

    logger.debug("[%d] dropping: %s" % (testid, callid))
    yield client_yate.msg("call.drop", {"id": callid}).dispatch()
    getResult()
    yield server_yate.msg("call.drop", {"id": remoteid}).dispatch()
    getResult()

    logger.debug("[%d] call %s finished" % (testid, callid))
Esempio n. 3
0
    def one_step(step):
        if "c:" in step or "s:" in step:
            media = step.split("|")
            consumer = None
            source = None
            for m in media:
                if m.startswith("c:"):
                    consumer = m[2:]
                elif m.startswith("s:"):
                    source = m[2:]
            if source or consumer:
                attrs = {"message": "chan.attach", "id": callid}
                if source:
                    attrs["source"] = source
                if consumer:
                    attrs["consumer"] = consumer
                client_yate.msg("chan.masquerade", attrs).enqueue()
        elif step == "...":
            logger.debug("[%d] call %s extended" % (testid, callid))
            #tester.extended_calls.append(callid)
            return

        elif "?" in step:
            i = step.find("?")
            check = step[:i]

            timeout = None
            if len(step) > i + 1:
                timeout = int(step[i + 1:])

            check_def = server_yate.onwatch(
                "test.checkpoint",
                lambda m: m["id"] == remoteid and m["check"] == check,
                until=end[0])

            if timeout:
                logger.debug(
                    "[%d] waiting for: %ds for checkpoint: %s on: %s" % \
                             (testid, timeout, check, remoteid))
                yield XOR(check_def, sleep(timeout))
                what, _ = getResult()
                if what > 0:
                    logger.warn(
                        "[%d] timeout while waiting %d s for checkpoint: %s on: %s" % \
                        (testid, timeout, check, remoteid))
                    ##                     client_yate.msg("call.drop", {"id": callid}).enqueue()
                    ##                     logger.debug(
                    ##                         "[%d] dropping connection because of timeout: %s" % (testid, remoteid))
                    raise Exception("Timeout while waiting %d s for checkpoint: %s on: %s" % \
                        (timeout, check, remoteid))
                logger.debug(
                    "[%d] checkpoint: %s on: %s passed" % \
                    (testid, check, remoteid))
            else:
                logger.debug(
                    "[%d] Waiting for checkpoint: '%s' on: %s" % \
                        (testid, check, remoteid))
                yield check_def
                getResult()
        elif "!" in step:
            check = step[:-1]
            error = server_yate.onwatch(
                "test.checkpoint",
                lambda m: m["id"] == remoteid and m["check"] == check,
                until=end[0])
            end[0] = OR(end[0], error)

        elif step in [
                "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "#", "*"
        ]:
            logger.debug("[%d] Sending dtmf: %s to %s" %
                         (testid, step, targetid))
            client_yate.msg("chan.dtmf", {
                "id": callid,
                "targetid": targetid,
                "text": step
            }).enqueue()
        elif "&" in step:
            timeout = int(step[1:])
            ignore_hangup[0] = True
            logger.debug(
                "[%d] Waiting for 'end' checkpoint after hangup for: %d s." %
                (testid, timeout))
            yield OR(end[0], sleep(timeout), patient=False)
            getResult()
            raise AbandonedException("Timeout while waiting for end.")
        else:
            t = 1
            if "*" in step:
                try:
                    t = int(step[2:])
                except ValueError:
                    pass
            logger.debug("[%d] Sleeping for: %d s." % (testid, t))
            yield OR(end[0], sleep(t), patient=False)
            getResult()
Esempio n. 4
0
def load(client_yate, server_yate, target, handler, con_max, tests, monitor):
    """
    Generate load. Needs:
        client and server yate connections;
        target number;
        handler function that defines incall activity;
        starts not more than con_max concurrent calls;
        tests is a list of tests to execute
        monitor is a extension that will be used to monitor tests.
    """

    concurrent = []
    monitored = []

    successes, failures = {}, {}

    def success(_, t, start):
        successes[t] = time.time() - start

    def failure(f, t, start):
        failures[t] = (time.time() - start, f)

    yield server_yate.installMsgHandler("call.route", prio = 50)
    getResult()
    yield client_yate.installWatchHandler("call.answered")
    getResult()
    yield client_yate.installWatchHandler("chan.hangup")
    getResult()
    yield server_yate.installWatchHandler("test.checkpoint")
    getResult()

    if monitor:
        monitorid = None
        monitor_room = None

        logger.debug("Creating monitoring connection.")

        execute = client_yate.msg("call.execute",
         {"callto": "dumb/",
          "target": monitor})
        yield execute.dispatch()
        if not getResult():
            logger.warn("can't create monitor connection on %s" % monitor)
            monitor = None
        else:
            try:
                end = client_yate.onwatch(
                    "chan.hangup",
                    lambda m, callid = execute["id"] : m["id"] == callid)

                yield client_yate.onwatch(
                    "call.answered",
                    lambda m : m["id"] ==  execute["targetid"],
                    until = end)
                getResult()
                logger.debug("Monitor connection answered.")

                dumbid = execute["id"]
                monitorid = execute["targetid"]

                execute = client_yate.msg(
                    "chan.masquerade",
                    {"message": "call.execute",
                     "id": execute["targetid"],
                     "lonely": "true",
                     "voice": "false",
                     "echo": "false",
                     "smart": "true",
                     "callto": "conf/"})
                yield execute.dispatch()
                if getResult():
                    monitor_room = execute["room"]
                    logger.debug("Monitor conference created.")
                    yield client_yate.msg("call.drop", {"id": dumbid}).dispatch()
                    getResult()
                else:
                    logger.warn("can't create monitor conference on %s" % monitor)
                    monitor = None
            except AbandonedException:
                logger.debug("Monitor connection not answered.")
                monitor = None

    count = 0

    for t in tests:
        concurrent = select_non_called(concurrent)
        if len(concurrent) >= con_max:
            logger.debug("waiting on concurrency limit: %d" % con_max)
            yield defer.DeferredList(concurrent, fireOnOneCallback=True)
            _, fired = getResult()
            concurrent.remove(concurrent[fired])

        count = count + 1
        start = time.time()

        route = server_yate.onmsg(
            "call.route",
            lambda m : m["driver"] != "dumb" and m["called"].find(impossible_prefix) >= 0)

        def getRemoteId(d):
            yield d
            route = getResult()
            route["called"] = route["called"].replace(impossible_prefix, "")
            remoteid = route["id"]
            route.ret(False)
            yield remoteid
            return

        remoteid_def = go(getRemoteId(route))

        execute = client_yate.msg(
            "call.execute",
            {"callto": "dumb/",
             "target": target % impossible_prefix,
             "maxcall": 1000})

        yield execute.dispatch()

        try:
            if not getResult():
                route.cancel()
                raise AbandonedException("Call to: %s failed." % target)

            callid = execute["id"]

            end = client_yate.onwatch(
                "chan.hangup",
                lambda m, callid = callid : m["id"] == callid)

            yield OR(remoteid_def, end, patient = False)

            end_first, remoteid  = getResult()

            if end_first:
                raise AbandonedException("Call to: %s hungup." % target)

            logger.debug("[%d] outgoing call to %s" % (count, callid))

            yield client_yate.onwatch(
                "call.answered",
                lambda m : m["targetid"] ==  callid,
                until = end)
            answered = getResult()

            targetid = execute["targetid"]

            monitoring = False

            if monitor and not monitored :
                logger.debug("[%d] monitoring: %s" % (count, callid))
                monitored.append(callid)
                end.addCallback(
                    lambda _, targetid = targetid: client_yate.msg("call.drop", {"id": targetid}).enqueue())

                yield client_yate.msg(
                    "chan.masquerade",
                    {"message": "call.conference",
                     "id": callid,
                     "room": monitor_room}).dispatch()
                getResult()
                monitoring = True

            logger.debug("[%d] recording: %s" % (count, str(callid)))
            client_yate.msg(
                "chan.masquerade",
                {"message": "chan.attach",
                 "id": callid,
#                 "source": "moh/default",
                 "source": "tone/silence",
                 "consumer": "wave/record//tmp/recording%s.slin" % \
                     callid.replace("/", "-"),
                 "maxlen": 0}).enqueue()

#            yield remoteid_def
#            remoteid = getResult()

            logger.debug(
                "[%d] running test with local=(%s, %s) remote=%s" %
                (count, targetid, callid, remoteid))

            start = time.time()

            result = go(handler(
                client_yate, server_yate,
                count,
                targetid,
                callid, remoteid, t))

            result.addCallbacks(success, failure,
                                callbackArgs=(count, start),
                                errbackArgs=(count, start))

            if monitoring:
                result.addCallback(
                    lambda _, mon_id: monitored.remove(mon_id),
                    callid)

            concurrent.append(result)
        except AbandonedException, e:
            if not route.called:
                route.cancel()
            logger.warn("[%d] outgoing call to %s abandoned" % (count, callid))
            failure(Failure(e), count, start)