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"); } } } `
Closed #4058 as completed.
Please address questions related to the usage or configuration of Kamailio to our "sr-users" E-Mail list. The github issue tracker is for discussing errors or enchancements related to the code base.