Sending UDP over Internet using SRT
Introduction
Sending video over UDP across the Internet is a problem due to the nature of UDP. Depending on network conditions packet loss is likely. Sending high quality video is very likely to result in a bad user experience.
What is SRT
SRT is an open source library provided by Haivision whom has also, together with Wowza, formed the srt alliance. SRT is a short for Secure Reliable Transport and that basically tells you what it is all about, sending data reliably across the Internet.
SRT details
The technique used by SRT to recover packet loss is called ARQ (Automatic Repeat Request). ARQ basically works by having a sender/caller setting a sequence number on each packet and a receiver/listener that checks that all packets have been received in correct order. Any lost packets are detected and the listener can request a retransmission of those packets.
The caller is storing sent packets in a cache in case it need to resend them and the listener buffers received packets to be able to reorder the received packets in case they arrive in wrong order.
SRT Deployment
SRT can be run in the modes Caller, Listener and Rendezvous. The mode only tells who initiated the connection, not in what direction the UDP stream is sent. In Rendezvous mode both nodes are initiating the communication. Rendezvous mode is used when both nodes are behind firewalls and allows for communicating without configuring the firewall.
Building SRT
SRT is a library you can use to implement applications that need to use SRT. There are, however, some sample tools in the library as well.
Checkout code from github and build
$ git clone https://github.com/Haivision/srt.git
$ cd srt
$ mkdir build
$ cd build
$ cmake ../
$ make
In addition to building the srt library this also builds a sample tool called
srt-live-transmit
which is used and described in this note.
Basic usage of SRT tool
The tool srt-live-transmit
is used to flip data between different
mediums. The tool is able to read/write from/to mediums. E.g. a caller
can read from UDP and write to SRT and then a listener can read from SRT
and write to UDP.
UDP -> SRT <=== internet ====> SRT -> UDP
The caller is started with the tool by doing:
$ srt-live-transmit udp://224.0.0.1:2244 srt://hjortsberg.org:6600
The listener is started on host hjortsberg.org
by running:
$ srt-live-transmit srt://:6600 udp://224.0.0.1:2255
In the use case described here the sender/source will run in calling mode
reading UDP multicast from 224.0.0.1 port 2244 and writing SRT to
hjortsberg.org
on port 6600. The receiver will run in listening mode reading
SRT from port 6600 and writing UDP multicast to 224.0.0.1 port 2255. So the UDP
stream goes from caller to listener hjortsberg.org
.
You can also send data from listener to caller. In this case you start the caller by doing:
$ srt-live-transmit srt://hjortsberg.org:6600 udp://127.0.0.1:9900
And the listener is started on hjortsberg.org
with:
$ srt-live-transmit udp://224.0.0.1:2244 srt://:6600
In this case the source will run in listening mode reading multicast UDP from
224.0.0.1 port 2244 and writing SRT to whoever connects to port 6600. The
destination is run in calling mode reading SRT from port 6600 and writing UDP
unicast to 127.0.0.1 port 9900. So in this case the UDP stream goes from the
listener hjortsberg.org
to the caller.
Using SRT behind firewall
The use cases above works fine on a private network but if the connection is over internet it requires that ports are opened in the firewall on the listener side. When running in rendezvous mode this may not be needed. This is really neat if running in an environment where it is hard to change firewall configuration.
The way this works is that both ends initiate communication. When this happens
both firewalls will register outgoing traffic to an <address>:<port>
. When
packets are received from the other end the firewall assumes that those packets
are responses to the packets sent by a host in the local network and lets the
packets pass through the firewall.
Caller and listener mode are deduced from the format of the URIs. Rendezvous mode must be specified with a parameter.
Running in rendezvous mode on source host is done by:
$ srt-live-transmit udp://224.1.1.1:1111 "srt://server2:6600?mode=rendezvous"
Media path: 'udp://224.1.1.1:1111' --> 'srt://<ip>:6600?mode=rendezvouz'
where server2
is the public hostname (or public ip) for the gateway hiding
the destination host behind NAT. On destination host srt is started with:
$ srt-live-transmit "srt://server1:6600?mode=rendezvous" udp://127.0.0.1:2222
Media path: 'srt://<ip>:6600?mode=rendezvous' --> 'udp://127.0.0.1:2222'
here server1
is the public hostname (or ip) for the gateway hiding the
source host behind NAT.
When data is sent from source then destination
will print a message that SRT source connected
. When stopping the source
SRT source disconnected
will be printed on destination node.
Using parameters
As seen when using rendezvous mode it is possible to set parameters for SRT.
Rendezvous mode is just one of many parameters that can be set. Parameters
are set by appending a query string to the uri on the form param=value
like
this:
srt://host:port?param=value¶m2=value2
Parameters can be used to configure the mediums, for example setting the TTL (Time To Live) on UDP medium or maximum transmission latency on SRT.
For UDP you can set parameters:
ttl - time to live (IP_TTL or IP_MULTICAST_TTL socket option)
iptos - Type of Service (IP_TOS socket option)
For SRT there are more parameters. For example you can set the parameters:
mode - force mode, caller, listener, rendezvous
port - force outgoing port
timeout - obviously a timeout
latency - maximum transmission latency
passphrase - Password for encrypted transmission
Encryption
Another example of using parameter is when using encrypted transmission. When SRT is used to send streams over the Internet it might be required to use some kind of encryption. The encryption in the SRT tool is using a pre-shared key to encrypt the traffic.
If we extend the rendezvous firewall example with encryption it will look like the following.
For source host in rendezvous mode:
$ srt-live-transmit udp://224.1.1.1:1111 "srt://server2:6600?mode=rendezvous&passphrase=secretpass"
On destination host srt is started with:
$ srt-live-transmit "srt://server1:6600?mode=rendezvous&passphrase=secretpass" udp://127.0.0.1:2222
Media path: 'srt://<ip>:6600?mode=rendezvous&passphrase=secretpass' --> 'udp://127.0.0.1:2222'
Where secretpass
is the pre-shared key.
If wrong passphrase is given there will be a message on the destination host:
KMREQ/rcv: (snd) Rx process failure - BADSECRET
Statistics
SRT is collecting statistics on the traffic in the form of a number of counters. These counters can be viewed on source and on destination host.
The statistic counters are enabled with a command line option. To view statistic counters after every 5000 packets on the destination host:
$ ./srt-live-transmit -s 5000 -f "srt://server1:6600?mode=rendezvous&passphrase=secretpass" udp://127.0.0.1:2222
the option -f
prints the full counter instead of only give the counter values
since last report.
The statistics report can look like this:
======= SRT STATS: sid=97099544
PACKETS SENT: 0 RECEIVED: 60025
LOST PKT SENT: 0 RECEIVED: 2
REXMIT SENT: 0 RECEIVED: 2
DROP PKT SENT: 0 RECEIVED: 0
RATE SENDING: 0 RECEIVING: 2.34583
BELATED RECEIVED: 0 AVG TIME: 0
REORDER DISTANCE: 0
WINDOW FLOW: 8192 CONGESTION: 8192 FLIGHT: 0
LINK RTT: 5.561ms BANDWIDTH: 1.368Mb/s
BUFFERLEFT: SND: 12288000 RCV: 12247500
The statistics above shows that after 60000 packets there has been 2 lost packets that were successfully retransmitted, 0 packets has been dropped.