Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jchavanton/voip_patrol
VoIP signaling and media test automation
https://github.com/jchavanton/voip_patrol
c sip speech-quality test-automation voip
Last synced: about 18 hours ago
JSON representation
VoIP signaling and media test automation
- Host: GitHub
- URL: https://github.com/jchavanton/voip_patrol
- Owner: jchavanton
- Created: 2016-08-31T10:42:48.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2024-11-28T21:13:53.000Z (2 months ago)
- Last Synced: 2025-01-25T17:07:19.316Z (8 days ago)
- Topics: c, sip, speech-quality, test-automation, voip
- Language: C++
- Homepage:
- Size: 2.68 MB
- Stars: 117
- Watchers: 18
- Forks: 34
- Open Issues: 12
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
[![Docker Pulls](https://img.shields.io/docker/pulls/jchavanton/voip_patrol.svg)](https://hub.docker.com/r/jchavanton/voip_patrol/)
# VoIP Patrol
![GitHub Logo](VP_Logo_1200px-11th_Airborne_Division.patch_small2.jpg)## VoIP signaling and media test automaton
Designed to automate end2end and or integration tests.VoIP patrol will follow a scenario in XML format and will output results in JSON.
Each line in the output file is a separate JSON structure, note that the entire file is not a valid JSON file,
this is because VoIP patrol will output results as they become available.It is possible to test many scenarios that are not easy to test manually like a re-invite with a new codec.
### Docker quick start
[quick start with docker](QUICK_START.md)### Linux Debian building from sources
[see commands in Dockerfile](docker/Dockerfile)### Load test example
[load test example](load_test/LOAD_TEST.md)### run
```
./voip_patrol --help
```### Example: making a test call
```xml
```
### Sample JSON output
```json
{
"2": {
"label": "us-east-va",
"start": "17-07-2018 00:00:05",
"end": "17-07-2018 00:00:24",
"action": "call",
"from": "15147371787",
"to": "12012665228",
"result": "PASS",
"expected_cause_code": 200,
"cause_code": 200,
"reason": "Normal call clearing",
"callid": "7iYDFukJr-9BOLOmWg.7fZyHZeZUAwao",
"transport": "TLS",
"peer_socket": "34.226.136.32:5061",
"duration": 16,
"expected_duration": 0,
"max_duration": 20,
"hangup_duration": 16,
"rtp_stats_0": {
"rtt": 0,
"remote_rtp_socket": "10.250.7.88:4028",
"codec_name": "PCMU",
"clock_rate": "8000",
"Tx": {
"jitter_avg": 0,
"jitter_max": 0,
"pkt": 816,
"kbytes": 127,
"loss": 0,
"discard": 0,
"mos_lq": 4.5
},
"Rx": {
"jitter_avg": 0,
"jitter_max": 0,
"pkt": 813,
"kbytes": 127,
"loss": 0,
"discard": 0,
"mos_lq": 4.5
}
}
}
}
```### Example: starting a TLS server
```bash
./voip_patrol \
--port 5060 \ # TLS port 5061 +1
--conf "xml/tls_server.xml" \
--tls-calist "tls/ca_list.pem" \
--tls-privkey "tls/key.pem" \
--tls-cert "tls/certificate.pem" \
--tls-verify-server \
``````xml
```
### Example: accepting calls and checking for specific header
```xml
```
### Example: accepting calls and checking for specific header with exact match or regular expression and no match on other
```xml
```
### Example: accepting calls and searching the message with a regular expression
```xml
```
### Example: making tests calls with wait_until
Scenario execution is sequential and non-blocking.
We can use “wait” command with previously set “wait_until” params
to control parallel execution.```
Call States
NULL : Before INVITE is sent or received
CALLING : After INVITE is sent
INCOMING : After INVITE is received.
EARLY : After response with To tag.
CONNECTING : After 2xx is sent/received.
CONFIRMED : After ACK is sent/received.
DISCONNECTED
```
```xml
```
### Example: testing registration
```xml
```
### Example: re-invite with new codec
```xml
```
### Example: Overwriting local contact header
```xml
```
### Example: WAIT action
#### wait forever:
```xml```
#### wait until you receive a certain amount of calls
```xml```
#### wait 5 seconds or one call
```xml```
### Sample JSON output RTP stats report with multiples sessions
#### one block is generated everytime a session is created
```json
{
"rtp_stats_0": {
"rtt": 0,
"remote_rtp_socket": "10.250.7.88:4028",
"codec_name": "PCMA",
"clock_rate": "8000",
"Tx": {
"jitter_avg": 0,
"jitter_max": 0,
"pkt": 105,
"kbytes": 16,
"loss": 0,
"discard": 0,
"mos_lq": 4.5
},
"Rx": {
"jitter_avg": 0,
"jitter_max": 0,
"pkt": 104,
"kbytes": 16,
"loss": 0,
"discard": 0,
"mos_lq": 4.5
}
},
"rtp_stats_1": {
"rtt": 0,
"remote_rtp_socket": "10.250.7.89:40230",
"codec_name": "PCMU",
"clock_rate": "8000",
"Tx": {
"jitter_avg": 0,
"jitter_max": 0,
"pkt": 501,
"kbytes": 78,
"loss": 0,
"discard": 0,
"mos_lq": 4.5
},
"Rx": {
"jitter_avg": 0,
"jitter_max": 0,
"pkt": 501,
"kbytes": 78,
"loss": 0,
"discard": 0,
"mos_lq": 4.5
}
}
}
```
### Example: email reporting
```xml
```
### accept command parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| ring_duration | int | ringing duration in seconds |
| early_media | bool | if "true" 183 with SDP and early media is used |
| timer | string | control SIP session timers, possible values are : inactive, optional, required or always |
| code | int | SIP cause code to return must be >100 and <700 |
| account | string | Account will be used if it matches the user part of an incoming call RURI or "default" will catch all |
| response_delay | int | ms delay before reponse is sent, useful to test timeouts and race conditions |
| call_count | int | The amount of calls to receive to consider the command completed, default -1 (considered completed) |
| transport | string | Force a specific transport for all messages on accepted calls, default to all transport available |
| re_invite_interval | int | Interval in seconds at which a re-invite with SDP will be sent |
| rtp_stats | bool | if "true" the json report will include a report on RTP transmission |
| srtp | string | Comma-separated values of the following "sdes" - add SDES support, "dtls" - add DTLS-SRTP support, "force" - make SRTP mandatory |
| hangup | int | call duration in second before hangup |
| label | string | test description or label |
| record | bool | if "true" the call will be recorded once connected in /voice_files |
| record_early | bool | if "true" the call will be recorded when early media starts in /voice_files. If call is answered after, recording will continue in the same file |### call command parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| timer | string | control SIP session timers, possible values are : inactive, optional, required or always |
| proxy | string | ip/hostname of a proxy where to send the call |
| caller | string | From header user@host, only used if from it not specified |
| from | string | From header complete "\"Display Name\" " |
| callee | string | request URI user@host (also used in the To header unless to_uri is specified) |
| to_uri | string | used@host part of the URI in the To header |
| transport | string | force a specific transport |
| re_invite_interval | int | Interval in seconds at which a re-invite with SDP will be sent |
| rtp_stats | bool | if "true" the json report will include a report on RTP transmission |
| srtp | string | Comma-separated values of the following "sdes" - add SDES support, "dtls" - add DTLS-SRTP support, "force" - make SRTP mandatory. Note, if you don't specify "force", call would be made with plain RTP. If you specify both "sdes" and "dtls", DTLS-SRTP would be used regardless of order. |
| late_start | bool | if "true" no SDP will be included in the INVITE and will result in a late offer in 200 OK/ACK |
| record | bool | if "true" the call will be recorded once connected in /voice_files |
| record_early | bool | if "true" the call will be recorded when early media starts in /voice_files. If call is answered after, recording will continue in the same file |
| force_contact | string | local contact header will be overwritten by the given string |
| max_ringing_duration | int | max ringing duration in seconds before cancel, default 60 |
| hangup | int | call duration in second before hangup |
| repeat | int | do this call multiple times |
| username | string | authentication username, account name, From/To/Contact header user part |
| password | string | authentication password |
| label | string | test description or label |### register command parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| proxy | string | ip/hostname of a proxy where to send the register |
| username | string | authentication username, account name, From/To/Contact header user part |
| password | string | authentication password |
| account | string | if not specified username is used, this is the the account name and From/To/Contact header user part |
| registrar | string | SIP UAS handling registration where the messages will be sent |
| transport | string | force a specific transport |
| unregister | bool | unregister the account |
| reg_id | int | if present outbound and other related parameters will be added see RFC5626 |
| instance_id | int | same as reg_id, if not present, it will be generated automatically |
| rewrite_contact | bool | default true, detect public IP when registering and rewrite the contact header |
| srtp | string | Comma-separated values of the following "sdes" - add SDES support, "dtls" - add DTLS-SRTP support, "force" - make SRTP mandatory. Used for incoming calls to this account |
| account | string | if not specified username is used, this is the the account name and From/To/Contact header user part |
| registrar | string | SIP UAS handling registration where the messages will be sent |
| transport | string | force a specific transport |
| unregister | bool | unregister the account |
| reg_id | int | if present outbound and other related parameters will be added see RFC5626 |
| instance_id | int | same as reg_id, if not present, it will be generated automatically |
| rewrite_contact | bool | default true, detect public IP when registering and rewrite the contact header |
| srtp | string | Comma-separated values of the following "sdes" - add SDES support, "dtls" - add DTLS-SRTP support, "force" - make SRTP mandatory. Used for incoming calls to this account |### message command parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| from | string | From header complete "\"Display Name\" " |
| to_uri | string | used@host part of the URI in the To header |
| transport | string | force a specific transport |
| username | string | authentication username, account name, From/To/Contact header user part |
| password | string | authentication password |
| label | string | test description or label |### Example: sending a message
```xml
```
### accept_message command parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| account | string | Account will be used if it matches the user part of an incoming message RURI or "default" will catch all |
| message_count | int | The amount of messages to receive to consider the command completed, default -1 (considered completed) |
| transport | string | Force a specific transport for all messages on accepted messages, default to all transport available |
| label | string | test description or label |### Example: receiving a message
```xml
```
### wait command parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| complete | bool | if "true" wait for all the test to complete (or reach their wait_until state) before executing next action or disconnecting calls and exiting, needed in most cases |
| ms | int | the amount of milliseconds to wait before executing next action or disconnecting calls and exiting, if -1 wait forever |### Example: codec configuration
```xml
```
### codec command parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| priority | int | 0-255, where zero means to disable the codec |
| enable | string | Codec payload type ID, ex. "g722", "pcma", "opus" or "all" |
| disable | string | Codec payload type ID, ex. "g722", "pcma", "opus" or "all" |### Example: TURN configuration
```xml
```
### turn command parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| enabled | bool | if "true" turn server usage will be enabled |
| server | string | turn server URI or IP:port |
| username | string | turn server username |
| password | string | turn server password |
| password_hashed | bool | if "true" us hashed password, default plain password |
| sip_stun_use | bool | if "true" SIP reflective IP is use with signaling |
| media_stun_use | bool | if "true" STUN reflective IP is use with media/SDP |
| stun_only | bool | if "true" TURN and ICE are disabled and only STUN is use |### using multiple accounts
When using multiple accounts, accounts can be created and selected with the following parameters.|command | account parameter |
| ------ | ----------------- |
| accept | account |
| register | account |
| call | caller |
|accept_message| account |
| message | from |### using env variable in scenario actions parameters
Any value starting with `VP_ENV` will be replaced by the envrironment variable of the same name.
Example : `username="VP_ENV_USERNAME"`
```bash
export VP_ENV_PASSWORD=????????
export VP_ENV_USERNAME=username
```### Docker
```bash
voip_patrol/docker$ tree
.
├── build.sh # docker build command example
├── Dockerfile # docker build file for Linux Alpine
└── voip_patrol.sh # docker run example starting
```## Dependencies
#### PJSUA2
PJSUA2 : A C++ High Level Softphone API : built on top of PJSIP and PJMEDIA
http://www.pjsip.org
http://www.pjsip.org/docs/book-latest/PJSUA2Doc.pdf## External tool to test audio quality
#### PESQ
P.862 : Perceptual evaluation of speech quality (PESQ): An objective method for end-to-end speech quality assessment of narrow-band telephone networks and speech codecs
http://www.itu.int/rec/T-REC-P.862
```
./run_pesq +16000 voice_files/reference.wav voice_files/recording.wav
```