Exemple #1
0
 def check_audio(conn):
     try:
         yield sleep(5)
         yield conn.send_dtmf(random.choice("23456789"))  # Compelled
         yield sleep(5)
         yield conn.send_dtmf("2")
         if (yield conn.await_disconnect()):
             return OK
         else:
             return NOTWORKING
     except Exception as e:
         print(e)
Exemple #2
0
    def answered(yate, route):
        callid = route["id"]
        route.ret(True, answered_target)

        logger.info("[%s, %s] Call answered.", called, callid)

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

        execute = yield yate.onwatch(
            "call.execute",
            lambda m : m["id"] == callid, until = end)    

        targetid = execute["targetid"]

        if answered_target.startswith("dumb"):           
            yate.msg("call.answered",
                     {"id": targetid,
                      "targetid": callid}).enqueue()

        if answered_handler:
            answered_handler(yate, called, callid, targetid)
        else:
            yield sleep(2)
            yate.msg("call.drop", {"id": targetid}).enqueue()
Exemple #3
0
    def answered(yate, route):
        callid = route["id"]
        route.ret(True, answered_target)

        logger.info("[%s, %s] Call answered.", called, callid)

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

        execute = yield yate.onwatch("call.execute",
                                     lambda m: m["id"] == callid,
                                     until=end)

        targetid = execute["targetid"]

        if answered_target.startswith("dumb"):
            yate.msg("call.answered", {
                "id": targetid,
                "targetid": callid
            }).enqueue()

        if answered_handler:
            answered_handler(yate, called, callid, targetid)
        else:
            yield sleep(2)
            yate.msg("call.drop", {"id": targetid}).enqueue()
Exemple #4
0
 def await_dtmf(self):
     self.logger.debug("Waiting for DTMF")
     qget = self._dtmf.get()
     ret = yield XOR(qget, sleep(8))
     if ret[0] is 1:
         self.logger.debug("Timeout")
         return None
     else:
         #self.logger.debug("Success")
         return ret[1]
Exemple #5
0
def do_nothing(client_yate, server_yate, testid, targetid, callid, remoteid, duration):
    """
    Defines incall activity. Does nothing for specified number of seconds.
    """
    logger.debug("[%d] doing nothing on %s for %d s." % (testid, callid, duration))
    yield sleep(duration)
    getResult()
    logger.debug("[%d] dropping: %s" % (testid, callid))
    yield client_yate.msg("call.drop", {"id": callid}).dispatch()
    getResult()
Exemple #6
0
def do_nothing(client_yate, server_yate, testid, targetid, callid, remoteid, duration):
    """
    Defines incall activity. Does nothing for specified number of seconds.
    """
    logger.debug("[%d] doing nothing on %s for %d s." % (testid, callid, duration))
    yield sleep(duration)
    getResult()
    logger.debug("[%d] dropping: %s" % (testid, callid))
    yield client_yate.msg("call.drop", {"id": callid}).dispatch()
    getResult()
Exemple #7
0
 def await_disconnect(self):
     self.logger.debug("Waiting for disconnect, timeout: %d" % timeout)
     ret = yield XOR(self._end, sleep(timeout))
     # ret[0] is index of deferred that has fired
     if ret[0] is 0:
         self.logger.info("Successfully received hangup from remote")
         return True
     else:
         self.logger.info("Timeout waiting for remote to hangup")
         return False
Exemple #8
0
 def send_dtmf(self, dtmf):
     self.logger.debug("Sending DTMF: %s" % dtmf)
     for c in dtmf:
         #self.logger.debug("At character: %c" % c)
         #self.logger.info("Target: %s" % self._targetid)
         yield self._yate.msg("chan.dtmf", {
             "targetid": self._targetid,
             "text": c,
             "duration": 2000
         }).dispatch()
         yield sleep(0.2)
