mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
544 lines
13 KiB
544 lines
13 KiB
<?xml version="1.0" encoding='ISO-8859-1'?>
|
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
|
|
|
|
<!-- Include general documentation entities -->
|
|
<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
|
|
%docentities;
|
|
|
|
]>
|
|
<!-- Module User's Guide -->
|
|
|
|
<chapter>
|
|
|
|
<title>&adminguide;</title>
|
|
|
|
<section>
|
|
<title>Overview</title>
|
|
<para>
|
|
This module provides a MSRP routing engine, a.k.a. MSRP relay.
|
|
MSRP (Message Session Relay Protocol) is defined by RFC4975,
|
|
and the extensions for an MSRP relay are covered in RFC4976.
|
|
</para>
|
|
<para>
|
|
A typical use of MSRP is instant messaging sessions initiated
|
|
via SIP. Unlike page-mode instant messaging, which is done via the SIP
|
|
MESSAGE request, MSRP uses a different communication channel which
|
|
is negotiated via INVITE-200 OK-ACK.
|
|
</para>
|
|
<para>
|
|
However, MSRP is still a text-based protocol. It uses several routing
|
|
mechanisms similar to what exists in SIP. Furthermore,
|
|
MSRP requres TCP, and recommends TLS for confidentiality and security.
|
|
In light of the scalability and performance of &kamailio; in handling
|
|
TCP/TLS, this module reuses &kamailio;'s core framework to
|
|
offer MSRP routing capabilities. Along with embedded Presence and XCAP
|
|
servers, &kamailio; offers now a complete solution for SIP beyond VoIP.
|
|
</para>
|
|
<para>
|
|
One of the main benefits of this module is the ability to reuse
|
|
all the other extensions that exist in the SIP server, including
|
|
accounting, authentication, authorization to database connectors,
|
|
security and DoS attack protections.
|
|
</para>
|
|
<para>
|
|
&kamailio; can handle SIP and MSRP traffic received on the same port;
|
|
the appropriate configuration file block being executed based on the
|
|
type of message. Therefore, you can use &kamailio; as a stand-alone
|
|
MSRP relay or you can have an instance handling both SIP and MSRP. Another
|
|
option is to configure &kamailio; to listen on multiple ports, some
|
|
of them for SIP and others for MSRP.
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Dependencies</title>
|
|
<section>
|
|
<title>&kamailio; Modules</title>
|
|
<para>
|
|
The following modules must be loaded before this module:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>None</emphasis>.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>External Libraries or Applications</title>
|
|
<para>
|
|
The following libraries or applications must be installed before running
|
|
&kamailio; with this module loaded:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>None</emphasis>
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
</section>
|
|
<section>
|
|
<title>Parameters</title>
|
|
<section>
|
|
<title><varname>sipmsg</varname> (int)</title>
|
|
<para>
|
|
If 1, the module will build a SIP message from MSRP frame headers,
|
|
providing it to event_route[msrp:frame-in]. All the config
|
|
file functions (apart from SIP request relay) that can be used
|
|
in a request route block can be used in msrp event_route.
|
|
</para>
|
|
<para>
|
|
<emphasis>
|
|
Default value is '1'.
|
|
</emphasis>
|
|
</para>
|
|
<example>
|
|
<title>Set <varname>sipmsg</varname> parameter</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
modparam("msrp", "sipmsg", 1)
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Functions</title>
|
|
<section>
|
|
<title>
|
|
<function moreinfo="none">msrp_relay()</function>
|
|
</title>
|
|
<para>
|
|
Relay MSRP frame according to the To-Path. This function has to be
|
|
executed for each MSRP request or reply that has to be forwarded. Note
|
|
that due to nature of MSRP transport layer, which is reliable
|
|
(TCP/TLS), there is no retransmission of MSRP frames.
|
|
</para>
|
|
|
|
<para>
|
|
This function can be used in ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>msrp</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
event_route[msrp:frame-in] {
|
|
msrp_relay();
|
|
}
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section>
|
|
<title>
|
|
<function moreinfo="none">msrp_reply(code, text [, hdrs])</function>
|
|
</title>
|
|
<para>
|
|
Send a reply for the current MSRP request, adding optional headers.
|
|
</para>
|
|
<para>
|
|
The parameter can be a pseudo-variable.
|
|
</para>
|
|
<para>
|
|
This function can be used in ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>msrp_reply</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
event_route[msrp:frame-in] {
|
|
msrp_reply("403", "Not allowed");
|
|
}
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section>
|
|
<title>
|
|
<function moreinfo="none">msrp_is_request()</function>
|
|
</title>
|
|
<para>
|
|
Return true if the MSRP frame is a request.
|
|
</para>
|
|
<para>
|
|
This function can be used in ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>msrp_is_request</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
event_route[msrp:frame-in] {
|
|
if(msrp_is_request())
|
|
{
|
|
msrp_relay();
|
|
exit;
|
|
}
|
|
}
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
|
|
<section>
|
|
<title>
|
|
<function moreinfo="none">msrp_is_reply()</function>
|
|
</title>
|
|
<para>
|
|
Return true if the MSRP frame is a reply.
|
|
</para>
|
|
<para>
|
|
This function can be used in ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>msrp_is_reply</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
event_route[msrp:frame-in] {
|
|
if(msrp_is_reply())
|
|
{
|
|
msrp_relay();
|
|
exit;
|
|
}
|
|
}
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section>
|
|
<title>
|
|
<function moreinfo="none">msrp_set_dst(addr, sock)</function>
|
|
</title>
|
|
<para>
|
|
Set destination attributes: addr - target address as MSRP URI;
|
|
sock - local socket to be used (format 'proto:ip:port').
|
|
</para>
|
|
<para>
|
|
The parameter can be a pseudo-variable.
|
|
</para>
|
|
<para>
|
|
This function can be used in ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>msrp_set_dst</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
event_route[msrp:frame-in] {
|
|
...
|
|
msrp_set_dst("msrp://127.0.0.1:8000", "tcp:127.0.0.1:5060");
|
|
...
|
|
}
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section>
|
|
<title>
|
|
<function moreinfo="none">msrp_relay_flags(flags)</function>
|
|
</title>
|
|
<para>
|
|
Set transport layer sending flags for forwarding current MSRP frame;
|
|
flags - a bitmask of flags - 1 (don't create a new connection), 2
|
|
(close connection after send).
|
|
</para>
|
|
<para>
|
|
The parameter can be a pseudo-variable.
|
|
</para>
|
|
<para>
|
|
This function can be used in ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>msrp_relay_flags</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
event_route[msrp:frame-in] {
|
|
...
|
|
msrp_relay_flags("1");
|
|
...
|
|
}
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
<section>
|
|
<title>
|
|
<function moreinfo="none">msrp_reply_flags(flags)</function>
|
|
</title>
|
|
<para>
|
|
Set transport layer sending flags for replies to the current MSRP frame;
|
|
flags - a bitmask of flags - 1 (don't create a new connection),
|
|
2 (close connection after send).
|
|
</para>
|
|
<para>
|
|
The parameter can be a pseudo-variable.
|
|
</para>
|
|
<para>
|
|
This function can be used in ANY_ROUTE.
|
|
</para>
|
|
<example>
|
|
<title><function>msrp_reply_flags</function> usage</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
event_route[msrp:frame-in] {
|
|
...
|
|
msrp_reply_flags("1");
|
|
...
|
|
}
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Pseudo Variables</title>
|
|
<para>
|
|
The module exports a pseudo-variable class, $msrp(key), to access
|
|
the MSRP frame (e.g. first line attributes, body, all frame
|
|
content).
|
|
</para>
|
|
<para>
|
|
The module exports a transformations class, 'msrpuri', to allow
|
|
access attributes of a MSRP URI.
|
|
</para>
|
|
<para>
|
|
These are documented in the appropriate Wiki pages hosted on the
|
|
project web site.
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Event Routes</title>
|
|
<para>
|
|
For each MSRP frame received from the network, the module executes
|
|
event_route[msrp:frame-in] block in the config file.
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Usage</title>
|
|
<para>
|
|
When 'sipmsg' parameter is set to 1 (which is default), the module
|
|
internally builds a SIP request from the MSRP frame and exposes it to
|
|
the config file interpreter. This way, all the functions that are
|
|
valid for SIP requests can be used safely in event_route[msrp:frame-in].
|
|
</para>
|
|
<para>
|
|
To build the SIP request, the module takes the first line and the
|
|
headers from an MSRP message and appends them to a static buffer. The
|
|
next two examples show an MSRP frame and the resulting SIP request.
|
|
</para>
|
|
<programlisting format="linespecific">
|
|
<![CDATA[
|
|
...
|
|
MSRP 6aef SEND
|
|
To-Path: msrps://a.example.org:9000/kjfjan;tcp \
|
|
msrps://b.example.net:9000/aeiug;tcp \
|
|
msrps://bob.example.net:8145/foo;tcp
|
|
From-Path: msrps://alice.example.org:7965/bar;tcp
|
|
Success-Report: yes
|
|
Byte-Range: 1-*/*
|
|
Message-ID: 87652
|
|
Content-Type: text/plain
|
|
|
|
Hi Bob, I'm about to send you a photo.
|
|
-------6aef$
|
|
...
|
|
]]>
|
|
</programlisting>
|
|
|
|
<programlisting format="linespecific">
|
|
<![CDATA[
|
|
...
|
|
MSRP sip:a@127.0.0.1 SIP/2.0
|
|
Via: SIP/2.0/UDP 127.0.0.1:9;branch=z9hG4bKa
|
|
From: <b@127.0.0.1>;tag=a
|
|
To: <a@127.0.0.1>
|
|
Call-ID: a
|
|
CSeq: 1 MSRP
|
|
Content-Length: 0
|
|
MSRP-First-Line: MSRP 6aef SEND
|
|
To-Path: msrps://a.example.org:9000/kjfjan;tcp \
|
|
msrps://b.example.net:9000/aeiug;tcp \
|
|
msrps://bob.example.net:8145/foo;tcp
|
|
From-Path: msrps://alice.example.org:7965/bar;tcp
|
|
Success-Report: yes
|
|
Byte-Range: 1-*/*
|
|
Message-ID: 87652
|
|
Content-Type: text/plain
|
|
|
|
...
|
|
]]>
|
|
</programlisting>
|
|
<para>
|
|
Note that MSRP does not permit line folding. A "\" in the examples
|
|
shows a line continuation due to the limitations of line length of this
|
|
document. Neither the backslash nor the extra CRLF is included in
|
|
the actual request or response.
|
|
</para>
|
|
<para>
|
|
As can be observed, the MSRP frame content starts with the body
|
|
of the 'MSRP-First-Line:' header. Using static content to get to a
|
|
valid SIP request is a perfect trade-off for performance.
|
|
</para>
|
|
<para>
|
|
Besides the option to access parts of MSRP frame via an
|
|
internally-built SIP message, the module exports a new pseudo-variable
|
|
class $msrp(key) which returns attributes from the MSRP frame. There is
|
|
also a new transformation, {msrpuri.key}, to get access to parts
|
|
of an MSRP URI. See the appropriate Wiki pages on the project's
|
|
web site for full details about new pseudo-variable and
|
|
transformation classes.
|
|
</para>
|
|
<para>
|
|
Next is an example of configuration file with the routing block
|
|
for MSRP frames. In this config, the SIP traffic is rejected.
|
|
</para>
|
|
<example>
|
|
<title>Event Route</title>
|
|
<programlisting format="linespecific">
|
|
...
|
|
<![CDATA[
|
|
#!KAMAILIO
|
|
|
|
debug=2
|
|
memdbg=5
|
|
memlog=5
|
|
|
|
children=4
|
|
|
|
log_stderror=yes
|
|
auto_aliases=no
|
|
|
|
tcp_accept_no_cl=yes
|
|
tcp_connection_lifetime=1810
|
|
|
|
listen=127.0.0.1:5060
|
|
|
|
mpath="modules_k/:modules/"
|
|
|
|
loadmodule "sl.so"
|
|
loadmodule "kex.so"
|
|
loadmodule "mi_fifo.so"
|
|
loadmodule "ctl.so"
|
|
loadmodule "msrp.so"
|
|
loadmodule "pv.so"
|
|
loadmodule "auth.so"
|
|
loadmodule "cfgutils.so"
|
|
loadmodule "htable.so"
|
|
loadmodule "xlog.so"
|
|
|
|
# ----- mi_fifo params -----
|
|
modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
|
|
|
|
modparam("htable", "htable", "c=>size=8;autoexpire=1800;")
|
|
|
|
request_route {
|
|
sl_send_reply("403", "No SIP Here");
|
|
exit;
|
|
}
|
|
|
|
reply_route {
|
|
drop;
|
|
}
|
|
|
|
event_route[msrp:frame-in] {
|
|
xdbg("============#[[$msrp(method)]]===========\n");
|
|
xdbg("============*[[$si:$sp]]\n");
|
|
xdbg("============ crthop: [$msrp(crthop)]\n");
|
|
xdbg("============ prevhop: [$msrp(prevhop)]\n");
|
|
xdbg("============ nexthop: [$msrp(nexthop)]\n");
|
|
xdbg("============ firsthop: [$msrp(firsthop)]\n");
|
|
xdbg("============ lasthop: [$msrp(lasthop)]\n");
|
|
xdbg("============ prevhops: [$msrp(prevhops)]\n");
|
|
xdbg("============ nexthops: [$msrp(nexthops)]\n");
|
|
xdbg("============ srcaddr: [$msrp(srcaddr)]\n");
|
|
xdbg("============ srcsock: [$msrp(srcsock)]\n");
|
|
xdbg("============ sessid: [$msrp(sessid)]\n");
|
|
|
|
msrp_reply_flags("1");
|
|
|
|
if(msrp_is_reply())
|
|
{
|
|
msrp_relay();
|
|
exit;
|
|
}
|
|
|
|
# handle AUTH MSRP requests
|
|
if($msrp(method)=="AUTH")
|
|
{
|
|
if($msrp(nexthops)>0)
|
|
{
|
|
msrp_relay();
|
|
exit;
|
|
}
|
|
# frame for local server - send Use-Path
|
|
# -- passwd can be loaded from DB based on $au
|
|
$var(passwd) = "xyz123";
|
|
if(!pv_www_authenticate("myrealm", "$var(passwd)", "0"))
|
|
{
|
|
if(auth_get_www_authenticate("myrealm", "0",
|
|
"$var(wauth)"))
|
|
{
|
|
msrp_reply("401", "Authorization Required",
|
|
"$var(wauth)");
|
|
} else {
|
|
msrp_reply("500", "Server Error");
|
|
}
|
|
exit;
|
|
}
|
|
$var(cnt) = $var(cnt) + 1;
|
|
pv_printf("$var(sessid)", "s.$(pp).$(var(cnt)).$(RANDOM)");
|
|
$sht(msrp=>$var(sessid)::srcaddr) = $msrp(srcaddr);
|
|
$sht(msrp=>$var(sessid)::srcsock) = $msrp(srcsock);
|
|
# - Use-Path: the MSRP address for server + session id
|
|
$var(UsePath) = "Use-Path: msrp://127.0.0.1:5060/"
|
|
+ $var(sessid) + ";tcp\r\n";
|
|
msrp_reply("200", "OK", "$var(UsePath)");
|
|
exit;
|
|
}
|
|
|
|
if($msrp(method)=="SEND")
|
|
{
|
|
if($msrp(nexthops)>1)
|
|
{
|
|
msrp_reply("200", "Received");
|
|
msrp_relay();
|
|
exit;
|
|
}
|
|
$var(sessid) = $msrp(sessid);
|
|
if($sht(msrp=>$var(sessid)::srcaddr) == $null)
|
|
{
|
|
# one more hop, but we don't have address in htable
|
|
msrp_reply("481", "No Such Session");
|
|
exit;
|
|
}
|
|
msrp_relay_flags("1");
|
|
msrp_set_dst("$sht(msrp=>$var(sessid)::srcaddr)",
|
|
"$sht(msrp=>$var(sessid)::srcsock)");
|
|
msrp_relay();
|
|
exit;
|
|
}
|
|
|
|
msrp_relay();
|
|
}
|
|
]]>
|
|
...
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
|
|
</chapter>
|
|
|