Code Monkey home page Code Monkey logo

pysipp's Introduction

Coverity Scan Build Status

SIPp - a SIP protocol test tool Copyright (C) 2003-2020 - The Authors

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Documentation

See the docs/ directory. It should also be available in html format at: https://sipp.readthedocs.io/en/latest/

Build a local copy using: sphinx-build docs _build

Building

This is the SIPp package. Please refer to the webpage for details and documentation.

Normally, you should be able to build SIPp by using CMake:

cmake .
make

The SIPp master branch (3.7.x) requires a modern C++11 compiler.

There are several optional flags to enable features (SIP-over-TLS, SIP-over-SCTP, media playback from PCAP files and the GNU Scientific Libraries for random distributions):

cmake . -DUSE_SSL=1 -DUSE_SCTP=1 -DUSE_PCAP=1 -DUSE_GSL=1

Static builds

SIPp can be built into a single static binary, removing the need for libraries to exist on the target system and maximising portability.

This is a fairly complicated process, and for now, it only works on Alpine Linux.

To build a static binary, pass -DBUILD_STATIC=1 to cmake.

Two Alpine-based Dockerfiles are provided, which can be used as a build-environment. Use either Dockerfile or Dockerfile.full in the following commands:

git submodule update --init
docker build -t sipp -f docker/Dockerfile --output=. --target=bin .

Support

I try and be responsive to issues raised on Github, and there's a reasonably active mailing list.

Making a release

  • Update CHANGES.md. Tag release. Do a build.
  • Make sipp.1 by calling:
    help2man --output=sipp.1 -v -v --no-info \
      --name='SIP testing tool and traffic generator' ./sipp
    
  • Then:
    mkdir sipp-$VERSION
    git ls-files -z | tar -c --null \
       --exclude=gmock --exclude=gtest --files-from=- | tar -xC sipp-$VERSION
    cp sipp.1 sipp-$VERSION/
    # check version, and do
    cp ${PROJECT_BINARY_DIR:-.}/version.h sipp-$VERSION/include/
    tar --sort=name --mtime="@$(git log -1 --format=%ct)" \
          --owner=0 --group=0 --numeric-owner \
          -czf sipp-$VERSION.tar.gz sipp-$VERSION
    
  • Upload to github as "binary". Note that github replaces tilde sign (for ~rcX) with a period.
  • Create a static binary and upload this to github as well:
    docker build -t sipp -f docker/Dockerfile --output=. --target=bin .
    
  • Note that the static build is broken at the moment. See ldd sipp.

Contributing

SIPp is free software, under the terms of the GPL licence (see the LICENCE.txt file for details). You can contribute to the development of SIPp and use the standard Github fork/pull request method to integrate your changes integrate your changes. If you make changes in SIPp, PLEASE follow a few coding rules:

  • Please stay conformant with the current indentation style (4 spaces indent, standard Emacs-like indentation). Examples:

    if (condition) {        /* "{" even if only one instruction */
        f();                /* 4 space indents */
    } else {
        char* p = ptr;      /* C++-style pointer declaration placement */
        g(p);
    }
    
  • If possible, check that your changes can be compiled on:

    • Linux,
    • Cygwin,
    • Mac OS X,
    • FreeBSD.

Thanks,

Rob Day [email protected]

pysipp's People

Contributors

goodboy avatar kontsaki avatar linuxmaniac avatar vodik avatar y-luis-rojo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pysipp's Issues

Issues with SIPp Command Timeout returning incorrect code.

Hi,

I have noticed that when SIPp times out (-timeout) pysipp incorrectly indicates the scenario was successful (Return code 0)

To replicate I am using the default_with_confpy scenario with the following changes to pysipp_conf.py:

def pysipp_conf_scen(agents, scen):
    agents['uas'].timeout = 30
    agents['uas'].call_count = 2

main.py looks like this:

import pysipp

pysipp.utils.log_to_stderr("DEBUG")

scen = pysipp.scenario(
    dirpath='./default_with_confpy'
)

print(scen.cmditems())

try:
    stuff = scen(timeout=180)
except Exception as e:
    print(e)
    exit()

Which appears to pass with exit code 0 despite timing out after 30 seconds ( I edited report.py to log the return code):

