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.
kamailio/modules/outbound/doc/outbound_admin.xml

526 lines
11 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 C-API functions to enable &kamailio; to be
used as an outbound Edge Proxy (see RFC 5626 section 5).</para>
<para>The <emphasis>path</emphasis> and <emphasis>rr</emphasis> will
bind to this module if it is loaded before they are.</para>
<section>
<title>Edge Proxy Keep-Alives (STUN)</title>
<para>Outbound Edge Proxies MUST support STUN NAT keep-alives
on their SIP UDP ports. &kamailio; supports this though the
<quote>stun</quote> module.</para>
</section>
<section>
<title>Flow Timer</title>
<para>The maximum interval at which a User Agent must send a
keep-alive may be specified by the Registrar using the
Flow-Timer: header in 2xx responses to REGISTERs.</para>
<para>When using TCP or TLS as the SIP transport care should
be taken to set the <quote>tcp_connection_lifetime</quote>
on the Edge Proxy to a value slightly larger than the interval
the Registrar is using for flow timer. Setting
<quote>tcp_connection_lifetime</quote> to less than the
interval could cause connections to be lost, and setting it
to a value much larger than the interval will keep connections
open far longer than is required (which is wasteful).</para>
<para>Application-layer keep-alives are optional when the
underlying transport already has a keep-alive mechanism. The
WebSocket transport has a transport-layer keep-alive. When
using the WebSocket transport the
<quote>keepalive_timeout</quote> should be set to a value
a little greater than the Registrar flow timer interval and a
little less than the <quote>tcp_connection_lifetime</quote>.
</para>
</section>
<example>
<title>Edge Proxy Configuration</title>
<programlisting><![CDATA[
#!KAMAILIO
#
# Edge proxy configuration
#
#!subst "/REGISTRAR_IP/192.168.122.3/"
#!subst "/REGISTRAR_PORT/5060/"
#!substdef "/FLOW_TIMER/20/"
####### Global Parameters #########
debug=2
log_stderror=no
log_facility=LOG_LOCAL0
fork=yes
children=4
alias="example.com"
mpath="/usr/lib64/kamailio/modules"
tcp_connection_lifetime=30 # FLOW_TIMER + 10
force_rport=yes
####### Modules Section ########
loadmodule "tm.so"
loadmodule "sl.so"
loadmodule "outbound.so"
loadmodule "rr.so"
loadmodule "path.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "mi_rpc.so"
loadmodule "mi_fifo.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "stun.so"
# ----------------- setting module-specific parameters ---------------
# ----- mi_fifo params -----
modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
# ----- tm params -----
modparam("tm", "failure_reply_mode", 3)
# ----- rr params -----
modparam("rr", "append_fromtag", 0)
####### Routing Logic ########
request_route {
route(REQINIT);
if (is_method("CANCEL")) {
if (t_check_trans()) {
route(RELAY);
}
exit;
}
route(WITHINDLG);
t_check_trans();
if (is_method("REGISTER")) {
remove_hf("Route");
add_path();
$du = "sip:REGISTRAR_IP:REGISTRAR_PORT";
} else {
if (is_method("INVITE|SUBSCRIBE"))
record_route();
if (@via[2] == "") {
# From client so route to registrar...
if ($rU == $null) {
sl_send_reply("484", "Address Incomplete");
exit;
}
remove_hf("Route");
$du = "sip:REGISTRAR_IP:REGISTRAR_PORT";
} else {
# From registrar so route using "Route:" headers...
if (!loose_route()) {
switch($rc) {
case -2:
sl_send_reply("403", "Forbidden");
exit;
default:
xlog("L_ERR", "in request_route\n");
sl_reply_error();
exit;
}
}
t_on_failure("FAIL_OUTBOUND");
}
}
route(RELAY);
}
route[RELAY] {
if (!t_relay()) {
sl_reply_error();
}
exit;
}
route[REQINIT] {
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
exit;
}
if(!sanity_check("1511", "7"))
{
xlog("Malformed SIP message from $si:$sp\n");
exit;
}
}
route[WITHINDLG] {
if (has_totag()) {
if (!loose_route()) {
switch($rc) {
case -2:
sl_send_reply("403", "Forbidden");
exit;
default:
if (is_method("ACK")) {
if ( t_check_trans() ) {
route(RELAY);
exit;
} else {
exit;
}
}
sl_send_reply("404","Not Found");
}
} else {
if (is_method("NOTIFY")) {
record_route();
}
route(RELAY);
}
exit;
}
}
onreply_route {
if (!t_check_trans()) {
drop;
}
if ($rm == "REGISTER" && $rs >= 200 && $rs <= 299) {
remove_hf("Flow-Timer");
if ($(hdr(Require)[*])=~"outbound")
insert_hf("Flow-Timer: FLOW_TIMER\r\n", "Call-ID");
}
}
failure_route[FAIL_OUTBOUND] {
if (t_branch_timeout() || !t_branch_replied()) {
send_reply("430", "Flow Failed");
}
}
]]></programlisting>
</example>
<example>
<title>Registrar Configuration</title>
<programlisting><![CDATA[
MAILIO
#
# Registrar configuration
#
####### Global Parameters #########
debug=2
log_stderror=no
log_facility=LOG_LOCAL0
fork=yes
children=4
alias="example.com"
mpath="/usr/lib64/kamailio/modules"
####### Modules Section ########
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "mi_rpc.so"
loadmodule "mi_fifo.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
# ----------------- setting module-specific parameters ---------------
# ----- mi_fifo params -----
modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
# ----- tm params -----
modparam("tm", "failure_reply_mode", 3)
modparam("tm", "restart_fr_on_each_reply", 0)
modparam("tm", "contact_flows_avp", "tm_contact_flows")
modparam("tm", "contacts_avp", "tm_contacts")
# ----- rr params -----
modparam("rr", "append_fromtag", 0)
# ----- registrar params -----
modparam("registrar", "use_path", 1)
modparam("registrar", "gruu_enabled", 1)
modparam("registrar", "outbound_mode", 1)
####### Routing Logic ########
request_route {
route(REQINIT);
if (is_method("CANCEL")) {
if (t_check_trans()) {
route(RELAY);
}
exit;
}
route(WITHINDLG);
t_check_trans();
remove_hf("Route");
if (is_method("INVITE|SUBSCRIBE"))
record_route();
route(REGISTRAR);
if ($rU==$null) {
xlog("L_INFO", "Address Incomplete\n");
send_reply("484","Address Incomplete");
exit;
}
route(LOCATION);
}
route[RELAY] {
if (!t_relay()) {
xlog("L_ERR", "t_relay() failed\n");
sl_reply_error();
}
exit;
}
route[REQINIT] {
if (!mf_process_maxfwd_header("10")) {
xlog("L_INFO", "Too Many Hops\n");
send_reply("483","Too Many Hops");
exit;
}
if(!sanity_check("1511", "7"))
{
xlog("Malformed SIP message from $si:$sp\n");
exit;
}
}
route[WITHINDLG] {
if (has_totag()) {
if (loose_route()) {
if (is_method("NOTIFY")) {
record_route();
}
route(RELAY);
} else {
if (is_method("ACK")) {
if (t_check_trans()) {
route(RELAY);
exit;
} else {
exit;
}
}
xlog("L_INFO", "Not Found");
send_reply("404","Not Found");
}
exit;
}
}
route[REGISTRAR] {
if (is_method("REGISTER"))
{
if (!save("location")) {
xlog("L_ERR", "Unable to save location\n");
sl_reply_error();
}
exit;
}
}
route[LOCATION] {
if (!lookup("location")) {
$var(rc) = $rc;
t_newtran();
switch ($var(rc)) {
case -1:
case -3:
send_reply("404", "Not Found");
exit;
case -2:
send_reply("405", "Method Not Allowed");
exit;
}
}
if (!t_load_contacts() || !t_next_contacts()) {
xlog("L_ERR", "t_(load|next)_contacts() failed\n");
sl_reply_error();
exit;
}
t_on_failure("FAIL_TRANSACTION");
t_on_branch_failure("FAIL-BRANCH");
route(RELAY);
exit;
}
onreply_route {
if (!t_check_trans()) {
drop;
}
}
failure_route[FAIL_TRANSACTION] {
if (!t_check_status("6[0-9][0-9]")) {
if (t_next_contacts()) {
t_relay();
exit;
}
}
if (t_check_status("430")) {
t_reply("480", "Temporarily Unavailable");
exit;
}
}
event_route[tm:branch-failure:FAIL-BRANCH] {
if (t_check_status("403|430")
|| (t_branch_timeout() && !t_branch_replied())) {
unregister("location", "$tu", "$T_reply_ruid");
if (t_next_contact_flow()) {
t_on_branch_failure("FAIL-BRANCH");
t_relay();
}
}
}
]]></programlisting>
</example>
</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>
<para>
The following modules are required to make proper use of this
module:
<itemizedlist>
<listitem>
<para><emphasis>stun</emphasis>.</para>
</listitem>
</itemizedlist>
</para>
</section>
<section>
<title>External Libraries or Applications</title>
<para>
The following libraries must be installed before running
&kamailio; with this module loaded:
<itemizedlist>
<listitem>
<para><emphasis>OpenSSL</emphasis>.</para>
</listitem>
</itemizedlist>
</para>
</section>
</section>
<section>
<title>Parameters</title>
<section>
<title><varname>force_outbound_flag</varname> (integer)</title>
<para>A flag which, if set for a request, will force
<emphasis>path</emphasis> and <emphasis>rr</emphasis> to add
flow tokens to Path: and Record-Route: headers regardless of
the request contents.</para>
<para><emphasis>Default value is -1.</emphasis></para>
<example>
<title>Set <varname>force_outbound_flag</varname> parameter
</title>
<programlisting format="linespecific">
...
modparam("outbound", "force_outbound_flag", 1)
...
</programlisting>
</example>
</section>
<section>
<title><varname>force_no_outbound_flag</varname> (integer)</title>
<para>A flag which, if set for a request, will force
<emphasis>path</emphasis> and <emphasis>rr</emphasis> not
to add flow tokens to Path: and Record-Route: headers
regardless of the request contents.</para>
<para><emphasis>Default value is -1.</emphasis></para>
<example>
<title>Set <varname>force_no_outbound_flag</varname> parameter
</title>
<programlisting format="linespecific">
...
modparam("outbound", "force_no_outbound_flag", 2)
...
</programlisting>
</example>
</section>
</section>
<section>
<title>Functions</title>
<para><emphasis>None</emphasis></para>
</section>
<section>
<title>MI Commands</title>
<para><emphasis>None</emphasis></para>
</section>
</chapter>