route[HANDLE_INVITE] {
    if (!has_totag()) {
        if (!t_newtran()) {
            xlog("L_ERROR", "Failed to create new transaction\n");
            sl_reply_error();
            exit;
        }
        
        if (!is_present_hf("X-VICIdial-Client-Id")) {
            xlog("L_WARN", "INVITE received without X-VICIdial-Client-Id 
header\n");
            t_reply("400", "Bad Request - Missing Client ID");
            exit;
        }

        if ($rU == $null) {
            xlog("L_WARN", "INVITE received with empty Request-URI username\n");
            t_reply("400", "Bad Request - Missing User");
            exit;
        }

        $var(full_client_id) = $hdr(X-VICIdial-Client-Id);
        # Extract parent ID
        if ($var(full_client_id) =~ "^(CID_[0-9]+)-[a-z]$") {
            $var(parent_client_id) = 
$(var(full_client_id){re.subst,/^(CID_[0-9]+)-[a-z]$/\1/});
        } else {
            $var(parent_client_id) = $var(full_client_id);
        }

        # CPS Check and Rate Limiting
        lock("cps_counter");

        # Get current CPS count and max limit
        $var(current_cps) = $sht(client_limits=>$var(parent_client_id));
        $var(max_cps) = $sht(client_max_cps=>$var(parent_client_id));

        xlog("L_INFO", "CPS Check - Client: $var(parent_client_id), Current: 
$var(current_cps), Max: $var(max_cps)\n");

        # Check for configured limit
        if($var(max_cps) == $null) {
            unlock("cps_counter");
            xlog("L_WARN", "No CPS limit configured for client 
$var(parent_client_id)\n");
            t_reply("403", "Client Not Authorized");
            exit;
        }

        # Get concurrent calls
        $var(concurrent_calls) = $sht(client_calls=>$var(parent_client_id));
        if($var(concurrent_calls) == $null) {
            $var(concurrent_calls) = 0;
        }

        # Strict limit check
        if($var(concurrent_calls) >= $var(max_cps)) {
            unlock("cps_counter");
            xlog("L_WARN", "Concurrent call limit reached for 
$var(parent_client_id): $var(concurrent_calls)/$var(max_cps)\n");
            t_reply("503", "Concurrent Call Limit Exceeded");
            exit;
        }

        # Allow call and increment counter
        if($var(current_cps) == $null) {
            $sht(client_limits=>$var(parent_client_id)) = 1;
        } else {
            $sht(client_limits=>$var(parent_client_id)) = $var(current_cps) + 1;
        }

        xlog("L_INFO", "Call allowed for $var(parent_client_id): 
Concurrent=$var(concurrent_calls+1)/$var(max_cps)\n");
        unlock("cps_counter");

        $var(user) = $rU;    

        # Extract parent client ID if this is a child ID
        if ($var(full_client_id) =~ "^(CID_[0-9]+)-[a-z]$") {
            $var(parent_client_id) = 
$(var(full_client_id){re.subst,/^(CID_[0-9]+)-[a-z]$/\1/});
            $var(is_child) = 1;
        } else {
            $var(parent_client_id) = $var(full_client_id);
            $var(is_child) = 0;
        }

        $avp(full_client_id) = $var(full_client_id);
        $avp(parent_client_id) = $var(parent_client_id);
        $avp(user) = $var(user);
        $var(call_id) = $ci;

        route(GENERATE_SERIAL_NUMBER);
        
        # Track client calls
        lock("client_counter");
        
        # Update parent counter
        $var(parent_calls) = $sht(client_calls=>$var(parent_client_id));
        if($var(parent_calls) == $null) {
            $var(parent_calls) = 0;
        }
        $sht(client_calls=>$var(parent_client_id)) = $var(parent_calls) + 1;
        
        # If it's a child ID, update its individual counter too
        if ($var(is_child) == 1) {
            $var(child_calls) = $sht(client_calls=>$var(full_client_id));
            if($var(child_calls) == $null) {
                $var(child_calls) = 0;
            }
            $sht(client_calls=>$var(full_client_id)) = $var(child_calls) + 1;
        }
        
        # Store mappings
        $sht(client_calls=>$var(call_id)) = $var(parent_client_id);
        $sht(client_original=>$var(call_id)) = $var(full_client_id);
        unlock("client_counter");

        # Find destination with lowest active calls
        $var(min_calls) = 999;
        $var(selected_dst) = "";
        
        lock("calls_counter");
        
        if (ds_select_dst("4", "4")) {
            $var(count) = 0;  # Add counter
            $var(current_calls) = $sht(active_calls=>$du);
            if ($var(current_calls) == $null) {
                $var(current_calls) = 0;
            }
            
            if ($var(current_calls) < $var(min_calls)) {
                $var(min_calls) = $var(current_calls);
                $var(selected_dst) = $du;
            }

            while(ds_next_dst() && $var(count) < 350) {  # Set higher than 280
                $var(count) = $var(count) + 1;
                $var(current_calls) = $sht(active_calls=>$du);
                if ($var(current_calls) == $null) {
                    $var(current_calls) = 0;
                }
                
                if ($var(current_calls) < $var(min_calls)) {
                    $var(min_calls) = $var(current_calls);
                    $var(selected_dst) = $du;
                }
            }
        }
        
        if ($var(selected_dst) != "" && $var(min_calls) < 25) {
            $du = $var(selected_dst);
            # Add this block - Double check the count hasn't changed
            $var(current_count) = $sht(active_calls=>$du);
            if ($var(current_count) >= 25) {
                unlock("calls_counter");
                xlog("L_ERROR", "Count increased during selection for $du to 
$var(current_count)\n");
                t_reply("503", "Service Unavailable");
                exit;
            }
            # Store Call-ID to destination mapping
            $sht(active_calls=>$var(call_id)) = $du;
            # Increment call counter
            $sht(active_calls=>$du) = $var(min_calls) + 1;
            unlock("calls_counter");
            route(RELAY_INVITE);
        } else {
            unlock("calls_counter");
            xlog("L_NOTICE", "Unlocked $ci");
            $du = "sip:34.125.5.64:5060";
            t_on_failure("FINAL_FAILURE");
            if (!t_relay()) {
                t_reply("500", "Internal Server Error");
            }
        }
    } else {
        route(RELAY);
    }
}    here is my invite rout configuration if you look at to the cps limit this 
is occultly the call per second limit on the client id when i set it 200 and 
the start calling up to 3000 per seconds so some time or for a bit of time it 
exceed the limit 201 or 202 then it start enforce 200 so if anyone have the 
best idea or suggestion regarding to this with the good ms time 


-- 
Reply to this email directly or view it on GitHub:
https://github.com/kamailio/kamailio/issues/4040
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