# time python main.py
2021-02-13 15:40:58,385 MainThread [DEBUG] pysipp agent.py:387 : uas 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {})])
2021-02-13 15:40:58,385 MainThread [DEBUG] pysipp agent.py:387 : uas 'serverdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {})])
2021-02-13 15:40:58,385 MainThread [DEBUG] pysipp agent.py:387 : uas 'agent.todict()' contents:
{'bin_path': '/usr/local/bin/sipp', 'call_count': 2, 'scen_file': '/opt/default_with_confpy/uas.xml', 'timeout': 30}
2021-02-13 15:40:58,385 MainThread [DEBUG] pysipp agent.py:390 : uas merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 2), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('bin_path', '/usr/local/bin/sipp'), ('scen_file', '/opt/default_with_confpy/uas.xml'), ('timeout', 30)])
2021-02-13 15:40:58,386 MainThread [DEBUG] pysipp agent.py:387 : uac 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {})])
2021-02-13 15:40:58,387 MainThread [DEBUG] pysipp agent.py:387 : uac 'clientdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {})])
2021-02-13 15:40:58,387 MainThread [DEBUG] pysipp agent.py:387 : uac 'agent.todict()' contents:
{'bin_path': '/usr/local/bin/sipp', 'scen_file': '/opt/default_with_confpy/uac.xml'}
2021-02-13 15:40:58,387 MainThread [DEBUG] pysipp agent.py:390 : uac merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('bin_path', '/usr/local/bin/sipp'), ('scen_file', '/opt/default_with_confpy/uac.xml')])
2021-02-13 15:40:58,388 MainThread [DEBUG] pysipp agent.py:387 : uas 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {})])
2021-02-13 15:40:58,388 MainThread [DEBUG] pysipp agent.py:387 : uas 'serverdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {})])
2021-02-13 15:40:58,388 MainThread [DEBUG] pysipp agent.py:387 : uas 'agent.todict()' contents:
{'bin_path': '/usr/local/bin/sipp', 'call_count': 2, 'local_host': '0.0.0.0', 'local_port': 41782, 'media_addr': '0.0.0.0', 'media_port': 45028, 'mediaaddr': ('0.0.0.0', 45028), 'scen_file': '/opt/default_with_confpy/uas.xml', 'srcaddr': ('0.0.0.0', 41782), 'timeout': 30}
2021-02-13 15:40:58,388 MainThread [DEBUG] pysipp agent.py:390 : uas merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 2), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('bin_path', '/usr/local/bin/sipp'), ('local_host', '0.0.0.0'), ('local_port', 41782), ('media_addr', '0.0.0.0'), ('media_port', 45028), ('mediaaddr', ('0.0.0.0', 45028)), ('scen_file', '/opt/default_with_confpy/uas.xml'), ('srcaddr', ('0.0.0.0', 41782)), ('timeout', 30)])
2021-02-13 15:40:58,392 MainThread [DEBUG] pysipp agent.py:387 : uas 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {})])
2021-02-13 15:40:58,393 MainThread [DEBUG] pysipp agent.py:387 : uas 'serverdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {})])
2021-02-13 15:40:58,393 MainThread [DEBUG] pysipp agent.py:387 : uas 'agent.todict()' contents:
{'bin_path': '/usr/local/bin/sipp', 'call_count': 2, 'local_host': '0.0.0.0', 'local_port': 41782, 'media_addr': '0.0.0.0', 'media_port': 45028, 'mediaaddr': ('0.0.0.0', 45028), 'scen_file': '/opt/default_with_confpy/uas.xml', 'srcaddr': ('0.0.0.0', 41782), 'timeout': 30}
2021-02-13 15:40:58,394 MainThread [DEBUG] pysipp agent.py:390 : uas merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 2), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('bin_path', '/usr/local/bin/sipp'), ('local_host', '0.0.0.0'), ('local_port', 41782), ('media_addr', '0.0.0.0'), ('media_port', 45028), ('mediaaddr', ('0.0.0.0', 45028)), ('scen_file', '/opt/default_with_confpy/uas.xml'), ('srcaddr', ('0.0.0.0', 41782)), ('timeout', 30)])
2021-02-13 15:40:58,395 MainThread [DEBUG] pysipp agent.py:387 : uac 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {})])
2021-02-13 15:40:58,395 MainThread [DEBUG] pysipp agent.py:387 : uac 'clientdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {}), ('destaddr', ('0.0.0.0', 41782))])
2021-02-13 15:40:58,395 MainThread [DEBUG] pysipp agent.py:387 : uac 'agent.todict()' contents:
{'bin_path': '/usr/local/bin/sipp', 'local_host': '0.0.0.0', 'local_port': 57106, 'media_addr': '0.0.0.0', 'media_port': 54202, 'mediaaddr': ('0.0.0.0', 54202), 'scen_file': '/opt/default_with_confpy/uac.xml', 'srcaddr': ('0.0.0.0', 57106)}
2021-02-13 15:40:58,396 MainThread [DEBUG] pysipp agent.py:390 : uac merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('destaddr', ('0.0.0.0', 41782)), ('bin_path', '/usr/local/bin/sipp'), ('local_host', '0.0.0.0'), ('local_port', 57106), ('media_addr', '0.0.0.0'), ('media_port', 54202), ('mediaaddr', ('0.0.0.0', 54202)), ('scen_file', '/opt/default_with_confpy/uac.xml'), ('srcaddr', ('0.0.0.0', 57106))])
[('uas', "'/usr/local/bin/sipp' -i '0.0.0.0' -p '41782' -mi '0.0.0.0' -mp '45028' -sf '/opt/default_with_confpy/uas.xml' -recv_timeout '5000' -timeout '30' -r '1' -l '1' -m '2' -log_file '/tmp/uas_log_file' -screen_file '/tmp/uas_screen_file' -trace_logs -trace_screen "), ('uac', "'/usr/local/bin/sipp' -i '0.0.0.0' -p '57106' -mi '0.0.0.0' -mp '54202' -sf '/opt/default_with_confpy/uac.xml' -recv_timeout '5000' -r '1' -l '1' -m '1' -log_file '/tmp/uac_log_file' -screen_file '/tmp/uac_screen_file' -trace_logs -trace_screen '0.0.0.0':'41782'")]
2021-02-13 15:40:58,398 MainThread [DEBUG] pysipp agent.py:387 : uas 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {})])
2021-02-13 15:40:58,398 MainThread [DEBUG] pysipp agent.py:387 : uas 'serverdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {})])
2021-02-13 15:40:58,398 MainThread [DEBUG] pysipp agent.py:387 : uas 'agent.todict()' contents:
{'bin_path': '/usr/local/bin/sipp', 'call_count': 2, 'local_host': '0.0.0.0', 'local_port': 41782, 'media_addr': '0.0.0.0', 'media_port': 45028, 'mediaaddr': ('0.0.0.0', 45028), 'scen_file': '/opt/default_with_confpy/uas.xml', 'srcaddr': ('0.0.0.0', 41782), 'timeout': 30}
2021-02-13 15:40:58,399 MainThread [DEBUG] pysipp agent.py:390 : uas merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 2), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('bin_path', '/usr/local/bin/sipp'), ('local_host', '0.0.0.0'), ('local_port', 41782), ('media_addr', '0.0.0.0'), ('media_port', 45028), ('mediaaddr', ('0.0.0.0', 45028)), ('scen_file', '/opt/default_with_confpy/uas.xml'), ('srcaddr', ('0.0.0.0', 41782)), ('timeout', 30)])
2021-02-13 15:40:58,400 MainThread [DEBUG] pysipp agent.py:387 : uac 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {})])
2021-02-13 15:40:58,400 MainThread [DEBUG] pysipp agent.py:387 : uac 'clientdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {}), ('destaddr', ('0.0.0.0', 41782))])
2021-02-13 15:40:58,400 MainThread [DEBUG] pysipp agent.py:387 : uac 'agent.todict()' contents:
{'bin_path': '/usr/local/bin/sipp', 'local_host': '0.0.0.0', 'local_port': 57106, 'media_addr': '0.0.0.0', 'media_port': 54202, 'mediaaddr': ('0.0.0.0', 54202), 'scen_file': '/opt/default_with_confpy/uac.xml', 'srcaddr': ('0.0.0.0', 57106)}
2021-02-13 15:40:58,400 MainThread [DEBUG] pysipp agent.py:390 : uac merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('destaddr', ('0.0.0.0', 41782)), ('bin_path', '/usr/local/bin/sipp'), ('local_host', '0.0.0.0'), ('local_port', 57106), ('media_addr', '0.0.0.0'), ('media_port', 54202), ('mediaaddr', ('0.0.0.0', 54202)), ('scen_file', '/opt/default_with_confpy/uac.xml'), ('srcaddr', ('0.0.0.0', 57106))])
2021-02-13 15:40:58,401 MainThread [DEBUG] pysipp launch.py:62 : launching cmd:
"'/usr/local/bin/sipp' -i '0.0.0.0' -p '41782' -mi '0.0.0.0' -mp '45028' -sf '/opt/default_with_confpy/uas.xml' -recv_timeout '5000' -timeout '30' -r '1' -l '1' -m '2' -log_file '/tmp/uas_log_file' -screen_file '/tmp/uas_screen_file' -trace_logs -trace_screen "

2021-02-13 15:40:58,403 MainThread [DEBUG] pysipp launch.py:70 : registering fd '5' for pid '402'
2021-02-13 15:40:58,407 MainThread [DEBUG] pysipp launch.py:62 : launching cmd:
"'/usr/local/bin/sipp' -i '0.0.0.0' -p '57106' -mi '0.0.0.0' -mp '54202' -sf '/opt/default_with_confpy/uac.xml' -recv_timeout '5000' -r '1' -l '1' -m '1' -log_file '/tmp/uac_log_file' -screen_file '/tmp/uac_screen_file' -trace_logs -trace_screen '0.0.0.0':'41782'"

