Source for drachtio server can be obtained from github (build instructions can also be found there). The drachtio server has been tested on most Linux distributions, but the preferred deployment (because it has been the most heavily tested) is Debian 8 (Jesse).
For those who use Ansible for automating builds, an ansible role is available.
Finally, a docker image is also available via:
docker pull drachtio/drachtio-server:latest
Please post any issues here if you have problems building
The drachtio-server executable built from source code is simply named drachtio
. By default, the build process installs it in /usr/local/bin/drachtio
.
On systemd distributions, drachtio can be installed as a systemd service -- the ansible role does this automatically; on a build from source the systemd script can be found here. The following options are supported:
$ systemctl [start|stop|restart|status] drachtio
Command-line options for the drachtio
executable will be covered in the following section.
The drachtio process can either be configured via command-line parameters, environment variables, a configuration file -- or a combination of all three. The order of precedence of configuration settings is as follows:
By default, the server will look for a configuration file at /etc/drachtio.conf.xml
. This can be changed by passing the configuration file path as a command line argument -f
; e.g., drachtio -f /tmp/drachtio.conf.xml
As the name suggests, the configuration file is in XML format. The structure of the file is described below, and a heavily commented version of the file can be found here that provides additional detail to the summary provided below.
A drachtio configuration file has the following high-level structure:
<drachtio>
<admin/>
<request-handlers/>
<sip/>
<cdrs/>
<monitoring/>
<logging/>
</drachtio>
Each section is described below, along with the command line parameters and environemnt variables that can be used to configure the same settings.
The admin section is required and specifies how the drachtio server will listen for incoming connections from drachtio applications. The information includes the tcp port to listen on, the address(es) to listen on (0.0.0.0 means all available interfaces), the shared secret that is used for authentication, and whether tcp keep alives will be sent on these connections.
Note that as of release 0.8.0, there is also an option to use tls encryption on connections. For inbound connections, this is specified by providing a 'tls-port' option. The server can be configured to handle either, or both, tcp and tls connections.
<admin port="9022" tls-port="9023" secret="cymru" tcp-keepalive-interval="30">0.0.0.0</admin>
or, using command-line parameters:
drachtio --port 9022 --tls-port 9023 --secret cymru --tcp-keepalive-interval 30
or, using environment variables
DRACHTIO_ADMIN_TCP_PORT=9022 \
DRACHTIO_ADMIN_TLS_PORT=9023 \
DRACHTIO_TCP_KEEPALIVE_INTERVAL=30 \
DRACHTIO_SECRET=cymru drachtio
Note that by default, tcp keepalives are enabled with an interval of 45 seconds. The value can be changed, as above, or disabled by setting it to a value of zero.
The request-handlers section is optional and configures the drachtio process to establish outbound connections to drachtio servers for some or all SIP methods instead of inbound connections.
The <request-handlers>
element can have zero or more child <request-handler>
elements. Each <request-handlers>
defines a specific SIP method (or *
to wildcard all methods) and an http(s) web callback to invoke when a new request of the specified method type arrives. It is the responsibility of the user-supplied web callback to return information in an HTTP 200 OK response indicating how to route the call.
<request-handlers>
<request-handler sip-method="INVITE" http-method="GET" verify-peer="false">https://38.187.89.96:8080</request-handler>
</request-handlers>
With the configuration above in place, when the drachtio server receives a new incoming INVITE request, it will send an HTTP GET to the URL above, with HTTP query arguments
method
: the SIP method of the requestdomain
: the SIP domain in the Request-URIprotocol
: the transport protocol used (e.g. 'udp', 'tcp', 'wss', etc)source_address
: the IP address of the senderfromUser
: the user part of the uri in the From headertoUser
: the user part of the uri in the To headeruriUser
: the user part of the uri in the Request-URIcontentType
: the Content-Type header in the request, if anyuri
: the full Request-URINote: either HTTP or HTTPS URIs are supported. If using self-signed certificates with HTTPS, set
verify-peer
to false, as above.
Note: setting
http-method="POST"
will cause an HTTP POST top be sent to the user-supplied web callback. All of the information supplied below will be provided (e.g. query args) but additionally the body of the request will have a full copy of the incoming SIP request message. This is useful in more complex routing scenarios which may, for instance, depend on examining specific values in the SIP headers of the incoming message.
An example HTTP URL that gets sent out looks like this:
http://38.187.89.96:8080/?method=INVITE&domain=server-01.drachtio.org&protocol=udp&source_address=10.132.0.29&fromUser=%2b15083084809&toUser=calltest&uriUser=r-ee78299f-2f85-4d92-97ab-24f1d11e2b69&contentType=application%2fsdp&uri=sip%3ar-ee78299f-2f85-4d92-97ab-24f1d11e2b69%server-01.drachtio.org%3bdst%3d%2b15083084809%2540139.59.165.83%3a5060&dst=%2b15083084809%2540139.59.165.83%3a5060
Based on the information above provided in the HTTP request, the user-supplied callback is responsible for indicating one of the following actions in a JSON body of the HTTP 200 OK response:
The first three actions completely disposition the incoming SIP request -- i.e. no further interaction with a drachtio application occurs.
The final action (route to an application) causes the drachtio server to establish an outbound tcp connection to a drachtio application listening on a specified port, which then receives and processes the request normally (e.g. in a srf.invite((req, res)))
or equivalent).
Note that as of release 0.8.0, it is possible route to a drachtio application over an outbound connection using tls. This is specified by appending a transport
attribute to the uri and specifying 'tls', e.g. uri:myapp.example.com;transport=tls
.
Example JSON responses for each of the above action are illustrated below (note: a response should include only one of the JSON payloads below):
// this would reject the call with a "503 Max Calls Exceeded" response
// note: reason is optional
{
"reject":
"data": {
"status": 503,
"reason": "Max Calls Exceeded"
}
}
// this redirects the call to the address specified.
// the Contact header of the response will be populated accordingly
{
"redirect":
"data": {
"contacts": [
"sip:foo@bar.com"
]
}
}
// this proxies the call accordingly
{
"proxy":
"data": {
"destination": [
"sip:foo@bar.com"
],
recordRoute: true
}
}
// this causes the request to be delivered to a drachtio app for further processing.
// the drachtio app must be listening on the uri provided; i.e an outbound connection.
{
"route":
"data": {
"uri": "call-recording.default.svc.cluster.local:4000"
}
}
// this causes the request to be delivered to a drachtio app for further processing.
// the drachtio app must be using tagged inbound connections.
{
"route":
"data": {
"tag": "conferencing-app"
}
}
Note: the last stanza above applies to using tagged inbound connections. For more details, see here
A request handler for all incoming SIP requests can be configured via the command-line as well:
drachtio --http-handler "http://38.187.89.96:8080" --http-method "GET"
The <sip>
section defines which addresses and ports the SIP stack will listen on, which protocols will be supported, where to find (if necessary) SSL certificates, and other SIP options.
The drachtio server can listen on multiple interfaces/addresses for SIP traffic. These are defined in a <contacts>
element that has child <contact>
elements for each SIP endpoint. Examples of possible configuration are shown below.
<!-- listen on all addresses, default port 5060 for udp and tcp protocols -->
<sip>
<contacts>
<contact>sip:*;transport=udp,tcp</contact>
</contacts>
</sip>
<!-- listen on ports 5060 and 5080 -->
<contacts>
<contact>sip:*;transport=udp,tcp</contact>
<contact>sip:*:5080;transport=udp,tcp</contact>
</contacts>
<!-- listen for secure websockets on specific address and port -->
<contacts>
<contact>sip:192.168.100.23:443;transport=wss</contact>
</contacts>
Additionally, if the SIP server has been assigned an external address that should be used in the SIP signaling, this should be specified as follows:
<contacts>
<contact external-ip="35.195.28.194">sip:10.132.0.22;transport=udp,tcp</contact>
</contacts>
This will cause the drachtio server to advertise its address as 35.195.28.194
in Contact and Via headers, even though its local assigned IP address is 10.132.0.22
.
Furthermore, if the drachtio server has an assigned DNS name, this should be configured as well so that it can detect when the Request-URI of an incoming SIP request is referring to the local host when the DNS name appears in the host portion.
<contacts>
<contact dns-names="server01.drachtio.org" external-ip="35.195.28.194">sip:10.132.0.22;transport=udp,tcp</contact>
</contacts>
Note: multiple DNS names can be provided in comma-separated format.
SIP contacts can be supplied via command line as follows
drachtio --contact "sip:10.132.0.22;transport=udp" --external-ip 35.195.28.194
The SIP spec contains definitions for timers governing retransmissions of SIP requests and the like. Generally, there is no need to modify the setting for these timers, but if desired this can be done as follows:
<timers>
<t1>500</t1>
<t2>4000</t2>
<t4>5000</t4>
<t1x64>32000</t1x64>
</timers>
Note: values are in milliseconds. The example above actually sets the timers to their defined default values, so if you are using this section you would like be setting them to some other values. You only need to specify those timers that you want to adjust from their default values.
If you are using either TLS or WSS as a transport, then you must specify where the associated tls certificates are stored on the server.
Additionally, when using tls on admin connections from applications, you must specify a dhparam file that contains the Diffie-Hellman (dh) parameters. (This is not required if you are only using TLS to secure SIP connections).
Finally, you can optionally specify the minimum acceptable TLS version (1.0, 1.1, or 1.2). If not specified, TLS 1.0 and above will be accepted
<tls>
<min-tls-version>1.2</min-tls-version>
<key-file>/etc/letsencrypt/live/yourdomain/privkey.pem</key-file>
<cert-file>/etc/letsencrypt/live/yourdomain/cert.pem</cert-file>
<chain-file>/etc/letsencrypt/live/yourdomain/chain.pem</chain-file>
<dh-param>/var/local/private/dh4096.pem</dh-param>
</tls>
or, via command-line
drachtio --key-file /etc/letsencrypt/live/yourdomain/privkey.pem \
--cert-file/etc/letsencrypt/live/yourdomain/cert.pem \
--chain-file /etc/letsencrypt/live/yourdomain/chain.pem \
--dh-param /var/local/private/dh4096.pem \
--min-tls-version 1.2
or, via environment variables
DRACHTIO_TLS_CERT_FILE=/etc/letsencrypt/live/yourdomain/cert.pem \
DRACHTIO_TLS_CHAIN_FILE=/etc/letsencrypt/live/yourdomain/chain.pem \
DRACHTIO_TLS_KEY_FILE=/etc/letsencrypt/live/yourdomain/privkey.pem \
DRACHTIO_TLS_DH_PARAM_FILE=/var/local/private/dh4096.pem \
DRACHTIO_MIN_TLS_VERSION=1.2 \
drachtio
This causes all outbound requests to be sent through an outbound proxy
<outbound-proxy>sip:10.10.10.1</outbound-proxy>
The drachtio server can examine the Contact, To, and From headers for distinctive signatures that indicate the request was sent from a spam source. If a spammer is detected, the message can either be rejected or silently discarded.
<spammers action="reject" action="discard">
<header name="User-Agent">
<value>sip-cli</value>
<value>sipcli</value>
<value>friendly-scanner</value>
</header>
<header name="To">
<value>sipvicious</value>
</header>
</spammers>
The drachtio server can be configured to send to Homer using the HEP protocol.
<capture-server port="9060" hep-version="3" id="101">127.0.0.1</capture-server>
or, via command line
drachtio --homer "127.0.0.1:9060" --homer-id 101
or, via environment variables:
DRACHTIO_HOMER_ADDRESS=127.0.0.1 \
DRACHTIO_HOMER_PORT=9060 \
DRACHTIO_HOMER_ID=101 drachtio
Added in version 0.7.3-rc2
sofia-sip has an annoying feature where it forces an outbound request to go out TCP if the packet size exceeds a specific threshold (usually 1300 bytes). Tis configuration setting allows users to increase this threshold to an arbitrary value.
<udp-mtu>4096</udp-mtu>
or, via command line
drachtio --mtu 4096
or, via environment variables
DRACHTIO_UDP_MTU=4096 drachtio
drachtio supports prometheus monitoring by optionally exposing a /metrics endpoint. See here for a list of the metrics provided
<monitoring>
<prometheus port="9090">127.0.0.1</prometheus>
</monitoring>
Note: if the address is not provided, the
/metrics
endpoints will be available on all interfaces (e.g. 0.0.0.0).
or, via command line:
drachtio --prometheus-scrape-port "9090"
# above implies 0.0.0.0:9090, we can be more explicit
drachtio --prometheus-scrape-port "10.0.1.5:9090"
or, via environment variables
DRACHTIO_PROMETHEUS_SCRAPE_PORT=9090 drachtio
# or
DRACHTIO_PROMETHEUS_SCRAPE_PORT=10.0.1.5:9090 drachtio
The <logging>
section defines where drachtio server will send logging information, including sip traces.
Logging destinations include the console, a named log file on the server, or syslog. Any or all of them may be used at one time.
To log output to the console simply include a <console\>
child element.
To send log output to a syslog server via UDP, specify the following:
<syslog>
<address>127.0.0.1</address>
<port>514</port>
<facility>local6</facility>
</syslog>
To send log output to a log file on the server, specify the following:
<file>
<name>/var/log/drachtio/drachtio.log</name>
<archive>/var/log/drachtio/archive</archive>
<size>50</size>
<maxSize>100</maxSize>
<minSize>2000</minSize>
<auto-flush>true</auto-flush>
</file>
The options are as follows:
name
: path to the log filearchive
: path a directory where older log files were be archivedsize
: the size (in MB) at which the log file is truncatedmaxSize
: the max size (in MB) of archived files to keepminSize
: the minimum freespace (in MB) on the filesytem to maintain when archivingauto-flush
: if true, log information is written immediately to disk; otherwise log file is buffered and written intermittently (slightly better performance)The overall system log level: 'notice', 'warning', 'error', 'info, or 'debug'.
<loglevel>info</loglevel>
Note: 'info' is the recommended log level for production systems. At this log level you will get sip traces, which are useful for debugging.
The drachtio server uses the sofia library internally. The log level for this library can be set from 0 (minimal) to 9 (extensive).
<sofia-loglevel>3</sofia-loglevel>
The drachtio
executable can accept command-line arguments that specify some configuration parameters. If provided, the command-line configuration parameters take preference over those specified in the configuration file.
The supported drachtio command-line arguments are:
--daemon
detach from the console and run as a daemon process. Note: when running as a systemd service, this parameter is not necessary.--noconfig
ignore any logging configuration in the configuration file--file|-f filename
read configuration from specified file rather that /etc/drachtio.conf.xml
--user|-u user
run as the named user rather than root--port|-p port
listen for tcp admin connections on the named port--tls-port
listen for tls admin connections on the named port. Added in version 0.8.0-rc1.--contact|-c
specifies a listening address/port/protocol. Multiple instances of this parameter may be provided--external-ip ip-address
specifies an external address that the drachtio server should advertise in the SIP signaling. This parameter applies to the --contact
parameter that it follows in the command line.dns-name name
a dns name that refer to the local server. This parameter applies to the --contact
parameter that it follows in the command line.http-handler url
an HTTP URL of a web callback that will be invoked for all new incoming requests. Setting this parameter turns on outbound connections for all SIP request types.http-method
either 'GET' or 'PUT'--loglevel level
the overall log level to set--sofia-loglevel level
the log level of the sofia library--stdout
write log output to console--homer ip-address:port
ip address of homer capture server to send to. HEP3 and udp transport will be used--homer-id id
id to use to represent this server when sending messages to homer--version
print the drachtio server version to console and exit.--mtu
specifies a message size, in bytes, for requests such that when outgoing requests exceed this threshold use of tcp is forced (this overrides the default sofia stack setting for the same). Added in version 0.7.3-rc2.--dh-param
dhparam file used for inbound tls admin connections. Added in version 0.8.0-rc1.--min-tls-version
minimum allowed TLS version for connecting clients (default: 1.0, allowed values: 1.0, 1,1, 1,2) Added in version 0.8.7-rc4.Note: This article is a work in progress.
The drachtio server is controlled by drachtio-srf applications using a utf8-based messaging protocol over a tcp connection.
Because some developers have expressed an interest in integrating other language frameworks (e.g. go) to the drachtio server, this section aims to give some details of that protocol. As highlighted above, it is a work in progress.
As per the documention found elsewhere on this site, drachtio supports both inbound and outbound connections. To begin with, we will focus here on describing the message flows for inbound connections.
Messages are utf8-encoded. (This was not always the case - originally ascii was used, but this broke down with applications that needed to receive and send information like emojis!).
Each message starts with a decimal number indicating the number of bytes in the message (again, this is utf-8 so number of characters does not necessarily mean number of bytes!), followed by a hash sign ('#'). The number of bytes specified does not include these leading decimal digits or the hash sign -- they indicate the length of the payload that follows.
The messsge payload that follows this consists of 1 or more lines of data, where each line is terminated by a CRLF.
Typically, the first line of payload data consists of a list of tokens, where each token is delimited by a '|' character. When SIP messages are exchanged between application and server, these are usually carried starting on the second line of data, and are simply represented exactly as they appear "on the wire" between SIP endpoints.
For those interested, note that is is possible to generate a trace file of all messaging between the client and the server by setting a property on the Srf
instance, e.g.:
const Srf = require('drachtio-srf');
const srf = new Srf();
// this will cause all messages between client and server to be logged to a file
srf.set('api logger', '/tmp/messages.log');
An inbound connection scenario starts when an application, acting as a TCP client, connects to a drachtio server on its configured admin port.
After the connection is established, the application must authenticate itself via the shared secret that is configured in the drachtio.conf.xml
configuration file on the server. If the client is authenticated, the server returns information including the sip hostports (e.g. list of address:port) that the server is listening on.
Let's look at an example of a successful authentication. Not all of this will immediately be clear, but we will review the individual message elements below.
===>56#12ad33a1-9f33-40b7-b327-b2e32bfcd9e8|authenticate|cymru|
<===465#2f8216a3-babf-4cdb-93c6-254fe8dba42d|response|12ad33a1-9f33-40b7-b327-b2e32bfcd9e8|OK|tcp/[::1]:5060,udp/[::1]:5060,tcp/127.0.0.1:5060,tcp/10.0.0.121:5060,udp/127.0.0.1:5060,tcp/[2601:182:cd00:5786::4a1e]:5060,udp/[2601:182:cd00:5786::4a1e]:5060,tcp/[2601:182:cd00:5786:a534:e8d4:3dcb:3553]:5060,udp/[2601:182:cd00:5786:a534:e8d4:3dcb:3553]:5060,udp/10.0.0.121:5060,tcp/[2601:182:cd00:5786:1866:49f9:e83b:9574]:5060,udp/[2601:182:cd00:5786:1866:49f9:e83b:9574]:5060
Note: the direction
===>
indicates a message sent from an application to the server; the reverse indicates a message sent from the server to the application
We see that after connecting, the application sends an authenticate request to the server. The authenticate request consists of a single line containing three (3) tokens:
The server validates the shared secret, and returns a message consisting of one line, containing the following tokens:
At this point, the client has connected and authenticated successfully, but it has not yet registered the SIP request types that it would like to receive. That happens next.
In order to notify the server that the application wishes to handle specific SIP request types, it is necessary to issue a 'route' command. This is typically the next thing a client application does after authenticating. It is only necessary to register for request types once, during startup (i.e., after actually handling an incoming request it is not necessary to re-register in order to get further requests).
Registering for request types is taken care of automatically in a drachtio-srf app when a
srf.invite()
statement is processed, for example.
# registering to receive INVITEs
===>49#5e60fef0-409f-4980-a859-94810d002ebb|route|invite
<===85#e7470b05-95be-448e-94cd-3935292c4956|response|5e60fef0-409f-4980-a859-94810d002ebb|OK
Note: to register for multiple request types (e.g. INVITE and REGISTER) the application must issue spearate 'route' commands.
The 'route' command consists of a single line containing the following tokens:
The response, as before, contains its own message id as well as the message id of the request, and the status ('OK').
At this point, the server will start sending SIP requests of the requested type to the application for handling. Let's look at what happens next.
Let's start with something simple: receiving a SIP INVITE and sending a non-success response.
The basic message flow is this:
With that as background, let's examine the message trace. To make it interesting, we will have the client application add a custom SIP header to the response.
We will also see now our first example of messages containining multiple lines, since we are now carrying SIP messages back and forth between client and server:
<===866#83936ddb-523a-4cd0-886e-92b484905d85|sip|network|732|udp|127.0.0.1|50500|16:06:41.114233|8f62909b-0f25-4bb8-b0fc-2c0ec88a4afe|\r\n
INVITE sip:15083084809@127.0.0.1 SIP/2.0\r\n
Via: SIP/2.0/UDP 127.0.0.1:50500;branch=z9hG4bK-524287-1---f8002e51f06e3b38;rport=50500\r\n
Max-Forwards: 70\r\n
Contact: <sip:dhorton@127.0.0.1:50500>\r\n
To: <sip:15083084809@127.0.0.1>\r\n
From: <sip:dhorton@127.0.0.1>;tag=ce2ff21e\r\n
Call-ID: 92383ZWEzZGI3MTY4NDRiMGI1ZTRhYjc2YWQ4ZTE1OWY4N2E\r\n
CSeq: 1 INVITE\r\n
Allow: SUBSCRIBE, NOTIFY, INVITE, ACK, CANCEL, BYE, REFER, INFO, OPTIONS\r\n
Content-Type: application/sdp\r\n
Supported: replaces\r\nUser-Agent: Bria 5 release 5.3.1 stamp 92383\r\n
Content-Length: 202\r\n
\r\n
v=0\r\n
o=- 1531670801092727 1 IN IP4 127.0.0.1\r\n
s=Bria 5 release 5.3.1 stamp 92383\r\n
c=IN IP4 127.0.0.1\r\n
t=0 0\r\n
m=audio 52282 RTP/AVP 0 101\r\n
a=rtpmap:101 telephone-event/8000\r\n
a=fmtp:101 0-15\r\n
a=sendrecv\r\n
===>332#829ba63e-5010-4719-b72f-cb3cf6f4aab2|sip|8f62909b-0f25-4bb8-b0fc-2c0ec88a4afe|\r\n
SIP/2.0 486 Busy Here\r\n
Call-ID: 92383ZWEzZGI3MTY4NDRiMGI1ZTRhYjc2YWQ4ZTE1OWY4N2E\r\n
cseq: 1 INVITE\r\n
from: <sip:dhorton@127.0.0.1>;tag=ce2ff21e\r\n
to: <sip:15083084809@127.0.0.1>\r\n
Content-Length: 0\r\nuser-agent: drachtio\r\n
X-custom: my custom header value\r\n
<===600#d04f4d88-108c-4d93-a3f9-e9967b63ff55|response|829ba63e-5010-4719-b72f-cb3cf6f4aab2|OK|application|359|udp|127.0.0.1|50500|16:06:41.127954|8f62909b-0f25-4bb8-b0fc-2c0ec88a4afe|92383ZWEzZGI3MTY4NDRiMGI1ZTRhYjc2YWQ4ZTE1OWY4N2E;uas||Msg sent:|\r\n
SIP/2.0 486 Busy Here\r\n
Via: SIP/2.0/UDP 127.0.0.1:50500;branch=z9hG4bK-524287-1---f8002e51f06e3b38;rport=50500\r\n
From: <sip:dhorton@127.0.0.1>;tag=ce2ff21e\r\n
To: <sip:15083084809@127.0.0.1>;tag=cjSXXKtQejgrg\r\n
Call-ID: 92383ZWEzZGI3MTY4NDRiMGI1ZTRhYjc2YWQ4ZTE1OWY4N2E\r\n
CSeq: 1 INVITE\r\n
User-Agent: drachtio\r\n
Content-Length: 0\r\n
X-custom: my custom header value\r\n
Let's examine the first message -- the one sent by the server to the application, giving it an incoming INVITE message to handle.
As usual, after the length specifier we see the message payload begins with the message identifier.
After that, we have the message type, which in this case is 'sip'. We've now almost all of the message types (there aren't that many!), so let's pause here and briefly give the full list:
In the case of a new incoming 'sip' request sent by the drachtio server we have the following tokens on the first line of the message payload:
Following the first line of payload the incoming SIP message in its entirety is provided.
At this point it is the responsibility of the application to return the desired SIP response that it wishes the server to send out. We see in the example above that the application also uses the 'sip' message type to accomplish this. The first line of payload contains the following tokens:
Following that we have the message itself. Note that it is not necessary to provide the full SIP response message -- based on the transaction id, most of the headers will be supplied by the drachtio server. The application must minimally provide the SIP status line (in our example, drachtio-srf is populating several other headers such as To, From, etc but this should not be necessary). Additionally, if a body is desired in the response (which is not in our example), then that would be provided by the application as well (in the normal way of separating the body from any headers with two (2) CRLFs).
The drachtio server sends out the indicated response and then notifies the application of the exact SIP response that was sent out over the wire. This allows the application to learn about information, such as the tag on the SIP To header, that the server itself would have applied.
This final message has the following payload:
Note: the additional tokens at the end of the first line (a blank token, and the string 'Msg sent') can be ignored; they are placeholders that are used in scenarios where the application has sent a SIP request, not a response.