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

.