2021-02-13 15:40:58,409 MainThread [DEBUG] pysipp launch.py:70 : registering fd '6' for pid '403'
2021-02-13 15:40:58,414 Thread-1 [DEBUG] pysipp launch.py:86 : started waiter for procs OrderedDict([(5, <Popen: returncode: None args: ['/usr/local/bin/sipp', '-i', '0.0.0.0', '-p'...>), (6, <Popen: returncode: None args: ['/usr/local/bin/sipp', '-i', '0.0.0.0', '-p'...>)])
2021-02-13 15:40:59,509 Thread-1 [DEBUG] pysipp launch.py:92 : received hangup for pairs '[(6, 16)]'
2021-02-13 15:40:59,509 Thread-1 [DEBUG] pysipp launch.py:97 : collecting streams for <Popen: returncode: None args: ['/usr/local/bin/sipp', '-i', '0.0.0.0', '-p'...>
2021-02-13 15:40:59,509 Thread-1 [DEBUG] pysipp launch.py:99 : Streams(stdout=None, stderr=b"Resolving remote host '0.0.0.0'... Done.\n")
2021-02-13 15:41:28,461 Thread-1 [DEBUG] pysipp launch.py:92 : received hangup for pairs '[(5, 16)]'
2021-02-13 15:41:28,462 Thread-1 [DEBUG] pysipp launch.py:97 : collecting streams for <Popen: returncode: None args: ['/usr/local/bin/sipp', '-i', '0.0.0.0', '-p'...>
2021-02-13 15:41:28,462 Thread-1 [DEBUG] pysipp launch.py:99 : Streams(stdout=None, stderr=b'')
2021-02-13 15:41:28,462 Thread-1 [DEBUG] pysipp launch.py:104 : terminating waiter thread
2021-02-13 15:41:28,468 MainThread [DEBUG] pysipp report.py:35 : uas = 0
2021-02-13 15:41:28,468 MainThread [DEBUG] pysipp report.py:35 : uac = 0

real	0m30.217s
user	0m0.311s
sys	0m3.228s

But running manually shows the correct return code (97):

/usr/local/bin/sipp -i 0.0.0.0 -p 48663 -mi 0.0.0.0 -mp 41918 -sf /opt/default_with_confpy/uas.xml -recv_timeout 5000 -timeout 30 -r 1 -l 1 -m 2 -log_file /tmp/uas_log_file -screen_file /tmp/uas_screen_file -trace_logs -trace_screen

# echo $?
97

If I add agents['uas'].timeout_error = True to pysipp_conf.py, pysipp successfully catches a 255 error (The same code as running the command manually) and indicates the test failed, but 255 is a bit generic vs 97.

Does anyone have any idea why I'm experiencing this issue? I've looked at the underlying code but can't figure out why its not picking up the 97 error.

Thanks

Allocate random default socket addrs

I realize pysipp isn't supposed to be much more then a command wrapper and launcher but, I do think it would be appreciated if the default pysipp_conf_scen hook actually provisioned all agents with default (and random) socket addresses acquired from the (local) OS.

That would reduce uac -> DUT -> uas testing to simply:

pysipp.scenario(proxyaddr=(<dut_ip_addr>, <dut_port>))()

Provide some doc for pytest usage

The main wiki page is ok to see usage of scenario and uac and uas, but it seems that there is no documentation for integration with pytest (example: auto-discovery of scenario directory, how to override defaults command line value for uas and uac).

pysipp is great work and seems very usable though. Thanks for it.

logdir is not respected in Scenario.defaults

Thanks to @fchareyron for finding this in #19.
It seems we never respect the logdir arg passed into pysipp.walk() or pysipp.scenario() such that it's never set in pysipp.Scenario.defaults. It is however overridden in the underlying agents (by original design) but this is arguably not clear to the user.

In other words:

>>> next(pysipp.walk('./scens/', logdir='/var/tmp'))[1].logdir
'/tmp'

@fchareyron's change to pysipp/__init__.py:96:

- walk(dirpath, autolocalsocks=autolocalsocks, **scenkwargs)
+ walk(dirpath, logdir=logdir, autolocalsocks=autolocalsocks, **scenkwargs)

does resolve this at the Agent level for pysipp.scenario as per:

In [7]: s = pysipp.scenario('./tests/scens/default/', logdir='/var/tmp')

In [8]: s.agents
Out[8]: 
OrderedDict([('uas', <pysipp.agent.UserAgent at 0x7f1b40cc0ed0>),
             ('uac', <pysipp.agent.UserAgent at 0x7f1b40cc0e90>)])

In [9]: s.agents['uac'].logdir
Out[9]: '/var/tmp'

but logdir should really be assigned in Scenario.defaults as well.
We need a test and fix for this.

ValueError: xml script must contain one of 'uac' or 'uas':

I am getting below error if i am trying to execute all my sipp xml files in a directory
Traceback (most recent call last): File "sipp.py", line 5, in <module> scen = pysipp.scenario(dirpath='/home/voiceqa/sipp-3.5.1/AMR_Testing/AMR',proxyaddr=('10.204.66.84', 5080)) File "/usr/local/lib/python3.5/dist-packages/pysipp/__init__.py", line 98, in scenario **scenkwargs) File "/usr/local/lib/python3.5/dist-packages/pysipp/__init__.py", line 72, in walk .format(xml) ValueError: xml script must contain one of 'uac' or 'uas': /home/voiceqa/sipp-3.5.1/AMR_Testing/AMR/AMR_oct_modeset_1.xml

My python code look as below

import pysipp
uas = pysipp.server(srcaddr=('10.204.66.84', 5080))
uac = pysipp.client(destaddr=uas.srcaddr)
scen = pysipp.scenario()
scen = pysipp.scenario(dirpath='/home/voiceqa/sipp-3.5.1/AMR_Testing/AMR',proxyaddr=('10.204.66.84', 5080))

Please help me how to get rid of this problem

Port to py3.7 +

As part of this moving to github actions might be in order (since apparently that's what everyone is doing and I do like msft footing the bill).

Has anyone done any ports already?

If so please please please send us a PR ๐Ÿ˜น

Get pypy CI rolling again!

pypy has been cranky in CI. I don't have time to look at this nor reproduce locally so lets defer this till later!

If and when someone wants this support we can address it then.

Agent timeout tests

Need unit tests to verify the PopenRunner fails correctly when agent(s) go off into the void.
That is, checking that agents are signaled/terminated and that the higher level reporting still operates as expected.

Async support via `trio`

trio recently added native subprocess support which could make for some really fancy stuff for spawing sipp processes and await-ing them before spawning it again. Though a bit hacky could make way for composing multiple simpler scenarios in native async python code.

Thoughts on this @vodik @wdoekes?

Does anyone really dislike the __call__ syntax?

I remember way back when first writing this we had an internal debate about .run() versus __call__() and can't remember why we settled on the latter.

In hindsight, after more years of codezing, I think the .run() is more clear and pythonic maybe?

Does anyone have opinions on this?

destaddr overrides remote_port

If _clientdefaults contains a destaddr, and an agent's _values contains a remote_port, remote_port will get ignored and the destaddr field will be incorrectly used.

Use towncrier for releases?

Seems like we need a more formalized release log if we're going to start moving this project forward. My work in the pytest community points me to use towncrier but I'm open to other options. I'm going to do the first release (#54) manually and then we can look at this down the road for the first 1.0.

xxx_file is not respected in defaults

File names provided by xxxx_file parameter are lost. For example, error_file value is lost and the error file name is always the default one.

In agent.py at line 130, the provided file name contained in attr is ignored. The fix just uses attr if provided.

    for name, attr in self.iter_logfile_items():
        setattr(
            self, name, path.join(
                logdir or self.logdir or tempfile.gettempdir(),
                attr or "{}_{}".format(self.name, name))
            )
    self.enable_tracing()

agent name missing from log file paths

Uhh..

In[5]: s = pysipp.scenario()

In [6]: s.logdir = '/tmp/doggy/'                                                                                       

In [7]: s.cmditems()                                                                                                   
Out[7]:                                                                                                                
[('uas',                                                                                                               
  "'/usr/bin/sipp' -i '[127.0.0.1]' -p '5060' -sn 'uas' -recv_timeout '5000' -r '1' -l '1' -m '1' -calldebug_file '/tmp
/doggy/None_calldebug_file' -message_file '/tmp/doggy/None_message_file' -log_file '/tmp/doggy/None_log_file' -screen_f
ile '/tmp/doggy/None_screen_file' -trace_calldebug -trace_msg -trace_logs -trace_screen "),                            
 ('uac',                                                                                                               
  "'/usr/bin/sipp' '[127.0.0.1]':'5060' -sn 'uac' -recv_timeout '5000' -r '1' -l '1' -m '1' -calldebug_file '/tmp/doggy
/None_calldebug_file' -message_file '/tmp/doggy/None_message_file' -log_file '/tmp/doggy/None_log_file' -screen_file '/
tmp/doggy/None_screen_file' -trace_calldebug -trace_msg -trace_logs -trace_screen ")]

Wtf is this None_log_file stuff?

Follow trio on the proc launchin API front

There's new work in python-trio/trio#1568 that will likely make some of our internals simpler.

The only outstanding concern I had was to do with the AsyncResource.aclos() steps that were possibly being dropped (that we might rely on?). See the issue / PR where I'm pretty I commented.

launch multiple scenarios with a context manager

Ended up using something similar for some FreeSWITCH cluster testing and figured it might as well be part of the pysipp API:

from contextlib import contextmanager

@contextmanager
def multicall(dialers):
    finalizers = []
    for for dialer in dialers:
        finalizers.append(dialer(block=False))

    yield dialers

    for finalize in finalizers:
        finalize()

It basically wraps the async usage from the README.

[pysipp] Scenario - Connection Error: socket already in use

@goodboy

I have trying to use pysipp to the following in order:
sipp_uac_register.xml will send a REGISTER to my Proxy. Contact header is set to port 5061.
sipp_uas_basic.xml will setup a UAS listening on port 5061.
sipp_uac_invite_with_sdp.xml will send a call out to the PSTN to number 2223334444.. which in turn will come back into my system and route to port 5061 on the same SIPP box.

Questions:
How do I change the params in individual sipp agents when using a scenario?
Maybe, I have to use the Async Scenario Launching, as I want to run the Second and Third together. Call from third xml will hit the second xml.

Manually, I can make this scenario work by running these commands:

Register
sipp 10.106.158.31:5060 -sf ~/did-testing/scenarios/sipp_uac_register.xml -trace_msg -inf ~/did-testing/scenarios/register.csv -t t1 -m 1 -trace_err

UAS Client Side:
sipp -sf ~/did-testing/scenarios/sipp_uas_basic.xml -t t1 -trace_err -i 10.106.158.81 -p 5061 -trace_msg

Outbound Call to +12223334444
sipp 10.106.158.75:5060 -sf ~/did-testing/scenarios/sipp_uac_invite_with_sdp.xml -trace_msg -m 1 -trace_err -s +12223334444

Here's my scenario directory. I have a directory called 'call' to use Scenario.
.:
total 8
drwxrwxr-x 2 ec2-user ec2-user 68 Apr 17 19:45 call
-rw-rw-r-- 1 ec2-user ec2-user 148 Apr 14 19:27 register.csv
-rw-rw-r-- 1 ec2-user ec2-user 1180 Apr 14 20:56 sipp_uac_register.xml

./call:
total 16
-rw-rw-r-- 1 ec2-user ec2-user 4600 Apr 14 17:27 sipp_uac_invite_with_sdp.xml
-rw-rw-r-- 1 ec2-user ec2-user 4343 Apr 14 21:24 sipp_uas_basic.xml

I got the REGISTER working with this code:

#!/usr/bin/python3
import pysipp
pysipp.utils.log_to_stderr("DEBUG")
print("helloworld")
sipp_options={
'call_count' : 1,
'info_file' : 'scenarios/register.csv',
'transport' : 't1',
'remote_host' : '10.106.158.31',
'remote_port': '5060',
'trace_message' : True
}

uac = pysipp.client(destaddr=('10.106.158.31',5060),defaults=sipp_options)
uac.local_host='10.106.158.81'
uac.local_port='5060'
uac.scen_file = '/home/ec2-user/did-testing/scenarios/sipp_uac_register.xml'
uac.scen_name = None
uac.info_file='/home/ec2-user/did-testing/scenarios/register.csv'
uac.transport='t1'
uac()

I am trying to get the UAS Client Side / Outbound call working:

#!/usr/bin/python3
import pysipp
#pysipp.utils.log_to_stderr("DEBUG")
print("helloworld")
sipp_options={
'call_count' : 1,
#'info_file' : 'scenarios/register.csv',
'local_host' :'10.106.158.81',
'local_port' :'5060',
'transport' : 't1',
'remote_host' : '10.106.158.31',
'remote_port': '5060',
'trace_message' : True
}
scen = pysipp.scenario(dirpath='/home/ec2-user/did-testing/scenarios/call/',defaults=sipp_options,proxyaddr=('10.106.158.31', 5060))

print(scen.cmditems())
scen() # run uac and uas synchronously to completion

Here's the error I get, both Agents are trying to use 5060.

stderr for 'sipp_uac_invite_with_sdp' @ ('10.106.158.81', '5060')
b"Resolving remote host '10.106.158.81'... Done.\n2020-04-17\t21:35:45.922876\t1587159345.922876: Unable to bind main socket, errno = 98 (Address already in use)\n"

Here's the scen.cmditems():
[('sipp_uas_basic', "'/home/ec2-user/sipp-3.6.0/sipp' -i '10.106.158.81' -p '5060' -mp '49147' -t 't1' -sf '/home/ec2-user/did-testing/scenarios/call/sipp_uas_basic.xml' -recv_timeout '5000' -r '1' -l '1' -m '1' -log_file '/tmp/sipp_uas_basic_log_file' -screen_file '/tmp/sipp_uas_basic_screen_file' -trace_msg -trace_logs -trace_screen '10.106.158.31':'5060'"), ('sipp_uac_invite_with_sdp', "'/home/ec2-user/sipp-3.6.0/sipp' -i '10.106.158.81' -p '5060' -rsa '10.106.158.31':'5060' -mp '42804' -t 't1' -sf '/home/ec2-user/did-testing/scenarios/call/sipp_uac_invite_with_sdp.xml' -recv_timeout '5000' -r '1' -l '1' -m '1' -log_file '/tmp/sipp_uac_invite_with_sdp_log_file' -screen_file '/tmp/sipp_uac_invite_with_sdp_screen_file' -trace_msg -trace_logs -trace_screen '10.106.158.81':'5060'")]

here's the full debug:

[ec2-user@ip-10-106-158-81 scenarios]$ python3 ../pysipp-test.py
helloworld
2020-04-17 21:35:06,110 MainThread [DEBUG] pysipp load.py:52 : No pysipp_conf.py found under '/home/ec2-user/did-testing/scenarios/call'
2020-04-17 21:35:06,114 MainThread [DEBUG] pysipp agent.py:365 : sipp_uas_basic 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True)])
2020-04-17 21:35:06,114 MainThread [DEBUG] pysipp agent.py:365 : sipp_uas_basic 'serverdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {})])
2020-04-17 21:35:06,114 MainThread [DEBUG] pysipp agent.py:365 : sipp_uas_basic 'agent.todict()' contents:
{'bin_path': '/home/ec2-user/sipp-3.6.0/sipp', 'scen_file': '/home/ec2-user/did-testing/scenarios/call/sipp_uas_basic.xml'}
2020-04-17 21:35:06,115 MainThread [DEBUG] pysipp agent.py:368 : sipp_uas_basic merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True), ('bin_path', '/home/ec2-user/sipp-3.6.0/sipp'), ('scen_file', '/home/ec2-user/did-testing/scenarios/call/sipp_uas_basic.xml')])
2020-04-17 21:35:06,115 MainThread [DEBUG] pysipp agent.py:365 : sipp_uac_invite_with_sdp 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True)])
2020-04-17 21:35:06,116 MainThread [DEBUG] pysipp agent.py:365 : sipp_uac_invite_with_sdp 'clientdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {})])
2020-04-17 21:35:06,116 MainThread [DEBUG] pysipp agent.py:365 : sipp_uac_invite_with_sdp 'agent.todict()' contents:
{'bin_path': '/home/ec2-user/sipp-3.6.0/sipp', 'scen_file': '/home/ec2-user/did-testing/scenarios/call/sipp_uac_invite_with_sdp.xml'}
2020-04-17 21:35:06,116 MainThread [DEBUG] pysipp agent.py:368 : sipp_uac_invite_with_sdp merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True), ('bin_path', '/home/ec2-user/sipp-3.6.0/sipp'), ('scen_file', '/home/ec2-user/did-testing/scenarios/call/sipp_uac_invite_with_sdp.xml')])
2020-04-17 21:35:06,117 MainThread [DEBUG] pysipp agent.py:365 : sipp_uas_basic 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True)])
2020-04-17 21:35:06,117 MainThread [DEBUG] pysipp agent.py:365 : sipp_uas_basic 'serverdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {})])
2020-04-17 21:35:06,117 MainThread [DEBUG] pysipp agent.py:365 : sipp_uas_basic 'agent.todict()' contents:
{'bin_path': '/home/ec2-user/sipp-3.6.0/sipp', 'media_port': 38879, 'scen_file': '/home/ec2-user/did-testing/scenarios/call/sipp_uas_basic.xml'}
2020-04-17 21:35:06,117 MainThread [DEBUG] pysipp agent.py:368 : sipp_uas_basic merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True), ('bin_path', '/home/ec2-user/sipp-3.6.0/sipp'), ('media_port', 38879), ('scen_file', '/home/ec2-user/did-testing/scenarios/call/sipp_uas_basic.xml')])
2020-04-17 21:35:06,119 MainThread [DEBUG] pysipp agent.py:365 : sipp_uas_basic 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True)])
2020-04-17 21:35:06,119 MainThread [DEBUG] pysipp agent.py:365 : sipp_uas_basic 'serverdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {})])
2020-04-17 21:35:06,119 MainThread [DEBUG] pysipp agent.py:365 : sipp_uas_basic 'agent.todict()' contents:
{'bin_path': '/home/ec2-user/sipp-3.6.0/sipp', 'media_port': 38879, 'scen_file': '/home/ec2-user/did-testing/scenarios/call/sipp_uas_basic.xml'}
2020-04-17 21:35:06,119 MainThread [DEBUG] pysipp agent.py:368 : sipp_uas_basic merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True), ('bin_path', '/home/ec2-user/sipp-3.6.0/sipp'), ('media_port', 38879), ('scen_file', '/home/ec2-user/did-testing/scenarios/call/sipp_uas_basic.xml')])
2020-04-17 21:35:06,120 MainThread [DEBUG] pysipp agent.py:365 : sipp_uac_invite_with_sdp 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True)])
2020-04-17 21:35:06,120 MainThread [DEBUG] pysipp agent.py:365 : sipp_uac_invite_with_sdp 'clientdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {}), ('destaddr', ('10.106.158.81', '5060')), ('proxyaddr', ('10.106.158.31', 5060))])
2020-04-17 21:35:06,120 MainThread [DEBUG] pysipp agent.py:365 : sipp_uac_invite_with_sdp 'agent.todict()' contents:
{'bin_path': '/home/ec2-user/sipp-3.6.0/sipp', 'media_port': 34516, 'scen_file': '/home/ec2-user/did-testing/scenarios/call/sipp_uac_invite_with_sdp.xml'}
2020-04-17 21:35:06,120 MainThread [DEBUG] pysipp agent.py:368 : sipp_uac_invite_with_sdp merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True), ('destaddr', ('10.106.158.81', '5060')), ('proxyaddr', ('10.106.158.31', 5060)), ('bin_path', '/home/ec2-user/sipp-3.6.0/sipp'), ('media_port', 34516), ('scen_file', '/home/ec2-user/did-testing/scenarios/call/sipp_uac_invite_with_sdp.xml')])
[('sipp_uas_basic', "'/home/ec2-user/sipp-3.6.0/sipp' -i '10.106.158.81' -p '5060' -mp '38879' -t 't1' -sf '/home/ec2-user/did-testing/scenarios/call/sipp_uas_basic.xml' -recv_timeout '5000' -r '1' -l '1' -m '1' -log_file '/tmp/sipp_uas_basic_log_file' -screen_file '/tmp/sipp_uas_basic_screen_file' -trace_msg -trace_logs -trace_screen '10.106.158.31':'5060'"), ('sipp_uac_invite_with_sdp', "'/home/ec2-user/sipp-3.6.0/sipp' -i '10.106.158.81' -p '5060' -rsa '10.106.158.31':'5060' -mp '34516' -t 't1' -sf '/home/ec2-user/did-testing/scenarios/call/sipp_uac_invite_with_sdp.xml' -recv_timeout '5000' -r '1' -l '1' -m '1' -log_file '/tmp/sipp_uac_invite_with_sdp_log_file' -screen_file '/tmp/sipp_uac_invite_with_sdp_screen_file' -trace_msg -trace_logs -trace_screen '10.106.158.81':'5060'")]
2020-04-17 21:35:06,121 MainThread [DEBUG] pysipp agent.py:365 : sipp_uas_basic 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True)])
2020-04-17 21:35:06,122 MainThread [DEBUG] pysipp agent.py:365 : sipp_uas_basic 'serverdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {})])
2020-04-17 21:35:06,122 MainThread [DEBUG] pysipp agent.py:365 : sipp_uas_basic 'agent.todict()' contents:
{'bin_path': '/home/ec2-user/sipp-3.6.0/sipp', 'media_port': 38879, 'scen_file': '/home/ec2-user/did-testing/scenarios/call/sipp_uas_basic.xml'}
2020-04-17 21:35:06,122 MainThread [DEBUG] pysipp agent.py:368 : sipp_uas_basic merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True), ('bin_path', '/home/ec2-user/sipp-3.6.0/sipp'), ('media_port', 38879), ('scen_file', '/home/ec2-user/did-testing/scenarios/call/sipp_uas_basic.xml')])
2020-04-17 21:35:06,123 MainThread [DEBUG] pysipp agent.py:365 : sipp_uac_invite_with_sdp 'defaults' contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True)])
2020-04-17 21:35:06,123 MainThread [DEBUG] pysipp agent.py:365 : sipp_uac_invite_with_sdp 'clientdefaults' contents:
OrderedDict([('key_vals', {}), ('global_vars', {}), ('destaddr', ('10.106.158.81', '5060')), ('proxyaddr', ('10.106.158.31', 5060))])
2020-04-17 21:35:06,123 MainThread [DEBUG] pysipp agent.py:365 : sipp_uac_invite_with_sdp 'agent.todict()' contents:
{'bin_path': '/home/ec2-user/sipp-3.6.0/sipp', 'media_port': 34516, 'scen_file': '/home/ec2-user/did-testing/scenarios/call/sipp_uac_invite_with_sdp.xml'}
2020-04-17 21:35:06,123 MainThread [DEBUG] pysipp agent.py:368 : sipp_uac_invite_with_sdp merged contents:
OrderedDict([('recv_timeout', 5000), ('call_count', 1), ('rate', 1), ('limit', 1), ('logdir', '/tmp'), ('key_vals', {}), ('global_vars', {}), ('local_host', '10.106.158.81'), ('local_port', '5060'), ('transport', 't1'), ('remote_host', '10.106.158.31'), ('remote_port', '5060'), ('trace_message', True), ('destaddr', ('10.106.158.81', '5060')), ('proxyaddr', ('10.106.158.31', 5060)), ('bin_path', '/home/ec2-user/sipp-3.6.0/sipp'), ('media_port', 34516), ('scen_file', '/home/ec2-user/did-testing/scenarios/call/sipp_uac_invite_with_sdp.xml')])
2020-04-17 21:35:06,123 MainThread [DEBUG] pysipp launch.py:63 : launching cmd:
"'/home/ec2-user/sipp-3.6.0/sipp' -i '10.106.158.81' -p '5060' -mp '38879' -t 't1' -sf '/home/ec2-user/did-testing/scenarios/call/sipp_uas_basic.xml' -recv_timeout '5000' -r '1' -l '1' -m '1' -log_file '/tmp/sipp_uas_basic_log_file' -screen_file '/tmp/sipp_uas_basic_screen_file' -trace_msg -trace_logs -trace_screen '10.106.158.31':'5060'"

