# RTPProxy 2.2 Manual

## Introduction

### What is RTPProxy

The RTPProxy is a high-performance software proxy for RTP streams that can work together with Sippy B2BUA, Kamailio, OpenSIPs and SER (SIP Express Router).

For the current moment the newest stable version is - RTPProxy 2.2

### Backstory

RTPProxy was originally developed by Maxim Sobolyev in 2003 with a purpose of VoIP calls facilitation to/from SIP User Agents located behind NAT or firewalls. That time, there were a few cases where direct end-to-end communication between users behind the NAT was not possible. RTPProxy, in common with a SIP proxy, overcomes those obstacles by acting as an intermediary point for the RTP streams.

Afterwards, the RTPProxy has become widely used by VoIP service providers that are in a demand for optimizing a traffic flow in their networks.

Later on it became apparent that there are many other possible uses of this software. It can be used in common with a signaling element (SIP Proxy or SIP B2BUA) to build complex VoIP networks, to optimize a traffic flow, to collect voice quality information and so on.

RTPProxy is now actively developed and maintained by the Sippy Software, Inc. and is available on GitHub of Sippy Labs - https://github.com/sippy/rtpproxy.

Over the years, many other individuals and organizations has contributed features and fixes into the code base, including Vonage, SipPulse, Voicenter, RateTel, either directly or by sponsoring respective development efforts (often both).

### Capabilities

Originally it was designed for handling of NAT scenarios. It can also act as a generic media relay, as well as a gateway for RTP sessions between IPv4 and IPv6 networks.

It can perform number of additional functions on RTP streams, including call recording, playing pre-recorded announcements, real-time stream copying and RTP payload re-framing.

The RTPProxy supports some advanced features, such as remote control mode, allowing a building of scalable distributed SIP VoIP networks. The nathelper module included into the SIP Express Router (now known as OpenSIPS or Kamailio, both are forks of SER), as well as Sippy B2BUA allow using multiple RTPProxy instances running on remote machines for fault-tolerance and load-balancing purposes.

An advanced high-capacity clustering and a load balancing is available through the use of RTP Cluster middleware.

The software also supports MOH/pre-recorded prompts injection, video relaying and RTP session recording to a local file or remote UDP listener(s).

### Principles of Operation

1. Firstly, when a SIP proxy receives an INVITE request, it extracts a call-id from it and hands it to the proxy via Unix domain socket. Then, in its turn, a proxy looks for an existing session with the same id. If the session exists, it returns a UDP port for that session. In case it doesn't exist, it creates a new session and binds it to a first empty UDP port from the range specified at the start time and returns the number of that port to a SIP proxy called it. Upon receiving a reply from the proxy, SIP Proxy (Sippy B2BUA, OpenSIPS or Kamailio) in its turn replaces media IP:port in the SDP body, in order to point to the media proxy and then it forwards a request as usually.

2. When it comes to receiving of non-negative SIP reply with the SDP body, then SIP proxy again extracts call-id from it and hands it to the rtpproxy. In this case the rtpproxy does not allocate a new session, if it doesn't exist. But simply performs a lookup among existing sessions and returns either a port number if the session is found, or an error code indicating that there is no session with such id. Upon receiving a positive reply from the rtpproxy, SIP Proxy (Sippy B2BUA, OpenSIPS or Kamailio) replaces media IP:port in the SDP body of that SIP reply, in order to point to the rtpproxy and then forwards this reply as usually.

3. After the session has been created, the rtpproxy listens on the port it has allocated for that session. It also waits for receiving at least one UDP packet from each of two parties participating in the call. Once such packet was received, the proxy fills one of two ip:port structures associated with each call, using source ip:port of that packet as a value. When both structures are filled in, the proxy starts relaying UDP packets between call parties.

A good advantage of the RTPProxy is, that it tracks idle time for each existing session (the period of time within which no packets were relayed) and automatically cleans up a session, idle time of which exceed the value specified at the command line (60 seconds by default).

