I am using the latest version of Kamailio, but I am unsure what the problem is. My
configuration does not handle the CANCEL request correctly, and it returns an error.
`#!KAMAILIO
#!define WITH_MYSQL
#!define SHM_MEMORY 64
debug=2
log_stderror=no
log_facility=LOG_LOCAL0
mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/"
loadmodule "permissions.so"
loadmodule "tm.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "dispatcher.so"
loadmodule "db_mysql.so"
loadmodule "siputils.so"
loadmodule "textops.so"
loadmodule "maxfwd.so"
loadmodule "xlog.so"
loadmodule "ctl.so"
loadmodule "cfgutils.so"
loadmodule "htable.so"
loadmodule "timer.so"
loadmodule "sqlops.so"
listen=udp::5060
alias=:5060
# Database connection parameters
modparam("sqlops", "sqlcon",
"ca=>mysql://kamailio:@/development")
modparam("permissions", "db_url",
"mysql://kamailio@/development")
modparam("permissions", "address_table", "address")
modparam("permissions", "peer_tag_avp", "$avp(tag)")
modparam("dispatcher", "db_url",
"mysql://kamailio:@/development")
modparam("dispatcher", "ds_hash_size", 2048)
modparam("dispatcher", "table_name", "dispatcher")
modparam("dispatcher", "flags", 0)
modparam("dispatcher", "force_dst", 1)
# Configure hash tables
modparam("htable", "htable",
"clientLimits=>size=64;autoexpire=300")
modparam("htable", "htable",
"clientCalls=>size=64;autoexpire=60")
modparam("ctl", "binrpc",
"unix:/var/run/kamailio/kamailio_ctl")
modparam("cfgutils", "lock_set_size", 14)
# Transaction Module Parameters
modparam("tm", "fr_inv_timer", 180000)
modparam("tm", "fr_timer", 60000)
modparam("tm", "restart_fr_on_each_reply", 1)
modparam("tm", "auto_inv_100", 1)
# Timer for refreshing limits
modparam("timer", "declare_timer",
"LIMITS_TIMER=refresh_limits,300,slow,enable")
modparam("timer", "declare_timer",
"CLEANUP_TIMER=cleanup_calls,60,slow,enable")
request_route {
if (is_method("CANCEL")) {
xlog("L_INFO", "Received CANCEL request for $ci - Method: $rm - R-URI:
$ru\n");
if (!t_check_trans()) {
xlog("L_INFO", "No transaction found with t_check_trans(),
trying t_lookup_cancel()\n");
# Try to find the transaction using branch and Call-ID
$var(branch) = $(hdr(Via){param.value,branch});
if (!t_lookup_cancel()) {
xlog("L_WARN", "No transaction found for CANCEL - $ci with
branch $var(branch)\n");
sl_reply("481", "Call Leg/Transaction Does Not
Exist");
exit;
}
xlog("L_INFO", "Found transaction using
t_lookup_cancel()\n");
}
# Extract destination from original request
if ($ru != "") {
$du = $ru;
xlog("L_INFO", "Setting destination from R-URI: $du\n");
} else {
xlog("L_WARN", "No R-URI found for CANCEL\n");
}
# Add debugging
xlog("L_INFO", "Forwarding CANCEL to $du for call $ci\n");
if (ds_is_from_list()) {
ds_load_unset();
xlog("L_INFO", "Unset dispatcher load for
destination\n");
}
# Handle the client ID and call counting
if (is_present_hf("X-VICIdial-Client-Id")) {
$var(client_id) = $(hdr(X-VICIdial-Client-Id));
if ($var(client_id) =~ "^(CID_[0-9]+)-[a-z]$") {
$var(parent_id) = $(var(client_id){re.subst,/^(CID_[0-9]+)-[a-z]$/\1/});
} else {
$var(parent_id) = $var(client_id);
}
if($var(parent_id) != $null) {
lock("calls_$var(parent_id)");
if($sht(clientCalls=>$var(parent_id)) > 0) {
$sht(clientCalls=>$var(parent_id)) =
$sht(clientCalls=>$var(parent_id)) - 1;
xlog("L_INFO", "CANCEL: Decremented call count for
$var(parent_id) to $sht(clientCalls=>$var(parent_id))\n");
}
unlock("calls_$var(parent_id)");
}
}
# Send 200 OK response for the CANCEL
t_reply("200", "OK");
# Force the relay of CANCEL to the destination
t_relay();
exit;
}
if(is_method("BYE")) {
if((!allow_source_address("1") && !ds_is_from_list())) {
xlog("L_WARN", "IP $si:$sp not in address or dispatcher
list\n");
sl_send_reply("403", "IP Not Allowed");
exit;
}
route(RELAY);
exit;
}
if (!allow_source_address("1") ) {
xlog("L_WARN", "IP $si:$sp not allowed\n");
sl_send_reply("403", "IP Not Allowed");
exit;
}
if (is_method("ACK")) {
if (t_check_trans()) {
t_relay();
} else {
route(RELAY);
}
exit;
}
if (is_method("OPTIONS")) {
options_reply();
exit;
}
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483", "Too Many Hops");
exit;
}
if (is_method("INVITE")) {
if (!is_present_hf("X-VICIdial-Client-Id")) {
xlog("L_WARN", "INVITE received without X-VICIdial-Client-Id
header\n");
sl_send_reply("400", "Bad Request - Missing Client ID");
exit;
}
t_check_trans();
$var(client_id) = $(hdr(X-VICIdial-Client-Id));
if ($var(client_id) =~ "^(CID_[0-9]+)-[a-z]$") {
$var(parent_id) = $(var(client_id){re.subst,/^(CID_[0-9]+)-[a-z]$/\1/});
} else {
$var(parent_id) = $var(client_id);
}
$var(limit) = $sht(clientLimits=>$var(parent_id));
if(!$var(limit)) {
xlog("L_WARN", "No limit configured for client
$var(parent_id)\n");
sl_send_reply("403", "Client Not Configured");
exit;
}
lock("calls_$var(parent_id)");
$var(current_calls) = $sht(clientCalls=>$var(parent_id));
if(!$var(current_calls)) {
$var(current_calls) = 0;
}
if($var(current_calls) >= $var(limit)) {
unlock("calls_$var(parent_id)");
xlog("L_WARN", "Call limit exceeded for client $var(parent_id):
$var(current_calls)/$var(limit)\n");
sl_send_reply("429", "Concurrent Call Limit Exceeded");
exit;
}
$sht(clientCalls=>$var(parent_id)) = $var(current_calls) + 1;
unlock("calls_$var(parent_id)");
route(GENERATE_SERIAL_NUMBER);
# xlog("L_INFO", "Processing INVITE - checking load - Serial
Number: $avp(serial_number)\n");
$var(original_contact) = $ct;
append_hf("X-Original-Contact: $var(original_contact)\r\n");
append_hf("X-Original-IP: $si\r\n");
append_hf("X-Original-Port: $sp\r\n");
append_hf("X-Serial-Number: $avp(serial_number)\r\n");
if (!ds_select_dst("4", "10")) {
xlog("L_WARN", "All destinations at max load, forwarding to
dump server\n");
$du = "sip::5060";
record_route();
route(RELAY);
exit;
}
xlog("L_INFO", "Selected destination: $du\n");
record_route();
ds_load_update();
t_on_failure("MANAGE_FAILURE");
route(RELAY);
exit;
}
if (is_method("BYE")) {
t_check_trans();
if($sht(clientCalls=>$var(parent_id)) > 0) {
$sht(clientCalls=>$var(parent_id)) = $sht(clientCalls=>$var(parent_id))
- 1;
}
if (ds_is_from_list()) {
ds_load_unset();
}
route(RELAY);
exit;
}
route(RELAY);
}
route[GENERATE_SERIAL_NUMBER] {
$var(seconds) = $Ts;
$var(microseconds) = $TV(u);
$var(server_number) = "01";
$var(seconds_str) = "" + $var(seconds);
$var(truncated_seconds) = $(var(seconds_str){s.substr,2,0});
$var(milliseconds_full) = "" + $var(microseconds);
$var(milliseconds) = $(var(milliseconds_full){s.striptail,3});
if ($var(milliseconds) < 100) {
if ($var(milliseconds) < 10) {
$var(milliseconds_str) = "00" + $var(milliseconds);
} else {
$var(milliseconds_str) = "0" + $var(milliseconds);
}
} else {
$var(milliseconds_str) = "" + $var(milliseconds);
}
$var(random) = $RANDOM;
if ($var(random) < 10) {
$var(random_padded) = "0" + $var(random);
} else {
$var(random_str) = "" + $var(random);
$var(random_padded) = $(var(random_str){s.substr,-2,0});
}
$var(serial_number) = $var(truncated_seconds) + $var(milliseconds_str) +
$var(server_number) + $var(random_padded);
$avp(serial_number) = $var(serial_number);
}
route[refresh_limits] {
sql_query("ca", "SELECT client_id, cps_limit FROM client_limits",
"ra");
$var(rows) = $dbr(ra=>rows);
$var(i) = 0;
# xlog("L_INFO", "Refreshing limits for $var(rows) clients\n");
while($var(i) < $var(rows)) {
$var(cid) = $dbr(ra=>[$var(i),0]);
$var(limit) = $dbr(ra=>[$var(i),1]);
$sht(clientLimits=>$var(cid)) = $var(limit);
# xlog("L_INFO", "Client $var(cid) limit set to $var(limit)
calls/second\n");
$var(i) = $var(i) + 1;
}
sql_result_free("ra");
# xlog("L_INFO", "Finished loading client limits\n");
}
route[RELAY] {
if (!t_relay()) {
sl_reply_error();
}
}
route[options_reply] {
sl_send_reply("200", "OK");
}
reply_route {
if (is_method("INVITE")) {
if (ds_is_from_list()) {
if (status=~"2[0-9][0-9]") {
ds_load_update();
} else if (status=~"[3-7][0-9][0-9]") {
ds_load_unset();
}
}
}
if(status=~"487|486|603") {
if (is_present_hf("X-VICIdial-Client-Id")) {
$var(client_id) = $(hdr(X-VICIdial-Client-Id));
if ($var(client_id) =~ "^(CID_[0-9]+)-[a-z]$") {
$var(parent_id) = $(var(client_id){re.subst,/^(CID_[0-9]+)-[a-z]$/\1/});
} else {
$var(parent_id) = $var(client_id);
}
if($var(parent_id) != $null) {
lock("calls_$var(parent_id)");
if($sht(clientCalls=>$var(parent_id)) > 0) {
$sht(clientCalls=>$var(parent_id)) =
$sht(clientCalls=>$var(parent_id)) - 1;
xlog("L_INFO", "Response $rs: Decremented call count
for $var(parent_id)\n");
}
unlock("calls_$var(parent_id)");
}
}
}
}
failure_route[MANAGE_FAILURE] {
if (is_method("INVITE")) {
if
(t_check_status("403|408|480|482|483|486|487|488|501|502|503|504|603")) {
xlog("L_WARN", "Failed response received from $du\n");
if (!$var(attempt)) {
$var(attempt) = 1;
}
if (ds_is_from_list() && $var(attempt) < 3) {
$var(attempt) = $var(attempt) + 1;
if (ds_next_dst()) {
xlog("L_INFO", "Trying destination $var(attempt):
$du\n");
t_relay();
exit;
}
} else if ($var(attempt) == 3) {
xlog("L_INFO", "3 destinations failed, routing to dump
server\n");
$du = "sip::5060";
t_relay();
exit;
} else {
xlog("L_ERR", "Dump server failed, rejecting
call\n");
t_reply("503", "Service Unavailable");
exit;
}
}
}
}
route[cleanup_calls] {
sht_iterator_start("cleanup", "clientCalls");
while(sht_iterator_next("cleanup")) {
$var(client_id) = $shtitkey(cleanup);
$var(current_calls) = $shtitval(cleanup);
xlog("L_INFO", "Client $var(client_id) - Current Calls:
$var(current_calls)\n");
}
sht_iterator_end("cleanup");
}
event_route[dispatcher:dst-down] {
if ($du != $null) {
xlog("L_WARN", "Destination $du went down\n");
}
}
event_route[dispatcher:dst-up] {
if ($du != $null) {
if ($sht(active_calls=>$du) == $null) {
$sht(active_calls=>$du) = 0;
xlog("L_INFO", "Initialized counter for recovered destination
$du\n");
}
}
}
`
--
Reply to this email directly or view it on GitHub:
https://github.com/kamailio/kamailio/issues/4058
You are receiving this because you are subscribed to this thread.
Message ID: <kamailio/kamailio/issues/4058(a)github.com>