2020-04-17 21:35:06,125 MainThread [DEBUG] pysipp launch.py:71 : registering fd '5' for pid '20158'
2020-04-17 21:35:06,129 MainThread [DEBUG] pysipp launch.py:63 : launching cmd:
"'/home/ec2-user/sipp-3.6.0/sipp' -i '10.106.158.81' -p '5060' -rsa '10.106.158.31':'5060' -mp '34516' -t 't1' -sf '/home/ec2-user/did-testing/scenarios/call/sipp_uac_invite_with_sdp.xml' -recv_timeout '5000' -r '1' -l '1' -m '1' -log_file '/tmp/sipp_uac_invite_with_sdp_log_file' -screen_file '/tmp/sipp_uac_invite_with_sdp_screen_file' -trace_msg -trace_logs -trace_screen '10.106.158.81':'5060'"

2020-04-17 21:35:06,132 MainThread [DEBUG] pysipp launch.py:71 : registering fd '6' for pid '20159'
2020-04-17 21:35:06,136 Thread-1 [DEBUG] pysipp launch.py:86 : started waiter for procs OrderedDict([(5, <subprocess.Popen object at 0x7ff595460f10>), (6, <subprocess.Popen object at 0x7ff59541c350>)])
2020-04-17 21:35:06,136 Thread-1 [DEBUG] pysipp launch.py:92 : received hangup for pairs '[(6, 16)]'
2020-04-17 21:35:06,137 Thread-1 [DEBUG] pysipp launch.py:97 : collecting streams for <subprocess.Popen object at 0x7ff59541c350>
2020-04-17 21:35:06,137 Thread-1 [WARNING] pysipp launch.py:150 : sent signal '10' to cmd ''/home/ec2-user/sipp-3.6.0/sipp' -i '10.106.158.81' -p '5060' -mp '38879' -t 't1' -sf '/home/ec2-user/did-testing/scenarios/call/sipp_uas_basic.xml' -recv_timeout '5000' -r '1' -l '1' -m '1' -log_file '/tmp/sipp_uas_basic_log_file' -screen_file '/tmp/sipp_uas_basic_screen_file' -trace_msg -trace_logs -trace_screen '10.106.158.31':'5060'' with pid '20158'
2020-04-17 21:35:06,138 Thread-1 [DEBUG] pysipp launch.py:92 : received hangup for pairs '[(5, 16)]'
2020-04-17 21:35:06,138 Thread-1 [DEBUG] pysipp launch.py:97 : collecting streams for <subprocess.Popen object at 0x7ff595460f10>
2020-04-17 21:35:06,138 Thread-1 [DEBUG] pysipp launch.py:103 : terminating waiter thread
2020-04-17 21:35:06,138 MainThread [WARNING] pysipp report.py:52 : stderr for 'sipp_uas_basic' @ ('10.106.158.81', '5060')
b"Resolving remote host '10.106.158.31'... Done.\n"

