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/4...@github.com>
_______________________________________________
Kamailio - Development Mailing List -- sr-dev@lists.kamailio.org
To unsubscribe send an email to sr-dev-le...@lists.kamailio.org
Important: keep the mailing list in the recipients, do not reply only to the 
sender!

Reply via email to