Exemple #9
0
def detect_dtmf_and_do_nothing(client_yate, server_yate, testid, targetid, callid, remoteid, duration):
    """
    Defines incall activity. Enables dtmf detection on server and does nothing
    for specified number of seconds.
    """
    server_yate.msg("chan.masquerade",
        attrs = {"message" : "chan.detectdtmf",
                 "id": remoteid,
                 "consumer": "dtmf/"}).enqueue()
        
    logger.debug("[%d] detecting dtmf on %s for %d s." % (testid, callid, duration))
    yield sleep(duration)
    getResult()
    logger.debug("[%d] dropping: %s" % (testid, callid))
    yield client_yate.msg("call.drop", {"id": callid}).dispatch()
    getResult()
Exemple #10
0
def detect_dtmf_and_do_nothing(client_yate, server_yate, testid, targetid, callid, remoteid, duration):
    """
    Defines incall activity. Enables dtmf detection on server and does nothing
    for specified number of seconds.
    """
    server_yate.msg("chan.masquerade",
        attrs = {"message" : "chan.detectdtmf",
                 "id": remoteid,
                 "consumer": "dtmf/"}).enqueue()

    logger.debug("[%d] detecting dtmf on %s for %d s." % (testid, callid, duration))
    yield sleep(duration)
    getResult()
    logger.debug("[%d] dropping: %s" % (testid, callid))
    yield client_yate.msg("call.drop", {"id": callid}).dispatch()
    getResult()
Exemple #11
0
    def unanswered(yate, route):
        callid = route["id"]
        route.ret(True, "dumb/")

        logger.info("[%s, %s] Call unanswered.", called, callid)

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

        execute = yield yate.onwatch("call.execute",
                                     lambda m: m["id"] == callid,
                                     until=end)

        targetid = execute["targetid"]

        yield sleep(1)

        yate.msg("call.drop", {"id": targetid, "reason": "noanswer"}).enqueue()
Exemple #12
0
    def unanswered(yate, route):
        callid = route["id"]
        route.ret(True, "dumb/")

        logger.info("[%s, %s] Call unanswered.", called, callid)

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

        execute = yield yate.onwatch(
            "call.execute",
            lambda m : m["id"] == callid, until = end)

        targetid = execute["targetid"]

        yield sleep(1)

        yate.msg("call.drop",
                 {"id": targetid, "reason": "noanswer"}).enqueue()
Exemple #13
0
    def _connect(self):
        try:
            # Username is SIP caller ID in call message
            username = random.choice([
                "crypto_addict", "helpless", "test", ''.join(
                    random.choice(
                        "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
                    )
                    for _ in range(random.choice([n for n in range(4, 23)]))),
                ''.join(
                    random.choice(
                        "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
                    ) for _ in range(random.choice([n for n in range(4, 23)])))
            ])

            self.logger.info("Username for this connection is %s" % username)

            # Create temporary file to record audio
            tmpfile = tempfile.NamedTemporaryFile(delete=False)
            self.recfile = tmpfile.name
            tmpfile.close()
            self.logger.info("Recording call audio to file %s" % self.recfile)

            # Ring
            execute = self._yate.msg("call.execute", {
                "callto": "dumb/",
                "caller": username,
                "target": self._ip
            })

            def answeredWatch(m):
                return execute["id"] == m["targetid"]

            # To avoid race conditions, we actually have
            # to install the message handler *before*
            # initiating the connection.
            answered = self._yate.onwatch("call.answered", answeredWatch)
            yield execute.dispatch()

            self._targetid = execute["targetid"]
            self._id = execute["id"]
            self._dtmf = defer.DeferredQueue()
            self._end = self._yate.onwatch(
                "chan.hangup",
                lambda m, callid=execute["id"]: m["id"] == callid)

            # Attach wavefile consumer to dumb channel
            attach_wave = self._yate.msg(
                "chan.masquerade", {
                    "message": "chan.attach",
                    "id": self._id,
                    "consumer": "wave/record/%s" % self.recfile
                })
            attach_wave.enqueue()

            # Wait for connection to be established
            self.logger.info("Waiting for connection to be established")
            ret = yield XOR(answered, sleep(timeout))
            # ret[0] is index of deferred that has fired
            if ret[0] is 1:
                return TIMEOUT

            self._yate.onmsg(
                "chan.dtmf",
                lambda m: m["targetid"] == execute["id"]).addCallback(
                    lambda dtmf: self.dtmf_callback(dtmf))

            self.logger.info("Connection established, running actual callback")
            retval = yield self._callback(self)

            # Disconnect
            yield self._yate.msg("call.drop", {
                "id": execute["targetid"]
            }).dispatch()

            self.logger.debug("Return value: {}".format(repr(retval)))

            return retval
        except Exception as e:
            self.logger.critical(e)