2020-04-17 21:35:06,149 MainThread [WARNING] pysipp report.py:75 : 'screen_file' contents for 'sipp_uas_basic' @ ('10.106.158.81', '5060'):
------------------------------ Scenario Screen -------- [1-9]: Change Screen --
Timestamp: Fri Apr 17 21:35:06 2020

Port Total-time Total-calls Transport
5060 0.00 s 0 TCP

0 new calls during 0.000 s period 0 ms scheduler resolution
0 calls Peak was 0 calls, after 0 s
0 Running, 2 Paused, 0 Woken up
0 dead call msg (discarded)
0 open sockets

                             Messages  Retrans   Timeout   Unexpected-Msg

----------> INVITE 0 0 0 0
<---------- 180 0 0
<---------- 200 0 0 0
----------> ACK E-RTD1 0 0 0 0

----------> BYE 0 0 0 0
<---------- 200 0 0
[ 4000ms] Pause 0 0
------- Waiting for active calls to end. Press [q] again to force exit. -------

----------------------------- Statistics Screen ------- [1-9]: Change Screen --
Start Time | 2020-04-17 21:35:06.128652 1587159306.128652
Last Reset Time | 2020-04-17 21:35:06.137408 1587159306.137408
Current Time | 2020-04-17 21:35:06.137468 1587159306.137468
-------------------------+---------------------------+--------------------------
Counter Name | Periodic value | Cumulative value
-------------------------+---------------------------+--------------------------
Elapsed Time | 00:00:00:000000 | 00:00:00:008000
Call Rate | 0.000 cps | 0.000 cps
-------------------------+---------------------------+--------------------------
Incoming call created | 0 | 0
OutGoing call created | 0 | 0
Total Call created | | 0
Current Call | 0 |
-------------------------+---------------------------+--------------------------
Successful call | 0 | 0
Failed call | 0 | 0
-------------------------+---------------------------+--------------------------
Response Time 1 | 00:00:00:000000 | 00:00:00:000000
Call Length | 00:00:00:000000 | 00:00:00:000000
------- Waiting for active calls to end. Press [q] again to force exit. -------

