> The kamailio script, completely stateless as I do not need to keep track of the sessions, iterates through one of the JSON branches and adds the destination URLs to the Contact header and replies a SIP 300 Multiple Choices.

 

 

The term ‘stateless’ in the scope of a SIP proxy doesn’t mean to keep track of the session (or the dialog).  It means tracking the state of the transaction.  In order to pause the current transaction and resume it (using http_async_query()), a stateful transaction must be created within Kamailio – and you’ve done this when you call `t_newtran()`.  As a recommendation, rather than using `sl_send_reply()`, `t_reply()`, or `t_send_reply()`, just  use `send_reply()`, which will send the reply statelessly if there’s no transaction, and statefully if there is a transaction.

 

 

If you want to make your replies LOOK stateless to request source, disable automatic 100 Trying from the TM module.

 

 

Kaufman
Senior Voice Engineer



E: bkaufman@bcmone.com

 

SIP.US Client Support: 800.566.9810  |  SIPTRUNK Client Support: 800.250.6510  |  Flowroute Client Support: 855.356.9768

img

img

img

 

From: Sergio Charrua via sr-users <sr-users@lists.kamailio.org>
Sent: Monday, April 8, 2024 10:13 AM
To: Kamailio (SER) - Users Mailing List <sr-users@lists.kamailio.org>
Cc: Sergio Charrua <sergio.charrua@voip.pt>
Subject: [SR-Users] making HTTP requests in stateless redirects

 

CAUTION: This email originated from outside the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.

 

Hi all!

 

 

For testing purposes, while I am waiting for the ST/SH REST API to be available from other teams, I developed a small python REST API that returns a mockup of a JSON object with some of the required values. 

The kamailio script, completely stateless as I do not need to keep track of the sessions, iterates through one of the JSON branches and adds the destination URLs to the Contact header and replies a SIP 300 Multiple Choices.

This works: the UAC does receive the SIP response with the Contacts , but it also receives a SIP 500 error message right after, and I can't figure out why. And i bet this is simple to solve.... 

Any clue? I'm aware I'm not processing ACK messages, but the sl_send_reply 403 should do the trick right? ... at least while testing....

 

Also, as this is a stateless script, is there another way of using async http or making http requests to a REST API without having to use TM Module? 

 

Thanks in advance.

 

The kamailio script is has follows:

 

#!KAMAILIO
/* add API http timeout */
#!define HTTP_API_TIMEOUT 5000
#!define HTTP_API_ROUTING_ENDPOINT "http://some_python_rest_api/get_route"
### LOG Levels: 3=DBG, 2=INFO, 1=NOTICE, 0=WARN, -1=ERR
debug=4
log_stderror=no
memdbg=5
memlog=5
log_facility=LOG_LOCAL0
log_prefix="{$mt $hdr(CSeq) $ci} "
/* number of SIP routing processes */
children=2
/* set paths to location of modules */
loadmodule "tm.so"
loadmodule "jsonrpcs.so"
loadmodule "kex.so"
loadmodule "corex.so"
loadmodule "sl.so"
loadmodule "db_mysql.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "ipops.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "cfg_rpc.so"
loadmodule "uac.so"
loadmodule "counters.so"
loadmodule "http_async_client.so"
loadmodule "jansson.so"
loadmodule "usrloc.so"
/* listen addresses */
listen=udp:10.20.0.2:5060
listen=udp:10.20.0.2:5062
advertised_address="10.20.0.2";
# ----- http_async_client params -----
modparam("http_async_client", "workers", HTTP_ASYNC_CLIENT_WORKERS)
modparam("http_async_client", "connection_timeout", 2000)
request_route {
  #route(HANDLE_DMQ);
  route(HANDLE_OPTIONS);
  if (is_method("INVITE"))
  {
    xlog("L_INFO","MAIN - calling TO_CARRIER");
    route(TO_CARRIER);
    exit;
  }
  else{
        sl_send_reply("401","UNAUTHORIZED");
  }
}
route[TO_CARRIER]{
        xlog("L_INFO","TO_CARRIER - calling RELAY_API");
        route(RELAY_API);                   #Route relay
        xlog("L_INFO","TO_CARRIER - return");
        return;
}
# Relay request using the API (response)
route[RELAY_API_RESPONSE] {
    xlog("L_INFO","RELAY_API_RESPONSE - got response from REST API");
        if ($http_ok==1 && $http_rs==200)
        {
                xlog("L_INFO","RELAY_API_RESPONSE - HTTP RESPONSE: $http_rb\n");
                if (jansson_get("json", $http_rb, "$var(json)")) {
                        xlog("L_INFO","RELAY_API_RESPONSE - JSON = $var(json)");
                        $var(count) = 0;
                        jansson_array_size("routes", $var(json), "$var(size)");
                        xlog("L_INFO","RELAY_API_RESPONSE - jansson_array_size");
                        

                    while ( $var(count) < $var(size) ){

                                jansson_get("routes[$var(count)].headers.to.uri", $var(rtjson), "$var(v)");

                                xlog("L_INFO","JSON - routes[$var(count)] - $var(v)");

                                #$(avp(mycontacts)[$var(count)]) = $avp(mycontacts) + $var(v) + "\r\n";

                                $avp(mycontacts) = $avp(mycontacts) + $var(v) + ";";

 

                                append_to_reply("Contact: <" + $var(v)  +">"+ "\r\n"); /*   ----  IS THERE A BETTER ?? ..... */

 

                                $var(count) = $var(count) + 1;

                        }

                        

                        xlog("L_INFO","RELAY_API_RESPONSE - RELAY");
                        xlog("L_INFO","MAIN - calling REPLY_302");
                        route(REPLY_302);
                        return;
                }
        }
        send_reply(500, "API Not Available - http response = $http_rs $http_ok");
        exit;
}
route[RELAY_API] {

        xlog("L_INFO","RELAY_API - from_ip $si:$sp 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",$si, "$var(http_routing_query)");
        jansson_set("string","from_port",$sp, "$var(http_routing_query)");
        jansson_set("string","from_number",$fU, "$var(http_routing_query)");
        jansson_set("string","to_number",$ru , "$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");
        xlog("L_INFO","RELAY_API - Waiting for Response");
}
route[REPLY_302] {
  # Sends a 300 Multiple Choices back to the proxy that requested the routing lookup
  xlog("L_INFO","REPLY_302 - send reply");
  sl_send_reply("300", "Multiple Choices");
  xlog("L_INFO","REPLY_302 - exit");
  exit;
}
route[HANDLE_OPTIONS]{
        if(is_method("OPTIONS"))
        {
           sl_send_reply(200, "OK");
           exit;
        }
        if ($fU=="ping")
        {
                sl_send_reply("200","OK");
                exit;
        }
}

 