Exemple #14
0
        except AbandonedException, e:
            if not route.called:
                route.cancel()
            logger.warn("[%d] outgoing call to %s abandoned" % (count, callid))
            failure(Failure(e), count, start)

    logger.debug(
        "Waiting for %d tests to finish" % len(select_non_called(concurrent)))
    yield defer.DeferredList(concurrent)
    logger.info("Test finished!")

    if monitor and monitorid:
        logger.debug("droping monitor connection")
        yield client_yate.msg("call.drop", {"id": monitorid}).dispatch()
        getResult()
        yield sleep(1)
        getResult()

    logger.debug("stopping reactor!")
    reactor.stop()

    logger.info("-"*80)
    logger.info("Summary")
    logger.info("-"*80)
    logger.info("Tests: %d" % (len(successes) + len(failures)))
    if successes:
        logger.info("-"*80)
        logger.info("Successes: %d" % len(successes))
        logger.info("Avg time: %.2f s" %
                    (reduce(lambda x, y: x + y, successes.values(), 0) /
                     len(successes)))
Exemple #15
0
        except AbandonedException, e:
            if not route.called:
                route.cancel()
            logger.warn("[%d] outgoing call to %s abandoned" % (count, callid))
            failure(Failure(e), count, start)            

    logger.debug(
        "Waiting for %d tests to finish" % len(select_non_called(concurrent)))
    yield defer.DeferredList(concurrent)
    logger.info("Test finished!")

    if monitor and monitorid:
        logger.debug("droping monitor connection")
        yield client_yate.msg("call.drop", {"id": monitorid}).dispatch()
        getResult()
        yield sleep(1)
        getResult()

    logger.debug("stopping reactor!")        
    reactor.stop()

    logger.info("-"*80)    
    logger.info("Summary")
    logger.info("-"*80)
    logger.info("Tests: %d" % (len(successes) + len(failures)))
    if successes:
        logger.info("-"*80)        
        logger.info("Successes: %d" % len(successes))
        logger.info("Avg time: %.2f s" %
                    (reduce(lambda x, y: x + y, successes.values(), 0) /
                     len(successes)))
Exemple #16
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))
Exemple #17
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 toparse.next() != ")":
                    raise Excepion("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, 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
Exemple #18
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()
Exemple #19
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()
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 as e:
            if not route.called:
                route.cancel()
            logger.warn("[%d] outgoing call to %s abandoned" % (count, callid))
            failure(Failure(e), count, start)

    logger.debug("Waiting for %d tests to finish" %
                 len(select_non_called(concurrent)))
    yield defer.DeferredList(concurrent)
    logger.info("Test finished!")

    if monitor and monitorid:
        logger.debug("droping monitor connection")
        yield client_yate.msg("call.drop", {"id": monitorid}).dispatch()
        getResult()
        yield sleep(1)
        getResult()

    logger.debug("stopping reactor!")
    reactor.stop()

    logger.info("-" * 80)
    logger.info("Summary")
    logger.info("-" * 80)
    logger.info("Tests: %d" % (len(successes) + len(failures)))
    if successes:
        logger.info("-" * 80)
        logger.info("Successes: %d" % len(successes))
        logger.info("Avg time: %.2f s" %
                    (reduce(lambda x, y: x + y, list(successes.values()), 0) /
                     len(successes)))
    if failures:
        logger.info("-" * 80)
        logger.info("Failures: %d" % len(failures))
        sumt = 0
        for tid, (t, f) in failures.items():
            logger.info("%d, %s %s" % (tid, str(f.type), f.getErrorMessage()))
            sumt = sumt + t
        logger.info("Avg time: %.2f s" % (sumt / len(failures)))