---------------------------- Repartition Screen ------- [1-9]: Change Screen --
Average Response Time Repartition 1
0 ms <= n < 10 ms : 0
10 ms <= n < 20 ms : 0
20 ms <= n < 30 ms : 0
30 ms <= n < 40 ms : 0
40 ms <= n < 50 ms : 0
50 ms <= n < 100 ms : 0
100 ms <= n < 150 ms : 0
150 ms <= n < 200 ms : 0
n >= 200 ms : 0
Average Call Length Repartition
0 ms <= n < 10 ms : 0
10 ms <= n < 50 ms : 0
50 ms <= n < 100 ms : 0
100 ms <= n < 500 ms : 0
500 ms <= n < 1000 ms : 0
1000 ms <= n < 5000 ms : 0
5000 ms <= n < 10000 ms : 0
n >= 10000 ms : 0
------- Waiting for active calls to end. Press [q] again to force exit. -------

2020-04-17 21:35:06,159 MainThread [WARNING] pysipp report.py:52 : stderr for 'sipp_uac_invite_with_sdp' @ ('10.106.158.81', '5060')
b"Resolving remote host '10.106.158.81'... Done.\n2020-04-17\t21:35:06.135102\t1587159306.135102: Unable to bind main socket, errno = 98 (Address already in use)\n"

2020-04-17 21:35:06,169 MainThread [WARNING] pysipp report.py:75 : 'screen_file' contents for 'sipp_uac_invite_with_sdp' @ ('10.106.158.81', '5060'):

Traceback (most recent call last):
File "../pysipp-test.py", line 18, in
scen() # run uac and uas synchronously to completion
File "/usr/local/lib/python3.7/site-packages/pysipp/agent.py", line 417, in call
raise_exc=raise_exc, **kwargs
File "/usr/local/lib/python3.7/site-packages/pluggy/hooks.py", line 289, in call
return self._hookexec(self, self.get_hookimpls(), kwargs)
File "/usr/local/lib/python3.7/site-packages/pluggy/manager.py", line 68, in _hookexec
return self._inner_hookexec(hook, methods, kwargs)
File "/usr/local/lib/python3.7/site-packages/pluggy/manager.py", line 62, in
firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
File "/usr/local/lib/python3.7/site-packages/pluggy/callers.py", line 208, in _multicall
return outcome.get_result()
File "/usr/local/lib/python3.7/site-packages/pluggy/callers.py", line 80, in get_result
raise ex[1].with_traceback(ex[2])
File "/usr/local/lib/python3.7/site-packages/pluggy/callers.py", line 187, in _multicall
res = hook_impl.function(*args)
File "/usr/local/lib/python3.7/site-packages/pysipp/init.py", line 250, in pysipp_run_protocol
finalize(cmds2procs, raise_exc=raise_exc)
File "/usr/local/lib/python3.7/site-packages/pysipp/init.py", line 228, in finalize
raise SIPpFailure(msg)
pysipp.SIPpFailure: Some agents failed
'sipp_uas_basic' with exit code 0 -> All calls were successful
'sipp_uac_invite_with_sdp' with exit code 254 -> Connection Error: socket already in use

python3 support

Tried to run it on python35, got