SNGrep output:

1 - INVITE from UAC to Kamailio

 

INVITE sip:918228990@10.20.0.2 SIP/2.0
Via: SIP/2.0/UDP 10.20.0.1:5063;branch=z9hG4bK58aa83f4
Max-Forwards: 70
From: "Anonymous" <sip:anonymous@anonymous.invalid:5063>;tag=as192b8891
To: <sip:918228990@10.20.0.2>
Contact: <sip:anonymous@10.20.0.1:5063>
Call-ID: 531668b959674f9f667f1c923d1d6c94@10.20.0.1:5063
CSeq: 102 INVITE
User-Agent: SIPp
Date: Mon, 08 Apr 2024 15:09:51 GMT
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Content-Type: application/sdp
Content-Length: 270
v=0
o=root 2021555890 2021555890 IN IP4 10.20.0.1
s=SIPp
c=IN IP4 10.20.0.1
t=0 0
m=audio 18422 RTP/AVP 8 0 101
a=rtpmap:8 PCMA/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=ptime:20
a=maxptime:150
a=sendrecv

 

2 - Reply from Kamailio to UAC

 

SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/UDP 10.20.0.1:5063;branch=z9hG4bK58aa83f4
From: "Anonymous" <sip:anonymous@anonymous.invalid:5063>;tag=as192b8891
To: <sip:918228990@10.20.0.2>
Call-ID: 531668b959674f9f667f1c923d1d6c94@10.20.0.1:5063
CSeq: 102 INVITE
Server: kamailio (5.7.4 (x86_64/linux))
Content-Length: 0

 

3 - SIP 300 Multiple Choices from Kamailio to UAC

 

SIP/2.0 300 Multiple Choices
Via: SIP/2.0/UDP 10.20.0.1:5063;branch=z9hG4bK58aa83f4
From: "Anonymous" <sip:anonymous@anonymous.invalid:5063>;tag=as192b8891
To: <sip:918228990@10.20.0.2>;tag=57c593265e21c2b70aea50cb414df9cd.32679ccd
Call-ID: 531668b959674f9f667f1c923d1d6c94@10.20.0.1:5063
CSeq: 102 INVITE
Contact: <sip:sip:918228990@10.20.0.2@sip.domain.io>
Contact: <sip:+351sip:918228990@10.20.0.2@10.20.0.3>
Server: kamailio (5.7.4 (x86_64/linux))
Content-Length: 0

 

4 - SIP 500 from Kamailio to UAC

 

SIP/2.0 500 I'm terribly sorry, server error occurred (1/TM)
Via: SIP/2.0/UDP 10.20.0.1:5063;branch=z9hG4bK58aa83f4
From: "Anonymous" <sip:anonymous@anonymous.invalid:5063>;tag=as192b8891
To: <sip:918228990@10.20.0.2>;tag=4eb2322b7d2b68e6fc3168f503344c21-32679ccd
Call-ID: 531668b959674f9f667f1c923d1d6c94@10.20.0.1:5063
CSeq: 102 INVITE
Server: kamailio (5.7.4 (x86_64/linux))
Content-Length: 0

 

5 - ACK from UAC to Kamailio

 

ACK sip:918228990@10.20.0.2 SIP/2.0
Via: SIP/2.0/UDP 10.20.0.1:5063;branch=z9hG4bK58aa83f4
Max-Forwards: 70
From: "Anonymous" <sip:anonymous@anonymous.invalid:5063>;tag=as192b8891
To: <sip:918228990@10.20.0.2>;tag=57c593265e21c2b70aea50cb414df9cd.32679ccd
Contact: <sip:anonymous@10.20.0.1:5063>
Call-ID: 531668b959674f9f667f1c923d1d6c94@10.20.0.1:5063
CSeq: 102 ACK
User-Agent: SIPp
Content-Length: 0

 

and continues with ACK and repeating SIP 500 above.... 

 

 

 

 


Sérgio Charrua

.