Hi Henning, Main reason is that the solution needs to be stateless, so, in my understanding, TM module would turn everything stateful... Am I wrong? This way I still end up with a stateless redirect server...
Anyway, I will give it a try. Any advice you can share? Atenciosamente / Kind Regards / Cordialement / Un saludo, *Sérgio Charrua* On Sun, Dec 22, 2024 at 9:13 AM Henning Westerholt <[email protected]> wrote: > Hello, > > > > I have not reviewed your cfg in detail. But I am wondering why you go this > way of adding additional complexity (e.g. using a htable, use special > message sending functions)? The easiest approach would be to use the > http_async_client module in a way it was designed in the first place, with > the tm module and transactions. > > > > Cheers, > > > > Henning > > > > *From:* Sergio Charrua via sr-users <[email protected]> > *Sent:* Sonntag, 22. Dezember 2024 00:34 > *To:* Kamailio (SER) - Users Mailing List <[email protected]> > *Cc:* Alexis Fidalgo <[email protected]>; Sergio Charrua < > [email protected]> > *Subject:* [SR-Users] Re: Transactions help > > > > i'm also doing some tests on my side, but in stateless mode and I came to > an interesting approach (but requires a lot more testing...). > > The idea is to have http_async_client running in a stateless proxy, and > the way I did it is: > > > > - receive the INVITE > > - keep the message buffer in a htable, with key call-id > > ... > > $var(call_id) = $ci; > > $sht(stateless_calls=>$var(call_id)) = $mb; > > ... > > > > - send the async http request, specifying the response route handler > > > > in the route that handles the http response, I do: > > - check if the JSON response received from HTTP includes the call-id value > (this is mandatory for the whole solution to work) > > - if the call-id is present, get the value from htable with something like: > > ... > > $var(saved_msg) = $sht(stateless_calls=>$var(call_id)); > > ... > > - then use $var(saved_msg) to create a new message buffer > with msg_set_buffer( $var(saved_msg) ); (from textopsx module) > > - modify the contact header with values found in JSON object returned from > the HTTP response > > - send_reply("300", "Multiple Choices"); > > > > But msg_set_buffer is not working as I would expect: not sure why, but the > Via header now includes a ;received=127.0.0.1 value (it is not present in > the original header), which results in the following SIP flow > > > > SBC ----> INVITE ----> Kamailio > > SBC <---- 100 Trying <---- Kamailio > > Kamailio ----> 300 Multi Choice ----> 127.0.0.1 > > > > (but the SIP 300 Multi Choice is not the message buffer constructed in > the RELAY_API_RESPONSE route) > > > > This is the code I ended up so far.... If you, or anyone, manage to make > this work, please share within this thread (I will do the same too) > > > > ####### Modules Section ######## > # Load stateless reply module > loadmodule "sl.so" > loadmodule "tm.so" > # Load PV module (pseudo-variables) > loadmodule "pv.so" > # Load http_async_client module > loadmodule "http_async_client.so" > # Load htable module (for storing data) > loadmodule "htable.so" > # Load JSON module (used if you parse JSON in responses) > loadmodule "jansson.so" > loadmodule "xlog.so" > loadmodule "textops.so" > loadmodule "textopsx.so" > # Other modules as needed... > # loadmodule "xlog.so" > # loadmodule "textopsx.so" > # ... > ####### Module Parameters ######## > # http_async_client parameters > #modparam("http_async_client", "http_retry", 0) # No retries > modparam("http_async_client", "tcp_keepalive", 1) > modparam("http_async_client", "workers", 4) # Number of async workers > modparam("http_async_client", "connection_timeout", 200) > # htable module parameters - define a table for storing requests > modparam("htable", "htable", "stateless_calls=>size=8;autoexpire=3600;") > # ^ 'stateless_calls' is just an example table name; it stores data for up > to 1 hour, but should be reduced to seconds.... > ####### Request Routing Section ######## > include_file "includes/handle_options.cfg" > > # Main request route > request_route { > if (is_method("ACK") ) { #&& t_check_trans() ){ > exit; > } > route(HANDLE_OPTIONS); > # Handle INVITE > if (is_method("INVITE")) { > if (is_method("INVITE")) { > send_reply("100","Trying"); > } > > # A unique key to identify this call; typically use $ci (Call-ID) > $var(call_id) = $ci; > xlog("L_INFO", "[INVITE] Received INVITE with Call-ID: > $var(call_id)\n"); > # --------------------------------------------------------- > # 1) Store the SIP Message in our HTable so we can respond later > # Key: the Call-ID > # Value: the entire SIP message buffer ($mb) + maybe some > headers > # --------------------------------------------------------- > $sht(stateless_calls=>$var(call_id)) = $mb; > xlog("L_INFO","[INVITE] $mb \n"); > # --------------------------------------------------------- > # 2) Generate JSON payload and Trigger asynchronous HTTP request > # > # We send the Call-ID so the server can return it in the > response > # > # --------------------------------------------------------- > > jansson_set("string","from" , $hdr(From) , "$var(post)"); > jansson_set("string","to" , $hdr(To) , "$var(post)"); > jansson_set("string","r-uri" , $ru , "$var(post)"); > jansson_set("string","contact" , $hdr(Contact) , "$var(post)"); > jansson_set("string","call-id" , $ci , "$var(post)"); > if ( is_present_hf("Identity") ) > jansson_set("string","identity" , $hdr(Identity) > , "$var(post)"); > if ( is_present_hf("P-Identity-Bypass") ) > jansson_set("string","p-identity-bypass" , > $hdr(P-Identity-Bypass) , "$var(post)"); > if ( is_present_hf("P-Asserted-Identity") ) > jansson_set("string","p-asserted-identity" , > $hdr(P-Asserted-Identity) , "$var(post)"); > if ( is_present_hf("P-STSH-UC") ) > jansson_set("string","p-stsh-uc" , $hdr(P-STSH-UC) > , "$var(post)"); > jansson_set("string", "request-time" , $xavp(requestTime), > "$var(post)"); > > $http_req(all) = $null; > $http_req(suspend) = 0 > $http_req(method) = "POST"; > $http_req(hdr) = "Content-Type: application/json"; > $http_req(suspend) = 0; > $http_req(body) = $var(post); > > xlog("L_INFO", "HANDLE_STIRSHAKEN - JSON object to POST :\n > $var(post)\n"); > xlog("L_INFO", "HANDLE_STIRSHAKEN - HTTP_STSH_QUERY URL = > $var(REQUEST_URL)\n"); > http_async_query( > "http://IP:PORT/ire/v1/stsh", # Endpoint > "RELAY_API_RESPONSE" # Callback route > ); > # --------------------------------------------------------- > # 3) Since we are 'stateless', do NOT send a reply yet, do NOT > forward. > # We simply exit; the code in event_route will handle the final > reply. > # --------------------------------------------------------- > xlog("L_INFO", "[INVITE] Asynchronous HTTP call triggered, exit > now.\n"); > exit; > } > # For other methods or default: > sl_send_reply("405","Method Not Allowed"); > exit; > } > # > # event_route for asynchronous HTTP responses > # > route[RELAY_API_RESPONSE] { > xlog("L_INFO", "[HTTP-ASYNC] HTTP response received!\n"); > xlog("L_INFO", "[HTTP-ASYNC] Response body: $(rb)\n"); > $var(rtjson) = ""; > $var(size) = ""; > $var(REQUEST_URL) = ""; > # 1) Parse the JSON (assuming you get something like: { "call_id": > "xyz", "contacts": ["sip:[email protected]", "sip:[email protected]"] } ) > # This is an example; adapt to your actual response format. > jansson_xdecode($http_rb, "json"); > $var(call_id) = $xavp(json=>call-id); # $(rb{s.json, call_id}); > > > xlog("L_INFO", "[HTTP-ASYNC] call_id from HTTP response: > $var(call_id)\n"); > if ($var(call_id) == "") { > xlog("L_ERR", "[HTTP-ASYNC] No call_id in HTTP response, cannot > correlate!\n"); > return; > } > # 2) Retrieve the original SIP message from the HTable > $var(saved_msg) = $sht(stateless_calls=>$var(call_id)); > if ($var(saved_msg) == $null) { > xlog("L_ERR", "[HTTP-ASYNC] No stored message found for > call_id=$var(call_id).\n"); > return; > } > > # 3) Now we must 're-inject' or 're-process' that saved SIP message in > Kamailio's context > # so we can send a stateless reply. > # We can do this by dynamically building the response. > # > # the typical approach is: > # - Use 'msg_set_buffer' to load the saved message buffer into > context > # - Then call 'sl_send_reply()' with the desired code and reason > msg_set_buffer( $var(saved_msg) ); > append_to_reply("Contact: $xavp(json=>contact)\r\n"); > # 4) Construct and send the 300 Multiple Choices. > # We can add new Contacts by using `append_hf("Contact: ...\r\n")`. > # In a perfect scenario, you'd parse the array properly. For > demonstration, > # let's assume $var(contacts) = "sip:[email protected],sip:[email protected]" > # Add the 300 code and reason > send_reply("300", "Multiple Choices"); > # 5) Clean up from the HTable > sht_rm("stateless_calls",$var(call_id)); > # Done > xlog("L_INFO", "[HTTP-ASYNC] 300 Multiple Choices sent for > call_id=$var(call_id).\n"); > } > > > > > > > > > > Atenciosamente / Kind Regards / Cordialement / Un saludo, > > > > *Sérgio Charrua* > > > > On Sat, Dec 21, 2024 at 5:31 PM Alexis Fidalgo via sr-users < > [email protected]> wrote: > > Hello, after the discussion regarding http and http_async, I started some > labs to make a comparison and see what’s the trade off and the associated > cost. > > Main problem (to me) is im not clear on how transactions behave. Im > running some fast tests now before I start to deploy the final scenarios > and > > 1. A new transaction is created before the http_async call (as the module > example shows for http_async_query function > 2. The http_async_query call is executed, receives a response and the > HTTP_REPLY route for http_async_query is executed. > 3. As we need to redirect the call, im adding Contact information with > append_to_reply and then calling t_reply(302,”Redirect) > > Up to here INVITE is received, a 100 is answered and then the 302 with the > expected Contact information (collected and built from the http_async_query > response), problem is that the 302 is retransmitted 3 more times. > > So, im not even sure that im doing the correct actions to process the call > this way. Is there a document/book/reference I can read to understand > transactions better? > > By now I can not handle the call to be processed correctly (without the > retransmissions) and finish the transaction the correct way. > > Any help, link, guide, will be appreciated. > > Regards. > > __________________________________________________________ > Kamailio - Users Mailing List - Non Commercial Discussions -- > [email protected] > To unsubscribe send an email to [email protected] > Important: keep the mailing list in the recipients, do not reply only to > the sender! > >
__________________________________________________________ Kamailio - Users Mailing List - Non Commercial Discussions -- [email protected] To unsubscribe send an email to [email protected] Important: keep the mailing list in the recipients, do not reply only to the sender!