Traceback (most recent call last):
  File "/root/.virtualenv/pylab3/lib/python3.5/site-packages/_pytest/config.py", line 385, in import_plugin
    __import__(importspec)
  File "/root/mirror/sangoma/sipp/__init__.py", line 1, in <module>
    from sangoma.sipp.plugin import *
  File "/root/mirror/sangoma/sipp/plugin.py", line 11, in <module>
    import pysipp
  File "/root/.virtualenv/pylab3/src/pysipp/pysipp/__init__.py", line 23, in <module>
    from load import iter_scen_dirs
ImportError: No module named 'load'

set -t t1 (tcp flag)

Hello,

Please can you tell me how I can pass the -t parameter to SIPP?

Thanks,

Daniel

pysipp release

Is there any plan to make a pysipp release in a short time?

Can't import pysipp after install

I just installed pysipp for the first time on windows 10 (Python2.7) using:
pip install git+git://github.com/SIPp/pysipp.git
And after it installed, I tried your example script and got an error. Basically opening a python prompt and typing "import pysipp" generates the following error:

C:\pyfiles>python
Python 2.7.11 (v2.7.11:6d1b6a68f775, Dec 5 2015, 20:32:19) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.

import pysipp
Traceback (most recent call last):
File "", line 1, in
File "C:\Python27\lib\site-packages\pysipp_init_.py", line 23, in
from . import launch, report, plugin, netplug, agent
File "C:\Python27\lib\site-packages\pysipp\launch.py", line 24, in
class PopenRunner(object):
File "C:\Python27\lib\site-packages\pysipp\launch.py", line 35, in PopenRunner
poller=select.epoll,
AttributeError: 'module' object has no attribute 'epoll'

Any ideas how to fix this?
Thanks!

Support for OS X

Need to change use of select.epoll (in launch.py) with select.select() (I think), because epoll is only supported on linux.

Add a requests-like interface to pysipp.agent.Scenario

Currently the scenario object supports an interface where you can immediately apply user agent instance variables (which eventually translate to cmd paramaters) via the MultiAccess type with syntax:

def pysipp_conf_scen(scen):
    scen.agents.sockaddr = ('10.10.8.1',  5060)
    scen.clients.timeout = 10000

The agents attr here references the entire scenario agent set and applies the named variable for all contained agents immediately in a loop. Getting the same attribute will result in a returned dictionary who's keys are the agent names and values are the accessed value per agent. This __getattr__/__setattr__ is not only asymmetric but unintuitive.

@vodik has suggested something similar to the requests.session interface.

I propose the following:

  • Scenario.agents, clients, servers simply become dict objects which can contain optional parameter (attribute) overrides. The keys can be any attribute of a pysipp.agent.UserAgent and values act as defaults.
    • clients and servers values (which are mutex) will override agents values and attributes set directly on a UserAgent will always take the highest precedence.
  • pysipp.agent.Scenario will get a prepare method similar to prepared-requests. This method takes in a single UserAgent and returns a copy of that agent now modified as per the params overrides from above such that can be used in place of the original. Scenario.__call__ will of course call prepare on each contained agent before invoking the run protocol hook with the full agent set.
  • the default pysipp_run_protocol hook will be changed to take in an agents sequence argument instead of a scen arg and accordingly the runner arg must be explicitly provided by the caller.
  • the launch.PopenRunner will be modified to remove it's agents arg to __init__ and instead take in a cmditems arg to __call__ such that the entire object becomes 'agent' agnostic and is only concerned with running commands.

Passing additional arguments to SIPP.

Hi, thanks for the great software! I have one question though, could not find the answer in the docs or code:
How can I pass arguments that are not listed in pysipp.command.sipp_spec, like -min_rtp_port, to SIPP executable?

Error logging output is easy to miss.. we should repair the formatting output.

Hello there,

First of all, thanks for a great framework. I want to test a call like a client from a softphone call. I tried unsuccesfully with

import pysipp

pysipp.client(
    destaddr=("mydomain.com", 5060), 
    auth_username="myuser",
    auth_password="mypassword",
    extension="999"
)()

Those params are what I need to make a call, I'm getting this log, what am I doing wrong?

gdp@gdp:~/Downloads/ddossip$ python3 main.py 
stderr for 'uac' @ None
b'Resolving remote host \'mydomain.com\'... Done.\n2022-05-26\t14:02:34.792872\t1653591754.792872: Aborting call on unexpected message for Call-Id \'[email protected]\': while expecting \'180\' (index 2), received \'SIP/2.0 407 Proxy Authentication Required\r\nVia: SIP/2.0/UDP 192.168.1.43:5060;rport=32607;received=181.67.169.200;branch=z9hG4bK-84371-1-0\r\nFrom: sipp <sip:[email protected]:5060>;tag=84371SIPpTag001\r\nTo: service <sip:[email protected]:5060>;tag=jcQ7pFe9QNvZD\r\nCall-ID: [email protected]\r\nCSeq: 1 INVITE\r\nUser-Agent: ExampleAgent\r\nAccept: application/sdp\r\nAllow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, PRACK, NOTIFY, PUBLISH, SUBSCRIBE\r\nSupported: precondition, 100rel, path, replaces\r\nAllow-Events: talk, hold, conference, presence, as-feature-event, dialog, line-seize, call-info, sla, include-session-description, presence.winfo, message-summary, refer\r\nProxy-Authenticate: Digest realm="192.168.1.43", nonce="43d1660c-1a8f-40f2-b2ff-ffed14096255", algorithm=MD5, qop="auth"\r\nContent-Length: 0\r\n\r\n\'\n'

'screen_file' contents for 'uac' @ None:
------------------------------ Scenario Screen -------- [1-9]: Change Screen --
  Call rate (length)   Port   Total-time  Total-calls  Remote-host
  1.0(0 ms)/1.000s   5060       1.11 s            1  34.236.226.85:5060(UDP)

  Call limit 1 hit, 0.0 s period          0 ms scheduler resolution            
  0 calls (limit 1)                       Peak was 1 calls, after 1 s
  0 Running, 4 Paused, 4 Woken up
  0 dead call msg (discarded)             0 out-of-call msg (discarded)
  0 open sockets                          0/0/0 UDP errors (send/recv/cong)

                                 Messages  Retrans   Timeout   Unexpected-Msg
0 :      INVITE ---------->         1         0         0                      
1 :         100 <----------         1         0         0         0            
2 :         180 <----------         0         0         0         1            
3 :         183 <----------         0         0         0         0            
4 :         200 <----------  E-RTD1 0         0         0         0            
5 :         ACK ---------->         0         0                                
6 :       Pause [      0ms]         0                             0        
7 :         BYE ---------->         0         0         0                      
8 :         200 <----------         0         0         0         0            

Last Error: Aborting call on unexpected message for Call-Id '1-84371@192...
------- Waiting for active calls to end. Press [q] again to force exit. -------
----------------------------- Statistics Screen ------- [1-9]: Change Screen --
  Start Time             | 2022-05-26   14:02:33.676882 1653591753.676882         
  Last Reset Time        | 2022-05-26   14:02:34.792967 1653591754.792967         
  Current Time           | 2022-05-26   14:02:34.793001 1653591754.793001         
-------------------------+---------------------------+--------------------------
  Counter Name           | Periodic value            | Cumulative value
-------------------------+---------------------------+--------------------------
  Elapsed Time           | 00:00:00:000000           | 00:00:00:000000          
  Call Rate              |    0.000 cps              |    0.896 cps             
-------------------------+---------------------------+--------------------------
  Incoming calls created |        0                  |        0                 
  Outgoing calls created |        0                  |        1                 
  Total Calls created    |                           |        1                 
  Current Calls          |        0                  |                          
-------------------------+---------------------------+--------------------------
  Successful call        |        0                  |        0                 
  Failed call            |        0                  |        1                 
-------------------------+---------------------------+--------------------------
  Response Time 1        | 00:00:00:000000           | 00:00:00:000000          
  Call Length            | 00:00:00:000000           | 00:00:00:000000          