### Content of the Package

The RTPProxy package by default provides the following components:

- rtpproxy - main RTP proxy server binary (production build)

- rtpproxy_debug - Main RTP proxy server binary (debug and profiling build)

- makeann - Utility to pre-encode prompts and announcements (production build)

- makeann_debug - Utility to pre-encode prompts and announcements (debug and profiling build)

- extractaudio - Utility to convert recorded sessions into plain audio files (production build)

- extractaudio_debug - Utility to convert recorded sessions into plain audio files (debug and profiling build)

## Installation of RTPProxy

### Pre-built RTPProxy

In case you want to use per-built RTPProxy package, then use your system's package manager to set this up:

dpkg - for Debian based systems(including Ubuntu), when installing .deb packages.

apt-get / `aptitude` - for Debian based systems (including Ubuntu), when installing from a repository.

rpm - for CentOS when installing .rpm packages.

pkg - for FreeBSD when installing from a repository or packages.

In case you want to compile RTPProxy from sources, use the following section "Compilation from sources".

### Compilation from sources

#### Installing Dependencies

The RTPProxy package has several optional dependencies that are detected at the configure stage and an appropriate functionality is enabled.

Those dependencies and their impact on the RTPProxy build are listed below:

- `bcg729` - Enables G.729 support in several tools.

  https://linphone.org/releases/sources/bcg729/

  Affected binaries: `extractaudio` `makeann`

- `libsndfile` - Allows decoded audio to be saved in a number of popular audio formats instead of just RAW signed-linear 16bit.

  http://www.mega-nerd.com/libsndfile/files/

  Affected binaries: `extractaudio`

- `libg722` - Enables G.722 support in several tools.

  https://github.com/sippy/libg722

  Affected binaries: `extractaudio` `makeann`

- `libsrtp` - Enables decoding recordings of SRTP streams.

  https://github.com/cisco/libsrtp.git

  Affected binaries: `extractaudio`

- `libsystemd-dev` - allows for a tighter systemd integration.

  Also requires --enable-systemd configure argument to enable. See section on enabling systemd support for details.

  libsystemd@github

  Affected binaries: `rtpproxy`

- `libelperiodic` - Required by several internal tools that are used by an automated testing framework. Both shared library and python module need to be installed into either system location or python environment. `make check` will fail if it's not installed.

  https://github.com/sobomax/libelperiodic.git

  Affected tools: `rtpp_notify_client.py` `rtpp_query.py` `getmonotime.py`

- `tcpdump` - Test framework requires it to capture traffic and verify PCAP decoding features. `make check` will fail if it's not installed.

  http://www.tcpdump.org/release/

- `sudo` - Test framework requires it to run the `tcpdump` at elevated privileges. `make check` will fail if it's not installed.

  http://www.sudo.ws/

Do not forget about your compiler! To build this version of the RTPProxy you would need either:

- GCC compiler, version 5.0 or higher, or

- Clang compiler, version 6.0 or higher

#### Compilation of the Source Code

