Kamailio v5.8.0 is out – it comes with 4 new modules and a large set of
improvements touching again more than 50 existing modules.
You can read a bit more detailed release notes at:
* https://www.kamailio.org/w/kamailio-v5-8-0-release-notes/
Many thanks to all developers and community members that made possible
this release.
v5.8.0 brings more flexibility and optimizations across many existing
components and modules, new parameters, functions, variables and
transformations.
Enjoy Kamailio v5.8.0!
Thank you for flying Kamailio!
Daniel
--
Daniel-Constantin Mierla (@ asipto.com)
twitter.com/miconda -- linkedin.com/in/miconda
Kamailio Consultancy, Training and Development Services -- asipto.com
Kamailio World Conference, April 18-19, 2024, Berlin -- kamailioworld.com
Hi all,
I am using uac_replace_to to replace the TO header on requests. I
understand it can only be called once per message and the recommendation is
to store the updated value in a pvar and apply it in the branch route.
However in my scenario I wish to first try one endpoint and then if it gets
a 4XX response forward it to another UAC, and update the TO accordingly.
Currently trying to call uac_replace_to twice shows an error and corrupts
the TO header. Is there a work around for this?
Thanks again
Matthew
Hello,
discussed a bit during the online Kamailio devel meeting, it is time to
set the milestones towards the next major Kamailio release series v5.8.x.
If no other suggestions that suit more developers, I would propose to
freeze by end of this month or early February, then test for about 4
weeks as usual and release by end of February or during March.
If anyone wants to add new features/modules, they have to be published
till freezing date, either pushed in the git repository or proposed as
pull request.
Cheers,
Daniel
--
Daniel-Constantin Mierla (@ asipto.com)
twitter.com/miconda -- linkedin.com/in/miconda
Kamailio Consultancy, Training and Development Services -- asipto.com
Kamailio Advanced Training, February 20-22, 2024 -- asipto.com
Kamailio World Conference, April 18-19, 2024, Berlin -- kamailioworld.com
Hi all,
I am using Kamailio 5.7.4 on a Debian 12 machine, with a Python Kemi based
config. I am seeing some intermittent failures when accessing an instance
variable within a function called by rtimer.
I'm using the rtimer module with the following parameters:
modparam("rtimer", "timer", "name=hello;interval=5;mode=0;")
modparam("rtimer", "exec", "timer=hello;route=ksr_route_hello")
I initialise the kamailio class, and instance variable like this:
class kamailio:
def __init__(self):
self.hello = "hi"
Within the class I have the following route function:
def ksr_route_hello(self, msg, evname):
KSR.info("Running ksr_route_hello\n")
KSR.info(f"Hello? {self.hello}\n")
Then in the logs I see it sometimes works, and sometimes fails:
9(15) INFO: <core> [core/kemi.c:106]: sr_kemi_core_info(): Running
ksr_route_hello
9(15) INFO: <core> [core/kemi.c:106]: sr_kemi_core_info(): Hello? hi
9(15) INFO: <core> [core/kemi.c:106]: sr_kemi_core_info(): Running
ksr_route_hello
9(15) ERROR: app_python3 [python_support.c:167]:
python_handle_exception(): apy_exec: ksr_route_hello(rtimer): Unhandled
exception in the Python code:
TypeError: 'NoneType' object cannot be interpreted as an integer
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/etc/kamailio/kamailio.py", line 1007, in ksr_route_hello
KSR.info("Running ksr_route_hello\n")
SystemError: <built-in function info> returned a result with an exception
set
Does anyone know where I'm going wrong?
Thanks
Matthew
Hi all,
it might be a minor issue, or it might not be an issue at all, but I stumbled over following statements in RFC 3261:
Chapter 16.6 Request Forwarding (of a proxy)
1. Copy request
The proxy starts with a copy of the received request. The copy
MUST initially contain all of the header fields from the
received request. Fields not detailed in the processing
described below MUST NOT be removed. The copy SHOULD maintain
the ordering of the header fields as in the received request.
The proxy MUST NOT reorder field values with a common field
name (See Section 7.3.1<https://www.rfc-editor.org/rfc/rfc3261.html#section-7.3.1>). The proxy MUST NOT add to, modify,
or remove the message body.
An actual implementation need not perform a copy; the primary
requirement is that the processing for each next hop begin with
the same request.
Chapter 16.7 Response Processing (at a proxy)
9. Forward response
After performing the processing described in steps "Aggregate
Authorization Header Field Values" through "Record-Route", the
proxy MAY perform any feature specific manipulations on the
selected response. The proxy MUST NOT add to, modify, or
remove the message body. Unless otherwise specified, the proxy
MUST NOT remove any header field values other than the Via
header field value discussed in Section 16.7<https://www.rfc-editor.org/rfc/rfc3261.html#section-16.7> Item 3. In
particular, the proxy MUST NOT remove any "received" parameter
On the other hand, everywhere in the Internet (starting with stackoverflow), you can read it is OK, if a SIP proxy modifies a body, and also kamailio allows it.
Might be a question for the coffee break.
All the best
Christoph
Trying to setup Kamailio with MS Teams Direct Routing.
I am familiar with the integration steps required by Microsoft (using contact header as FQDN, certified CA for certificate) aswell as the famous guide; https://skalatan.de/en/blog/kamailio-sbc-teams + https://learn.microsoft.com/en-us/microsoftteams/direct-routing-protocols-s…
Sending any SIP requests (Invite, ACK, BYE) toward MS is working fine (with provisional response received in Kamailio) - so there is obviously a working connection between Kamailio <-> MS Direct Routing environment.
HOWEVER, once Kamailio is forwarding SIP responses to MS (provisional responses/200 OK received from UAS), then Kamailio is closing the TCP connection.
Please see attached logs below.
Any idea why Kamailio is closing the connection when trying to send provisional responses to MS?
- Using t_realy on original invite from MS
- tcp_reuse_port=yes, tcp_rd_buf_size = 16384, tcp_connection_lifetime=3605, children=8, socket_workers=4
- No override rules in firewall
- OS; debian:11.7
- Notice that TLS connection is made on port :26627 - however, MS sends port :5061 in VIA header (on first Invite). This seems to me to be a conflict in ports.
https://www.kamailio.org/wiki/cookbooks/5.4.x/core#reply_route
"There is no network route that can be enforced for a SIP reply - it is sent based on Via header, according to SIP RFC3261"
-----
Handshake complete for 52.114.76.76:26627
19(43) DEBUG: tls [tls_domain.c:818]: sr_ssl_ctx_info_callback(): SSL handshake done
19(43) DEBUG: tls [tls_server.c:473]: tls_accept(): TLS accept successful
19(43) DEBUG: tls [tls_server.c:476]: tls_accept(): tls_accept: new connection from 52.114.76.76:26627 using TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256
19(43) DEBUG: tls [tls_server.c:480]: tls_accept(): tls_accept: local socket: 10.129.0.91:5061
19(43) DEBUG: tls [tls_server.c:420]: tls_dump_cert_info(): tls_accept: client certificate subject:/C=US/ST=WA/L=Redmond/O=Microsoft Corporation/CN=sip.pstnhub.microsoft.com
19(43) DEBUG: tls [tls_server.c:424]: tls_dump_cert_info(): tls_accept: client certificate issuer:/C=US/O=Microsoft Corporation/CN=Microsoft Azure RSA TLS Issuing CA 04
-----
Kamailio trying to forward SIP response "183" to MS (response received from UAS).
Kamailio finds active connection by ID 13 / 0x7f4ecad0be08
20(44) DEBUG: {2 1 INVITE e926eb82d1a25bdc9ba03048cdbc5c77} <core> [core/tcp_main.c:1722]: _tcpconn_find(): found connection by id: 13
20(44) DEBUG: {2 1 INVITE e926eb82d1a25bdc9ba03048cdbc5c77} <core> [core/tcp_main.c:2627]: tcpconn_send_put(): tcp connection found (0x7f4ecad0be08), acquiring fd
20(44) DEBUG: {2 1 INVITE e926eb82d1a25bdc9ba03048cdbc5c77} <core> [core/tcp_main.c:2637]: tcpconn_send_put(): c=0x7f4ecad0be08, n=16
23(47) DEBUG: <core> [core/tcp_main.c:3982]: handle_ser_child(): read response= 7f4ecad0be08, 2, fd -1 from 20 (44)
20(44) DEBUG: {2 1 INVITE e926eb82d1a25bdc9ba03048cdbc5c77} <core> [core/tcp_main.c:2665]: tcpconn_send_put(): after receive_fd: c= 0x7f4ecad0be08 n=8 fd=12
20(44) DEBUG: {2 1 INVITE e926eb82d1a25bdc9ba03048cdbc5c77} <core> [core/tcp_main.c:2842]: tcpconn_do_send(): sending...
20(44) DEBUG: {2 1 INVITE e926eb82d1a25bdc9ba03048cdbc5c77} <core> [core/tcp_main.c:2878]: tcpconn_do_send(): after real write: c= 0x7f4ecad0be08 n=1191 fd=12
-----
Kamailio immediately closes the connection due to EOF.
19(43) DEBUG: <core> [core/tcp_read.c:280]: tcp_read_data(): EOF on connection 0x7f4ecad0be08 (state: 0, flags: 4018) - FD 10, bytes 0, rd-flags 10000 ([52.114.76.76]:26627 -> [52.114.76.76]:5061)19(43) DEBUG: <core> [core/tcp_read.c:1544]: tcp_read_req(): EOF
19(43) DEBUG: <core> [core/io_wait.h:597]: io_watch_del(): DBG: io_watch_del (0x555b3cf20260, 10, -1, 0x10) fd_no=2 called
19(43) DEBUG: <core> [core/tcp_read.c:1927]: handle_io(): removing from list 0x7f4ecad0be08 id 13 fd 10, state 2, flags 4018, main fd 57, refcnt 2 ([52.114.76.76]:26627 -> [52.114.76.76]:5061)
19(43) DEBUG: <core> [core/tcp_read.c:1702]: release_tcpconn(): releasing con 0x7f4ecad0be08, state -1, fd=10, id=13 ([52.114.76.76]:26627 -> [52.114.76.76]:5061)
Hello all,
I can't seem to find a way to make interim accounting requests for RADIUS. Can you help me with this?
I can't find any native way for doing this. I've thought of getting a custom timer for each dialog and run a event route similar do dialog:start or dialog:end. Is that possible?
Cheers,
Duarte Rocha
Hello guys,
I'm trying to add an xml with a boundary to an outgoing INVITE. But if i do:
set_body_multipart("$rb", "application/sdp", "delimiter");
msg_apply_changes();
append_body_part("$var(something)", "application/pidf+xml");
msg_apply_changes();
but kamailio adds the SDP, but NOT the second $var(something). If i switch
them and add firs the var, and then the SDP. kamailio adds the contents of
$var(something) but NOT the SDP.... point is it doesn't add the second
append
Thanks!!!
Regards,
David Villasmil
email: david.villasmil.work(a)gmail.com
phone: +34669448337
hi,
i have kamailio gw (5.6.x) for voxbone. dispatcher module
voxbone has separated inbound/outboud and prohibit sip options to
"inbound" IP
#traffic from voxbone
20 sip:81.201.82.45:5060;transport=udp 1 0 duid=abc;socket=udp:x.x.x.x:5060
#traffic TO voxbone
30 sip:81.201.89.110:5060;transport=udp 0 0 duid=abc;socket=udp:x.x.x.x:5060
is it possible send sip options per GW with dispatcher module?
i tried flag "1 (bit at index 0 - 1 <<0) - inactive destination"
https://www.kamailio.org/docs/modules/devel/modules/dispatcher.html#idm1059
Marek
Hi all!
got a weird behavior that I cannot understand the reason for...
In our LAB environment, we have 2 Asterisk instances (version 13.38.3 and
chan_sip) and 1 Kamailio 5.7 in between.
All servers are in the same network, so, there is no NAT involved. No
RTPEngine neither.
Network is 10.20.0.0/24 and Asterisk #1 has IP .1 Asterisk #2 has IP .3
and Kamailio has IP .5
The Asterisk servers are used only for testing, nothing serious. However,
Kamailio is setup to use RTJson requesting routes to a Routing Server on
the same network. And it works fine.
Both Asterisk servers have the same dialplan, which only Answers the call
and plays MOH on both ends so that RTP audio streams both ways.
When making a call on Asterisk Server #1 via command line to go directly to
Asterisk Server #2 without using Kamailio (CLI> channel originate SIP/
123(a)10.20.0.*3* application MusicOnHold() ) the Asterisk #2 receives the
call, answers and plays MOH too and I can see RTP streams coming from both
ends correctly.
However, if I use Kamailio to proxy the call generated from Asterisk #1 to
Asterisk #2, using similar command line instruction (CLI> channel originate
SIP/123(a)10.20.0.5 application MusicOnHold() ), the call is indeed received
on Kamailio who then sends it to Asterisk #2, who answers the call and
plays MOH, *but* despite the audio stream being sent to Asterisk #1 it is
never received, however audio from Asterisk #1 is received by Asterisk #2,
which configures a typical One Way Audio issue due to NAT.
This is where it gets strange, because there is no NAT, SDP on INVITE and
SIP 200 messages seem OK, as far as I understand it.
Also, Asterisk servers have SIP configuration with directmedia enabled and
NAT disabled to make sure that media is direct. But I have also tried with
directmedia disabled and NAT enabled and get identical results.
I am most probably missing some tiny detail, but I have no clue.... and I
bet it is simple and stupid....
Could another pair of eyes help me with this? What is wrong? Do I really
need RTPEngine even when the network has no NAT? I am sure it would work
that way, but it doesn't make sense...
Here are some screenshots:
Call Scenario #1 - direct call from Asterisk #1 to Asterisk #2 without
Kamailio in between:
Invite from Asterisk #1 to Asterisk #2 with direct media between both ends:
[image: image.png]
Replies from Asterisk #2 to Asterisk #1 with direct media between both ends:
[image: image.png]
Call Scenario #2 - call from Asterisk #1 using Kamailio to relay call to
Asterisk #2, with one way audio
Invite from Asterisk #1 to Asterisk #2 via Kamailio with SDP details:
[image: image.png]
Invite from Kamailio relayed to Asterisk #2 with SDP details from Asterisk
#1 identical to above:
[image: image.png]
Reply from Asterisk #2 to Kamailio with SDP details:
[image: image.png]
Reply from Kamailio to Asterisk #2 with SDP details from Asterisk #2
identical to above:
[image: image.png]
As we can see, SDP details seem OK, but if I check call flow on Asterisk
#1, I can only find 1 RTP channel with audio coming from Asterisk #2
[image: image.png]
and the same on Asterisk #2 :
[image: image.png]
My Kamailio.cfg :
#!KAMAILIO
#
# config file for SIPProxy
# - load balancing of VoIP calls
# - no TPC listening
#
# Kamailio (OpenSER) SIP Server v3.2
# - web: http://www.kamailio.org
# - git: http://sip-router.org
#
#
# Refer to the Core CookBook at http://www.kamailio.org/dokuwiki/doku.php
# for an explanation of possible statements, functions and parameters.
#
# Several features can be enabled using '#!define WITH_FEATURE' directives:
#
# *** To run in debug mode:
# - define WITH_DEBUG
#
#!define WITH_DEBUG
###!define WITH_NAT
#!define WITH_PSTN
/* enables Accounting Log functions */
#!define FLT_ACC 1
/* enable Accounting of missed or failed calls */
#!define FLT_ACCMISSED 2
#!define FLT_ACCFAILED 3
/* defines DB connection string */
#!ifndef DBURL
#!define DBURL "mysql://kamailio:kamailio@10.20.0.1:3306/kamailio"
#!endif
# - the value for 'use_domain' parameters
#!define MULTIDOMAIN 1
####### Global Parameters #########
#!ifdef WITH_DEBUG
debug=4
log_stderror=no
#!else
debug=2
log_stderror=no
#!endif
#!define FLT_DISPATCH_SETID 1
#!define FLT_FS 10
#!define FLT_NATS 5
#!define FLB_NATB 6
#!define FLB_NATSIPPING 7
#!define FLT_SRC_ALLOWED 8
#!define FLT_DST_INTERNAL_IP 9
#!define FLT_SRC_INTERNAL_IP 10
#!substdef "!INTERNAL_IP_NET!10.20.0.0/24!g"
#!substdef "!INTERNAL_IP_ADDR!10.20.0.2!g"
#!substdef "!EXTERNAL_IP_ADDR!10.20.0.2!g"
#!ifndef HTTP_ASYNC_CLIENT_WORKERS
#!define HTTP_ASYNC_CLIENT_WORKERS 8
#!endif
/* add API http timeout */
#!define HTTP_API_TIMEOUT 5000
#!define HTTP_API_ROUTING_ENDPOINT "http://10.246.212.40:7778/get_route"
/* DMQ SIP message sharing */
#!define DMQ_PORT 5062
#!define DMQ_LISTEN "sip:10.20.0.2:5062"
#!define DMQ_SERVER_ADDRESS "sip:10.20.0.2:5062"
#!define DMQ_NOTIFICATION_ADDRESS "sip:10.20.0.4:5062"
memdbg=5
memlog=5
log_facility=LOG_LOCAL0
log_prefix="{$mt $hdr(CSeq) $ci} "
fork=yes
children=8
/* comment the next line to enable TCP - all trunks are UDP only */
disable_tcp=yes
/* uncomment the next line to disable the auto discovery of local aliases
based on revers DNS on IPs (default on) */
auto_aliases=no
port=5060
/* uncomment and configure the following line if you want Kamailio to
bind on a specific interface/port/proto (default bind on all available)
*/
listen=udp:10.20.0.5:5060 advertise 10.20.0.5:5060
listen=tcp:10.20.0.5:5060 advertise 10.20.0.5:5060
listen=udp:10.20.0.2:5062
advertised_address="10.20.0.5";
sip_warning=no;
use_dns_failover = on;
####### Modules Section ########
#set module path
mpath="/usr/local/lib64/kamailio/modules/"
loadmodule "db_mysql.so"
loadmodule "jsonrpcs.so"
loadmodule "kex.so"
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "acc.so"
loadmodule "usrloc.so"
loadmodule "nathelper.so"
#loadmodule "rtimer.so"
#loadmodule "sqlops.so"
# --- CPS Limiter
# --- end of CPS Limiter
loadmodule "ipops.so"
loadmodule "textopsx.so"
loadmodule "sdpops.so"
loadmodule "http_async_client.so"
loadmodule "rtjson.so"
loadmodule "jansson.so"
loadmodule "dmq.so"
loadmodule "dmq_usrloc.so"
loadmodule "htable.so"
loadmodule "dialog.so"
#!ifdef WITH_DEBUG
loadmodule "debugger.so"
#!endif
#!ifdef WITH_DEBUG
# ----- debugger params -----
modparam("debugger", "log_level_name", "exec")
#!endif
# ----------------- setting module-specific parameters ---------------
# ----- jsonrpcs params -----
modparam("jsonrpcs", "fifo_name", "/var/run/kamailio/kamailio_rpc.fifo")
modparam("jsonrpcs", "pretty_format", 1)
# ----- rr params -----
modparam("jsonrpcs", "fifo_name", "/var/run/kamailio/kamailio_rpc.fifo")
modparam("jsonrpcs", "pretty_format", 1)
# ----- rr params -----
# add value to ;lr param to cope with most of the UAs
modparam("rr", "enable_full_lr", 1)
# do not append from tag to the RR (no need for this script)
modparam("rr", "append_fromtag", 0)
# ----- acc params -----
modparam("acc", "failed_transaction_flag", 3)
modparam("acc",
"log_extra","src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd;src_ip=$si")
# ----- acc params -----
/* what special events should be accounted ? */
modparam("acc", "early_media", 0)
modparam("acc", "report_ack", 0)
modparam("acc", "report_cancels", 0)
/* by default we do not adjust the direct of the sequential requests.
if you enable this parameter, be sure the enable "append_fromtag"
in "rr" module */
modparam("acc", "detect_direction", 0)
/* account triggers (flags) */
modparam("acc", "log_flag", FLT_ACC)
modparam("acc", "log_missed_flag", FLT_ACCMISSED)
modparam("acc",
"log_extra","src_user=$fU;src_domain=$fd;src_ip=$si;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
modparam("acc", "failed_transaction_flag", FLT_ACCFAILED)
/* enhanced DB accounting */
modparam("acc", "db_flag", FLT_ACC)
modparam("acc", "db_missed_flag", FLT_ACCMISSED)
modparam("acc", "db_url", DBURL)
modparam("acc",
"db_extra","src_user=$fU;src_domain=$fd;src_ip=$si;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
//;calltype=$avp(calltype)")
# ----- tm params -----
# ----- the TM module enables stateful processing of SIP requests
modparam("tm", "fr_timer", 5000)
modparam("tm", "fr_inv_timer", 60000)
modparam("tm", "remap_503_500", 0)
# ----- usrloc params -----
/* enable DB persistency for location entries */
modparam("usrloc", "db_url", DBURL)
modparam("usrloc", "db_mode", 2)
modparam("usrloc", "use_domain", MULTIDOMAIN)
# params needed for NAT traversal in other modules
modparam("usrloc", "nat_bflag", FLB_NATB)
# ----- nathelper params -----
modparam("nathelper", "received_avp", "$avp(s:rcv)")
modparam("nathelper", "natping_interval", 30)
modparam("nathelper", "ping_nated_only", 1)
modparam("nathelper", "sipping_bflag", FLB_NATSIPPING)
modparam("nathelper", "sipping_from", "sip:ping@kamailio.org")
#modparam("rtimer", "timer", "name=cdr;interval=300;mode=1;")
#modparam("rtimer", "exec", "timer=cdr;route=CDRS")
#modparam("sqlops", "sqlcon", "ca=>mysql://
kamailio:kamailiorw@10.19.139.113:3306/kamailio")
#modparam("dmq", "server_socket", DMQ_SERVER_SOCKET )
modparam("dmq", "server_address", DMQ_SERVER_ADDRESS )
modparam("dmq", "notification_address", DMQ_NOTIFICATION_ADDRESS )
modparam("dmq", "multi_notify", 1)
modparam("dmq", "num_workers", 4)
modparam("dmq", "ping_interval", 60)
modparam("dmq_usrloc", "enable", 1)
# -- CPS Limiter
modparam("htable", "htable", "rhs=>size=32;initval=0;autoexpire=10;")
modparam("htable", "htable", "rhm=>size=32;initval=0;autoexpire=120;")
modparam("htable", "enable_dmq", 1)
modparam("htable", "dmq_init_sync", 1)
modparam("dialog", "profiles_with_value", "concurrent_calls")
modparam("dialog", "enable_dmq", 1)
# ----- http_async_client params -----
modparam("http_async_client", "workers", HTTP_ASYNC_CLIENT_WORKERS)
modparam("http_async_client", "connection_timeout", 2000)
####### Routing Logic ########
# main request routing logic
route {
if (is_method("KDMQ") && $Rp == 5062)
{
dmq_handle_message();
}
xlog("L_INFO"," ********** Route START ***********");
# log the basic info regarding this call
xlog("L_INFO","start|\n");
xlog("L_INFO","===================================================\n");
xlog("L_INFO","New SIP message $rm with call-ID $ci \n");
xlog("L_INFO","---------------------------------------------------\n");
xlog("L_INFO"," received $pr request $rm $ou\n");
xlog("L_INFO"," source $si:$sp\n");
xlog("L_INFO"," from $fu\n");
xlog("L_INFO"," to $tu\n");
xlog("L_INFO","---------------------------------------------------\n");
xlog("L_INFO","---------------------------------------------------\n");
# OPTIONS requests without a username in the Request-URI but one
# of our domains or IPs are addressed to the proxy itself and
# can be answered statelessly.
if (is_method("OPTIONS"))
{
sl_send_reply("200","OK");
exit;
}
if ($fU=="ping")
{
sl_send_reply("200","OK");
exit;
}
# extract original source ip / port from X-forwarded-For header
route(HANDLE_X_FORWARDED_FOR);
# per request initial checks
route(REQINIT);
# NAT detection
route(NATDETECT);
# handle requests within SIP dialogs
### only initial requests (no To tag)
# CANCEL processing
if (is_method("CANCEL"))
{
if (t_check_trans()){
route(RELAY);
}
exit;
}
# handle retransmissions
if (!is_method("ACK")) {
if(t_precheck_trans()) {
t_check_trans();
xlog("L_INFO", "ROUTE - Exiting after Retransmission check - method $rm");
exit;
}
t_check_trans();
}
route(WITHINDLG);
# record routing for dialog forming requests (in case they are routed)
# - remove preloaded route headers
xlog("L_INFO", "ROUTE - Removing Headers");
remove_hf("Route");
if (is_method("INVITE|SUBSCRIBE")){
t_on_failure("MANAGE_FAILURE");
xlog("L_INFO", "ROUTE - Recording Route");
record_route();
if (is_method("INVITE") && is_request()) {
if (has_body("application/sdp")) {
xlog("L_INFO", "ROUTE - goiing to t_on_reply[ON_REPLY]\n");
t_on_reply("ON_REPLY");
}
}
}
if ($rU==$null)
{
# request with no Username in RURI
sl_send_reply("484","ROUTE - Address Incomplete");
exit;
}
route(TOCARRIER);
xlog("L_INFO", " ********** Route END *************");
}
# extract original source ip / port from X-forwarded-For header
route[HANDLE_X_FORWARDED_FOR] {
if (is_present_hf("X-Forwarded-For")) {
$var(source_ip) = $(hdr(X-Forwarded-For){s.select,0,:});
$var(source_port) = $(hdr(X-Forwarded-For){s.select,1,:});
} else {
$var(source_ip) = $si;
$var(source_port) = $sp;
}
$var(to_number) = $rU;
}
route[RELAY_API] {
xlog("L_INFO","RELAY_API - from_ip $var(source_ip):$var(source_port)
from_number $fU to_number $ru");
$http_req(all) = $null;
$http_req(suspend) = 1;
$http_req(timeout) = HTTP_API_TIMEOUT;
$http_req(method) = "POST";
$http_req(hdr) = "Content-Type: application/json";
jansson_set("string","from_ip",$var(source_ip), "$var(http_routing_query)");
jansson_set("string","from_port",$var(source_port),
"$var(http_routing_query)");
jansson_set("string","from_number",$fU, "$var(http_routing_query)");
jansson_set("string","to_number",$var(to_number) ,
"$var(http_routing_query)");
xlog("L_INFO","RELAY_API - API ASYNC ROUTING REQUEST:
$var(http_routing_query)\n");
$http_req(body) = $var(http_routing_query);
t_newtran();
http_async_query(HTTP_API_ROUTING_ENDPOINT, "RELAY_API_RESPONSE");
}
# Relay request using the API (response)
route[RELAY_API_RESPONSE] {
if ($http_ok==1 && $http_rs==200)
{
xlog("L_INFO","RELAY_API_RESPONSE - RESPONSE: $http_rb\n");
if (jansson_get("rtjson", $http_rb, "$var(rtjson)")) {
xlog("L_INFO","RELAY_API_RESPONSE - $var(rtjson)");
rtjson_init_routes("$var(rtjson)");
rtjson_push_routes();
# relay the message
t_on_branch("MANAGE_BRANCH");
t_on_failure("MANAGE_FAILURE");
route(RELAY);
return;
}
}
send_reply(500, "API Not Available - http response = $http_rs $http_ok");
exit;
}
onreply_route[ON_REPLY] {
xlog("L_INFO", "ON_REPLY - In onreply_route[ON_REPLY] $rs");
# on reply
if (t_check_status("183|180|200")) {
xlog("L_INFO", "ON_REPLY - Fixing Contacts");
# subst_hf("Contact","/@.*:/@EXTERNAL_IP_ADDR:/","a");
//subst_hf("Record-Route","/INTERNAL_IP_ADDR/EXTERNAL_IP_ADDR/","f");
}
if (has_body("application/sdp")){
if (sdp_remove_line_by_prefix("a=maxptime")){
xlog("L_INFO", "ON_REPLY - remove maxptime ");
msg_apply_changes();
}
else{
xlog("L_INFO", "ON_REPLY - did not removed maxptime ");
}
}
if (t_check_status("408")) {
xlog("L_INFO", "ROUTE - Handling 408 Timeout\n");
}
}
route[TOCARRIER]{
#using rtjson, unsomment following line
route(RELAY_API);
}
# Per SIP request initial checks
route[REQINIT] {
xlog("L_INFO", "REQINIT - Starting");
if (!mf_process_maxfwd_header("10")) {
xlog("L_INFO", "REQINIT - 483 - Too Many Hops");
sl_send_reply("483","Too Many Hops");
exit;
}
if(!sanity_check("1511", "7"))
{
xlog("L_INFO","REQINIT - Sanity Check -> Malformed SIP message from
$si:$sp\n");
exit;
}
}
# Caller NAT detection
route[NATDETECT] {
xlog("L_INFO", "NATDETECT - Entering");
#!ifdef WITH_NAT
force_rport();
if (nat_uac_test("19")) {
if (is_method("REGISTER")) {
xlog("L_INFO", "NATDETECT - Fix Nated Register");
fix_nated_register();
} else {
if(is_first_hop()){
xlog("L_INFO", "NATDETECT - Set Contact Alias");
set_contact_alias();
}
}
xlog("L_INFO", "NATDETECT - Set FLT_NATS" + FLT_NATS);
setflag(FLT_NATS);
}
#!endif
xlog("L_INFO", "NATDETECT - NAT Detect set FLT_NTS = " + FLT_NATS);
return;
}
# Handle requests within SIP dialogs
route[WITHINDLG] {
xlog("L_INFO", "WITHINDLG - Entering");
if (!has_totag()) return;
if (is_present_hf("Route") && $hdrc(Route)==1)
{
if (search_hf("Route", ".*EXTERNAL_IP_ADDR.*", "f"))
{
xlog("L_INFO", "WITHINDLG - Removing the route to self");
remove_hf("Route");
}
}
# sequential request within a dialog should
# take the path determined by record-routing
if (loose_route()) {
route(DLGURI);
if (is_method("BYE|CANCEL")) {
setflag(FLT_ACC); # do accounting ...
setflag(FLT_ACCFAILED); # ... even if the transaction fails
}
else if ( is_method("ACK") ) {
# ACK is forwarded statelessy
xlog("L_INFO", "WITHINDLG - Going to NATMANAGE");
route(NATMANAGE);
}
else if ( is_method("NOTIFY") ) {
#Add Record-Route for in-dialog NOTIFY as per RFC 6665.
record_route();
}
if(is_method("BYE"))
xlog("L_INFO", "WITHINDLG - BYE message from $rU");
route(RELAY);
exit;
}
if ( is_method("ACK|BYE|INVITE|UPDATE") ) {
if ( t_check_trans() ) {
# no loose-route, but stateful ACK;
# must be an ACK after a 487
# or e.g. 404 from upstream server
route(RELAY);
exit;
} else {
# ACK without matching transaction. Try to route anyway - being optimistic
# since it has at least a To Tag
route(RELAY);
exit;
}
}
sl_send_reply("404","Not here");
xlog("L_INFO", "WITHINDLG - Finishing WITHINDLG");
exit;
}
# URI update for dialog requests
route[DLGURI] {
xlog("L_INFO", "WITHINDLG - Entering DLGURI");
#!ifdef WITH_NAT
if(!isdsturiset()) {
xlog("L_INFO", "WITHINDLG - Handle ruri ALIAS");
handle_ruri_alias();
}
#!endif
return;
}
# Routing to foreign domains ---> NOT USED
route[SIPOUT] {
xlog("L_INFO", "WITHINDLG - Entering SIPOUT");
if (uri==myself){
xlog("L_INFO", "WITHINDLG - URI is MySelf!");
return;
}
append_hf("P-hint: outbound\r\n");
xlog("L_INFO", "WITHINDLG - Finishing SIPOUT");
route(RELAY);
exit;
}
# Wrapper for relaying requests
route[RELAY] {
xlog("L_INFO", " ******** RELAY *******");
xlog("L_INFO", "RELAY - $si $su $ru");
# enable additional event routes for forwarded requests
# - serial forking, RTP relaying handling, a.s.o.
if (is_method("INVITE|BYE|CANCEL|SUBSCRIBE|UPDATE")) {
if(!t_is_set("branch_route")) {
xlog("L_INFO", "RELAY - branch_route NOT SET!");
t_on_branch("MANAGE_BRANCH");
}
}
xlog("L_INFO", "RELAY - checking method");
if (is_method("INVITE|SUBSCRIBE|UPDATE")) {
xlog("L_INFO", "RELAY - is INVITE|SUBSCRIBE|UPDATE");
if(!t_is_set("onreply_route")) {
xlog("L_INFO", "RELAY - onreply_route NOT SET!");
t_on_reply("ON_REPLY"); # MANAGE_REPLY");
}
}
if (is_method("INVITE")) {
xlog("L_INFO", "RELAY - is INVITE");
t_on_failure("FAILED_RELAY");
if(!t_is_set("failure_route")) {
xlog("L_INFO", "RELAY - failure_route NOT SET!");
t_on_failure("MANAGE_FAILURE");
}
}
if (!t_relay()) {
xlog("L_INFO", "RELAY - t_relay returns FALSE");
route("MANAGE_FAILURE");
#sl_reply_error();
}
xlog("L_INFO", "RELAY - exiting");
exit;
}
failure_route[FAILED_RELAY] {
xlog("L_INFO", "FAILED_RELAY - Entering");
if (t_check_status("[4-5][0-9][0-9]")){
xlog("L_INFO", "FAILED_RELAY - Could not reach destination endpoint!");
if (rtjson_next_route()) {
xlog("L_INFO", "MANAGE_FAILURE - Getting next route");
t_on_branch("MANAGE_BRANCH");
t_on_failure("MANAGE_FAILURE");
route(RELAY);
}
}
}
route[NATMANAGE] {
xlog("L_INFO", "NATMANAGE - Entering");
#!ifdef WITH_NAT
if (is_request()) {
if(has_totag()) {
xlog("L_INFO", "NATMANAGE - nat=yes --- Setting FLB_NATB");
setbflag(FLB_NATB);
}
}
if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB) ))
{
xlog("L_INFO", "NATMANAGE - NO FLT_NATS/B Set!!! Getting out of
NATMANAGE");
return;
}
if (is_request()) {
xlog("L_INFO", "NATMANAGE - is_request - $rm from $si");
if (!has_totag()) {
if(t_is_branch_route()) {
xlog("L_INFO", "NATMANAGE - adding nat=yes");
add_rr_param(";nat=yes");
}
}
}
if (is_reply()) {
xlog("L_INFO", "NATMANAGE - is_reply - $rm from $si");
if(isbflagset(FLB_NATB)) {
if(is_first_hop())
{
xlog("L_INFO", "NATMANAGE - Set Contact Alias");
set_contact_alias();
}
}
}
#!endif
return;
}
# Manage failure routing cases
route[MANAGE_FAILURE] {
xlog("L_INFO", "MANAGE_FAILURE - Entering ");
route(NATMANAGE);
xlog("L_INFO", "MANAGE_FAILURE - t_is_canceled");
if (t_is_canceled()) exit;
#!ifdef WITH_BLOCK3XX
# block call redirect based on 3xx replies.
if (t_check_status("3[0-9][0-9]")) {
xlog("L_INFO", "MANAGE_FAILURE - SIP 3XX returned!!");
t_reply("404","Not found");
exit;
}
#!endif
#!ifdef WITH_BLOCK401407
# block call redirect based on 401, 407 replies.
if (t_check_status("401|407")) {
xlog("L_INFO", "MANAGE_FAILURE - SIP 401|407 returned!!");
t_reply("404","Not found");
exit;
}
#!endif
if (t_check_status("503")){
xlog("L_INFO", "MANAGE_FAILURE - SIP 503 returned : no destination
available");
t_reply("503", "Destination not available");
exit;
}
if (rtjson_next_route()) {
xlog("L_INFO", "MANAGE_FAILURE - Getting next route!!");
t_on_branch("MANAGE_BRANCH");
t_on_failure("MANAGE_FAILURE");
route(RELAY);
exit;
}
}
# Manage outgoing branches
branch_route[MANAGE_BRANCH] {
xlog("L_INFO","MANAGE_BRANCH - New branch [$T_branch_idx] to
$ru\n");
xlog("L_INFO", "MANAGE_BRANCH - branch_route MANAGE_BRANCH 1 ");
rtjson_update_branch();
route(NATMANAGE);
}
Any help would be greatly appreciated.
Thanks in advance.
*Sérgio *