Last Error: Aborting call on unexpected message for Call-Id '1-84371@192...
------- Waiting for active calls to end. Press [q] again to force exit. -------
---------------------------- Repartition Screen ------- [1-9]: Change Screen --
  Average Response Time Repartition 1                                          
             0 ms <= n <         10 ms :          0
            10 ms <= n <         20 ms :          0
            20 ms <= n <         30 ms :          0
            30 ms <= n <         40 ms :          0
            40 ms <= n <         50 ms :          0
            50 ms <= n <        100 ms :          0
           100 ms <= n <        150 ms :          0
           150 ms <= n <        200 ms :          0
                   n >=        200 ms :          0
  Average Call Length Repartition                                              
             0 ms <= n <         10 ms :          0
            10 ms <= n <         50 ms :          0
            50 ms <= n <        100 ms :          0
           100 ms <= n <        500 ms :          1
           500 ms <= n <       1000 ms :          0
          1000 ms <= n <       5000 ms :          0
          5000 ms <= n <      10000 ms :          0
                   n >=      10000 ms :          0
Last Error: Aborting call on unexpected message for Call-Id '1-84371@192...
------- Waiting for active calls to end. Press [q] again to force exit. -------

Traceback (most recent call last):
  File "/home/gdp/Downloads/ddossip/main.py", line 3, in <module>
    pysipp.client(
  File "/home/gdp/.local/lib/python3.10/site-packages/pysipp/agent.py", line 72, in __call__
    return plugin.mng.hook.pysipp_run_protocol(
  File "/home/gdp/.local/lib/python3.10/site-packages/pluggy/hooks.py", line 289, in __call__
    return self._hookexec(self, self.get_hookimpls(), kwargs)
  File "/home/gdp/.local/lib/python3.10/site-packages/pluggy/manager.py", line 68, in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
  File "/home/gdp/.local/lib/python3.10/site-packages/pluggy/manager.py", line 59, in <lambda>
    self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
  File "/home/gdp/.local/lib/python3.10/site-packages/pluggy/callers.py", line 208, in _multicall
    return outcome.get_result()
  File "/home/gdp/.local/lib/python3.10/site-packages/pluggy/callers.py", line 80, in get_result
    raise ex[1].with_traceback(ex[2])
  File "/home/gdp/.local/lib/python3.10/site-packages/pluggy/callers.py", line 187, in _multicall
    res = hook_impl.function(*args)
  File "/home/gdp/.local/lib/python3.10/site-packages/pysipp/__init__.py", line 250, in pysipp_run_protocol
    finalize(cmds2procs, raise_exc=raise_exc)
  File "/home/gdp/.local/lib/python3.10/site-packages/pysipp/__init__.py", line 228, in finalize
    raise SIPpFailure(msg)
pysipp.SIPpFailure: Some agents failed
'uac' with exit code 1 -> At least one call failed

Some modifications

Hi

I join a patch file including some needed modifications to use pysipp properly in my software.

In command.py, some missing SIPp parameters.
In agent.py and init.py, some modifications to handle properly the log dir and to generate error log file.
In report.py, some modifications to avoid seldom exception cases. For any reason, proc.streams.stderr doesn't exist when used.

I hope it's useful enough to be included in the product.
Regards
Frederic

pysipp.patch.zip

Warn about non-hook objects in pysipp_conf.py files

There should be a validation step which warns about any python object (function or other) inside a pysipp_conf.py file which isn't found registered with the plugin manager. The plugin.mng.is_registered() meth can be used for this purpose. This should help with catching misnamed hook functions.

PS I don't think we want to actually prevent the user from defining their own custom objects hence my suggestion for a simple warning.

proxyaddr ignored

When dirpath and proxyaddr are set, the last is ignored because of its indentation.

Error "Missing remote host parameter. This scenario requires it.\n' "

I am encountering below error when i am trying to run sipp scenario file through pysipp

root@voiceqa-desktop:/opt/test# python3 sipp.py ('10.204.66.84', 5080) stderr for 'uac_AMR_BW' @ ('0.0.0.0', 34607) b'2018-10-08\t16:31:39.337407\t1538976699.337407: Missing remote host parameter. This scenario requires it.\n 'screen_file' contents for 'uac_AMR_BW' @ ('0.0.0.0', 34607): Traceback (most recent call last): File "sipp.py", line 8, in <module> scen() File "/usr/local/lib/python3.5/dist-packages/pysipp/agent.py", line 413, in __call__ raise_exc=raise_exc, **kwargs File "/usr/local/lib/python3.5/dist-packages/pluggy.py", line 724, in __call__ return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs) File "/usr/local/lib/python3.5/dist-packages/pluggy.py", line 338, in _hookexec return self._inner_hookexec(hook, methods, kwargs) File "/usr/local/lib/python3.5/dist-packages/pluggy.py", line 333, in <lambda> _MultiCall(methods, kwargs, hook.spec_opts).execute() File "/usr/local/lib/python3.5/dist-packages/pluggy.py", line 596, in execute res = hook_impl.function(*args) File "/usr/local/lib/python3.5/dist-packages/pysipp/__init__.py", line 250, in pysipp_run_protocol finalize(cmds2procs, raise_exc=raise_exc) File "/usr/local/lib/python3.5/dist-packages/pysipp/__init__.py", line 228, in finalize raise SIPpFailure(msg) pysipp.SIPpFailure: Some agents failed 'uac_AMR_BW' with exit code 255 -> Command or syntax error: check stderr output

My Directory has only one scenario file

`root@voiceqa-desktop:/opt/test# ls /home/voiceqa/sipp-3.5.1/AMR_Testing/AMR-WB/

               uac_40sec_harvard.amr  uac_AMR_BW.xml  uac_Harvard_AMR.amr`

My python script looks as below

import pysipp uas = pysipp.server(srcaddr=('10.204.66.84', 5080)) print(uas.srcaddr) uac = pysipp.client(destaddr=uas.srcaddr) #scen = pysipp.scenario() scen = pysipp.scenario(dirpath='/home/voiceqa/sipp-3.5.1/AMR_Testing/AMR-WB',proxyaddr=('10.204.66.84', 5080)) #print(scen.cmditems()) scen() pysipp.log_to_stderr('DEBUG')

Kindly let me know how to fix this

Thanks
Praveen

`FileNotFoundError` raised when `sipp` binanry not found

raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: '-sn': '-sn'


UPDATE (by @goodboy)

The real issue here is not loading a more explicit error when the sipp binary can't be found in the environment.

49b50a9 contains a fix for this but we still need a test to match.

`pysipp.server()` accepts `destaddr` as a keyword argument

pysipp.server() and pysipp.client() appear to be implemented identically, the only exceptions being their respective default scenario name and the fact that pysipp.server() is not supposed to accept a destaddr keyword argument. However, the guard inside the function checks for dstaddr (without the "e"), which I'd assume to be a typo. Since server and client can be used interchangeably, I don't think this has functional implications, though.

Add a useful agent.UserAgent.__repr__()

For debugging purposes, something along the lines of the following will be useful:

>>> sipp_scenario.agents    # lets see the effective arguments we're use to build commands from:
... [u'uac': Agent(timeout=1000,
                   global_vars={u'foobar': u'Hello World',
                                u'baz': u'All hail pysipp'},
                   proxy=('vortex.qa.sangoma.local', 5060))
     u'uac': Agent(...)]

Thanks to @vodik for the suggestion.

how to keep uas running without an infinite loop ?

when launching UAS with a scen file, the process stops after the it's first iteration.
when launching the exact same scen file via CLI, it process keeps running until manuel interuption.

is there any other option to keep the UAS scene running other then creating an infinite loop (while True:), which starts a new process after every iteration ?

"how to" get access to report.py ?

Hi,
when executing a test, I'd like to get back the result of the call. it looks like report.py can do this but I could not figure out how to use it.
can anybody give some hints ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.