Pull the latest stable version from a git master branch (into a directory where you want to store compilation sources, usually it's /usr/src/):

         cd /usr/src
         git clone -b master https://github.com/sippy/rtpproxy.git

Make sure you bring rtpprpoxy git submodules:

         git -C rtpproxy submodule update --init --recursive

Now compile a binary file using sources using the following commands:

A sequence for users:

         cd rtpproxy
         ./configure
         make clean all
         make install

For developers might also be useful to include `make check` in the sequence. Make sure you have libelperiodic, sudo and tcpdump installed for that step to complete:

         cd rtpproxy
         ./configure
         make clean all
         make check
         make install

After a successful compilation, you have the following binaries

- Main RTP proxy server binary - production build.

  After the compilation is done, you have a binary file stored in the /usr/local/bin/ folder. You can test this out, checking the version of the rtpproxy: /usr/local/bin/rtpproxy -V

- Main RTP proxy server binary - debug and profiling build.

  You will also have a second binary file for debug and profiling: /usr/local/bin/rtpproxy_debug

## Getting Started

A good way to maintain your RTPProxy is to start it using a certain Service Manager, such as systemd.

Systemd is a latest and the most known Service Manager application in most UNIX based systems:

- Ubuntu 15.04 is the first version (of Ubuntu) that uses systemd by default;

- Debian 8 (Jessie) is the first version (of Debian) that uses systemd by default;

- Red Hat-based distributions are migrating to systemd as well. It has been the default system and services manager in Red Hat 7, CentOs7 and Fedora since the release of Fedora 15;

- There is huge list of other distributions, that use the systemd as a System Manager by default now as well (OpenSUSE, Mint, Mageia etc.) .

In case you have a system, that doesn't support the systemd, you can use any other Service Managers as you want to (for e.g. init.d start scripts in Debian systems older than 8th one).

Link to an init.d start/stop script: https://link.here.com (TO DO)

But, as it was said that the systemd is the most relevant solution for this, because it provides the following capabilities:

- Define a list of options in a separate environment file, and use those options as a variable in the start row 'ExecStart='

- You're able to react on a failure of an application using a special parameter 'OnFailure=' (and to send notification for e.g.)

- You can specify a list of pre-actions to be performed, before systemd launches binary file 'ExecStartPre=' (for e.g. creation of /var/run/rtproxy directory and adding user/group rights to it)

- As well as you can add pre-start actions, you can perform post-stop actions for cases when application stops running 'ExecStopPost=' (for e.g. deletion of the /var/run/rtpproxy directory)

- You can set a policy for cases when application stops improperly (not a manual stop of the application), for e.g. restarting always with 'Restart=always'

- You may also want to add a time delay between restart attempts with 'RestartSec=5'

- You can deal with different things related to logging or syslogging (for e.g. changing of a name identifier when writing to a syslog 'SyslogIdentifier=' or specifying a different logfacility level with 'StandardOutput=' and 'StandardError=' )

- User/Group to be used for running an application

- and many many other things..

The link to an instance of the systemd service file (for the RTPProxy): systemd configuration file instance -> Instance of the systemd service file

After you downloaded your systemd service file, adjust OPTIONS parameters.

Set you own IP address for listening, or leave it with 0.0.0.0 (manual way)

    -l 0.0.0.0

Set upper bound on number of file descriptors the rtpproxy service instance might be using. Rule of thumb is that 4 file descriptors are needed for a fully established session (two RTP endpoints and two RTCP ones).

Make the value reasonably high to match your load expectations in terms of number of concurrent sessions but not excessively high, as it may cause rtpproxy to fail initialization because operating system usually also enforces upper bound on this value that varies from system to system:

    -L 4096

You may also want to change a port range for opening UDP ports:

    -m <min number> -M <max number>

    e.g.: -m 10000 -M 40000

Change you log facility level if you want to:

    -d INFO:<LOG_LOCAL_NUMBER>

    e.g.: -d INFO:LOG_LOCAL5
          -d DBUG:LOG_LOCAL5

Another great reason to use systemd, is a possibility of systemd to create control sockets for rtpproxy.

The benefit of this is, that even rtpproxy is down for some reason, remote daemons (such as OpenSIPS or Kamailio) do not lose a connection with a control file descriptor, thus do not throw any errors related to a connection loss with rtpproxy (still you can get timeout errors, but they can be not that critical as a complete loss of control socket connection).

During the period of time rtpproxy is down, all control commands sent to it, are to be caught after rtpproxy is back. Thus systemd keeps all commands in a buffer for future usage.

To let this be working, follow this guide: Configuration section -> 5. Configuration of control socket.

Other than that, for better view of how to configure your startup line, you can use this Configuration section.

After you're done with customizing of your systemd service file for RTPProxy, follow this sequence to finish it:

- copy it to the /lib/systemd/system/ directory

- reload systemd configuration with:

      bash> sudo systemctl daemon-reload

- enable the service:

      bash> sudo systemctl enable rtpproxy.service

- Now you can start your RTPProxy using the commands given below

Working with a systemd, you may need to know a list of general commands to manage with your RTPProxy service, here they are:

- Start of the service:

      bash> sudo systemctl start rtpproxy.service

- Stop of the service:

      bash> sudo systemctl stop rtpproxy.service

- Restart of the service:

      bash> sudo systemctl restart rtpproxy.service

- Check status of the service:

      bash> sudo systemctl status rtpproxy.service

- Show systemd configuration file of the service:

      bash> sudo systemctl show rtpproxy.service

To see an output after you started you RTPProxy, or even just to keep a track on how it's working, you can use the following commands:

- Look into a journal:

      bash> sudo journalctl -xe -u rtpproxy.service

- You can configure logging to a separate logfile, to do this, follow the manual (or you can use manual logging to a syslog file) listed in the:

  Configuration section -> Logging to a separate file

- You can see an output of the systemctl tool:

      bash> sudo systemctl status rtpproxy.service

Interaction of a SIP proxy server with RTPProxy application is supported via

`rtpproxy.sock` - control socket created by the RTPProxy

`rtpproxy_timeout.sock` - a socket for timeout notifications created by the SIP proxy

## Configuration

Historically, primary configuration method for the RTPProxy was done via command-line parameters. Starting with version 2.2 certain advanced parameters (particularly loadable modules configuration) have been moved into configuration file.

### Command Line Parameters

#### SYNOPSIS

#### OPTIONS

The following command-line parameters are supported:

### Configuration File

TODO

### Startup Script

The way you integrate RTPProxy into your system startup sequence is highly OS-version dependent. If you are using per-built RTPProxy package then most likely such method will be provided as part of that package and the best course of actions is to use that facility.

However, if you are a package maintainer or system builder you might need to create such configuration from scratch. In the next sections we would provide some basic guidelines on how to launch RTPProxy in some common cases.

#### Systemd based systems

On most modern Linux-based systems systemd is the recommended method to start the RTPProxy.

    [Unit]
    Description=RTPProxy media server
    After=network.target
    Requires=network.target

    [Service]
    Type=simple
    PIDFile=/var/run/rtpproxy/rtpproxy.pid
    Environment='OPTIONS= -f -L 4096 -l 0.0.0.0 -m 10000 -M 20000 -d INFO:LOG_LOCAL5'

    Restart=always
    RestartSec=5

    ExecStartPre=-/bin/mkdir /var/run/rtpproxy
    ExecStartPre=-/bin/chown rtpproxy:rtpproxy /var/run/rtpproxy

    ExecStart=/usr/local/bin/rtpproxy -p /var/run/rtpproxy/rtpproxy.pid -s unix:/var/run/rtpproxy/rtpproxy.sock \
     -u rtpproxy rtpproxy -n unix:/var/run/rtpproxy/rtpproxy_timeout.sock $OPTIONS
    ExecStop=/usr/bin/pkill -F /var/run/rtpproxy/rtpproxy.pid

    ExecStopPost=-/bin/rm -R /var/run/rtpproxy

    StandardOutput=syslog
    StandardError=syslog
    SyslogIdentifier=rtpproxy
    SyslogFacility=local5

    TimeoutStartSec=10
    TimeoutStopSec=10

    [Install]
    WantedBy=multi-user.target

### Logging

Logging is a very important aspect of the RTPProxy operation that should not be overlooked. In our experience, properly configured and tested RTPProxy instance can keep running unattended literally for many years non-stop. Yet, various issues with a particular session and/or endpoint would inevitably pop-up over time, so it's of utter importance to setup logging and log management in a manner that is durable and forward-looking. Allowing someone to perform a post-mortem investigation of particular issue that happened days, if not weeks, ago with a relative ease.

Some of the consideration one should have in mind while configuring logging is:

1. How much storage my system has for the RTPProxy to use?

2. What is the typical amount of time it takes for my user to report an issue and get it escalated to the DevOps team?

3. What is the typical amount of time it takes for the DevOps team to act on issue and look at the logs in question?

4. How much detail do I need? The answer to this might depends on whether this is a development/QA or a production system.

5. Are there any other non-technical consideration that might influence those decisions? For example: data protection laws, law enforcement requirements etc.

#### Logging to a separate file

- First of all you need to create a file you will use for logging and give it proper permissions (according to a user/group starting RTPProxy):

      touch /var/log/rtpproxy.log
      chown rtpproxy:rtpproxy /var/log/rtpproxy.log

- Then define a log facility for it in rsyslog configuration file (add a row at the bottom of the file) and restart rsyslog server:

      vim /etc/rsyslog.d/50-default.conf
       local5.*        /var/log/rtpproxy.log

      systemctl restart rsyslog.service

- next step add a log rotation configuration for this log file (that's a good way of handling overfilled log files):

      vim /etc/logrotate.d/rtpproxy

      /var/log/rtpproxy.log {
        missingok
        compress
        delaycompress
        notifempty
        copytruncate
        rotate 5
        daily
      }

- Now add a log facility level to your start row of the RTPProxy:

      -d INFO:LOG_LOCAL5

- Reload systemd configuration (to apply previous change) and restart your RTPProxy server. Now logging should be done using new output file:

      systemctl daemon reload

      systemctl restart rtpproxy.service

### Configuration of control socket (using systemd)

As it was said earlier, keeping of the control socket using systemd, is a good reason to start using systemd.

A configuration process is pretty simple, there are just a few steps you need to implement to start using of it.

1. Firstly, you need to install package requirements: `libsystemd-dev`

2. Secondly, you need to compile rtpproxy with a systemd flag (a usual compilation process, just add an option to a configure execution):

    ./configure --enable-systemd

3. A third step, you need to create rtpproxy.socket systemd unit file, that will be responsible for keeping your control socket:

An example:

/etc/systemd/system/sockets.target.wants/rtpproxy.socket (better to create it in /lib/systemd/system/sockets.target.wants/ and symlink it)

    [Socket]
    ListenStream=/var/run/rtpproxy/rtpproxy.sock
    SocketUser=rtpproxy
    SocketGroup=rtpproxy
    SocketMode=755
    ExecStartPost=-/bin/chown rtpproxy:rtpproxy /var/run/rtpproxy

    [Install]
    WantedBy=sockets.target

4. Set a parameter in startup row of rtpproxy.service unit (you don't need to provide a path to socket file):

    -s systemd:

an example:

    ExecStart=/usr/local/bin/rtpproxy -p /var/run/rtpproxy/rtpproxy.pid -s systemd: -u rtpproxy:rtpproxy -n unix:/var/run/rtpproxy/rtpproxy_timeout.sock -f -l 0.0.0.0 -m 10000 -M 20000 -d INFO:LOG_DAEMON

When you're done with all above, do not forget to reload systemd configuration and enable socket unit:

    bash> sudo systemctl daemon-reload

    bash> sudo systemctl enable rtpproxy.socket

(btw here is a nice article of how to configure systemd socket unit files - http://0pointer.de/blog/projects/socket-activation.html?fbclid=IwAR2aIYwttyFOc_7rXarlYaz0SexTxMverWF42Xpg5yX96eytkmhFhtsI49M)

Now start rtpproxy.socket and rtpproxy,service just after that:

    bash> sudo systemctl start rtpproxy.socket

    bash> sudo systemctl start rtpproxy.service

At this stage, your rtpproxy.service should catch up a socket created by systemd and start working properly. If you see some kind of errors, then you're missing one of the steps defined above.