(resending, without attachment, as OP is more than 250kb size and awaits for moderator's approval)


Hi all!

still struggling with Async HTTP Client ...
My current configuration is very simple:

#!define HTTP_API_ROUTING_ENDPOINT_MAIN   "http://MY_HTTP_REST_API:18085/Endpoint"
include_file "listen.cfg"

loadmodule "pv"
loadmodule "tm"
loadmodule "http_async_client"
loadmodule "xlog"
loadmodule "tmx"
loadmodule "sl"
loadmodule "textops"
loadmodule "cfgutils"
loadmodule "siputils"
loadmodule "rr"
loadmodule "ctl"
loadmodule "jsonrpcs.so"
loadmodule "jansson.so"

modparam("pv", "shvset", "http_async=i:8");
modparam("http_async_client", "workers", 1);
modparam("http_async_client", "connection_timeout", 500)
modparam("http_async_client", "curl_verbose", 1) # for debug purpose

#modparam("tm", "fr_timer", 750)
#modparam("tm", "fr_inv_timer", 20000)
#modparam("tm", "remap_503_500", 0)
modparam("tm", "failure_reply_mode", 3)
modparam("tm", "max_inv_lifetime",5000)

# ----- jsonrpcs params -----
modparam("jsonrpcs", "pretty_format", 1)
/* set the path to RPC fifo control file */
modparam("jsonrpcs", "fifo_name", "/tmp/kamailio_rpc.fifo")
/* set the path to RPC unix socket control file */
modparam("jsonrpcs", "dgram_socket", "/tmp/kamailio_rpc.sock")

debug=2
children=16
log_facility=LOG_LOCAL0
log_prefix="{$mt $hdr(CSeq) $ci} "
disable_sctp = yes
force_rport  = yes
rundir="/tmp"

request_route {

        $avp(REQUEST_URL) = HTTP_API_ROUTING_ENDPOINT_MAIN;

        if ( is_method("ACK") ) {
                if ( t_check_trans() ) {
                    t_relay();
                }
                exit;
        }

        if(is_method("OPTIONS")){
                sl_reply("200", "OK");
                exit;
        }

        if(is_method("CANCEL")){
                sl_reply("200","OK");
                sl_reply("487","Request Terminated");
                exit;
        }



        jansson_set("string","from"    , $hdr(From)    , "$var(req)");
        jansson_set("string","to"      , $hdr(To)      , "$var(req)");
        jansson_set("string","r-uri"   , $ru           , "$var(req)");
        jansson_set("string","contact" , $hdr(Contact) , "$var(req)");
        jansson_set("string","call-id" , $ci           , "$var(req)");

        xinfo("MAIN-ROUTE - Setting From=$hdr(From) To=$hdr(To) Contact=$hdr(Contact) ci=$ci \n");

        if ( is_present_hf("Identity") )
                jansson_set("string","identity"             , $hdr(Identity)            , "$var(req)");

        if ( is_present_hf("P-Identity-Bypass") )
                jansson_set("string","p-identity-bypass"    , $hdr(P-Identity-Bypass)   , "$var(req)");

        if ( is_present_hf("P-Asserted-Identity") )
                jansson_set("string","p-asserted-identity"  , $hdr(P-Asserted-Identity) , "$var(req)");

        if ( is_present_hf("P-STSH-UC") )
                jansson_set("string","p-stsh-uc"            , $hdr(P-STSH-UC)           , "$var(req)");
        jansson_set("string", "request-time" , $avp(requestTime), "$var(req)");


    ## Create transaction before http_async_query;
    if (is_method("INVITE")){
        t_newtran();
        xinfo("MAIN-ROUTE - Sending request [$var(req)]\n");
        route(HTTP_ASYNC_REQUEST);
    }
    exit;
}



route[HTTP_ASYNC_REQUEST] {
    xinfo("HTTP_ASYNC_REQUEST - Sending request [$var(req)]\n");

    $http_req(all) = $null;
    $http_req(suspend) = 1;
    $http_req(timeout) = 1500; # 1 second timeout
    $http_req(method) = "POST";
    $http_req(hdr) = "Content-Type: application/json";
    $http_req(body) = $var(req);

    if ( !http_async_query($avp(REQUEST_URL), "HTTP_REPLY") ) {
        xinfo("HTTP_ASYNC_REQUEST - http_async_query $ci FAILED. Return is [$rc]\n");
    }else{
        send_reply("503", "Server Error");
        exit;
    }
}


route[HTTP_REPLY] {
    xinfo("HTTP_REPLY - Xphere Response Code $http_rs - $ci\n");

    if ( $http_ok && $http_rs==200) {
        xinfo("HTTP_REPLY - $ci reply ok\n");
        jansson_xdecode($http_rb, "json");
        xinfo("HTTP_REPLY - HTTP JSON Response: $http_rb \n");

        if ( $xavp(json=>sip-response-code) == 300 ){
                remove_hf("Contact");
                append_to_reply("Contact: $xavp(json=>contact)\r\n");
                ## "touch" the ruri to add the contact header for 3xx:
                $ru = $ru;
                send_reply("300", "Multiple Choice");
                exit;
        }else{
                xinfo("HTTP_REPLY - $ci Error Replied $xavp(json=>sip-response-code) - $xavp(json=>sip-response-text) \n");
                send_reply("$xavp(json=>sip-response-code)","$xavp(json=>sip-response-text)");
                exit;
        }

    }
    else {
                xinfo("HTTP_REPLY - HTTP Response Code $ci - $http_rs and error $http_err \n");
                if (!$http_ok){
                        sl_reply("503", "No Connection to HTTP");
                        exit;
                }else if ($http_rs>=500){
                        sl_reply("503", "HTTP Processing Error");
                        exit;
                }
                else{
                        sl_reply("503", "Cannot Connect to HTTP");
                        exit;
                }
    }
    exit;
}

The configuration is based on Ben Kaufman's kamailio_http_async example, but I have extended it a bit.
Currently all the requests are being sent to the HTTP REST API. I can't find queue/buffering issues...

What I am experiencing is that , using SNGREP, I get this flow:

                                                          
          10.240.12.209:5060            10.242.17.146:5060
        ----------*----------         ----------*----------
17:33:46.689852   x        INVITE (SDP)         x         
      +0.000530   x --------------------------> x         
17:33:46.690382   x  100 trying -- your call is x         
      +1.499822   x <-------------------------- x         
17:33:48.190204   x  503 No Connection to HTTP  x         
      +0.000029   x <-------------------------- x         
17:33:48.190233   x  500 I'm terribly sorry, se x         
      +0.002130   x <-------------------------- x         
17:33:48.192363   x             ACK             x         
      +0.485836   x --------------------------> x         
17:33:48.678199   x  500 I'm terribly sorry, se x         
      +0.004881   x <<<------------------------ x         
17:33:48.683080   x             ACK             x         
      +0.973295   x ------------------------>>> x         
17:33:49.656375   x  500 I'm terribly sorry, se x         
      +0.004105   x <<<------------------------ x         
17:33:49.660480   x             ACK             x         
      +1.995420   x ------------------------>>> x         
17:33:51.655900   x  500 I'm terribly sorry, se x         
      +0.005361   x <<<-------------------------x         
17:33:51.661261   x             ACK             x         
                  x ------------------------>>> x         

I suspected issues with the HTTP REST service, but when using tcpdump, I can find the Request from Kamailio and a reply back from the REST API service, so doesn't seem to be a problem on the HTTP REST service
So my questions are:
- why is Kamailio sending a "SIP 500 I'm terribly sorry..." error after a 503 No Connection to HTTP is sent and an "exit" command is executed?
- how can I get rid of these messages?
- Why Kamailio keeps sending responses back to SBC after the ACK when it is set to just "exit"?
- Why is Kamailio not processing the response from HTTP REST API when it is correctly received?

Logs are also weird:
- I find a lot of these warnings:
"Dec 29 17:38:34 ire-nprod-sip1 /usr/local/sbin/kamailio[590864]: WARNING: http_async_client [http_async_client_mod.c:529]: ah_get_status(): an async variable was read after http error, use $http_ok to check the request's status"
and 
"Dec 29 17:38:34 ire-nprod-sip1 /usr/local/sbin/kamailio[590864]: ERROR: http_async_client [http_multi.c:621]: check_multi_info(): handle 0x7f375f786b30 returned error 7:"

(I am still not using EVAPI module, that will be my next step, after the holiday season)
(I suspect, however, that the REST API is not being able to handle the load in this test environment (between 400 to 600 CAPS), but that is another matter.)

I can send the TCPDUMP, if anyone wishes to analyze.

Atenciosamente / Kind Regards / Cordialement / Un saludo,


Sérgio Charrua