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.
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:alice@1.2.3.4", "sip:bob@1.2.3.5"] } ) # 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:alice@1.2.3.4,sip:bob@1.2.3.5" # 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 < sr-users@lists.kamailio.org> 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
- 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 -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
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 sr-users@lists.kamailio.org Sent: Sonntag, 22. Dezember 2024 00:34 To: Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org Cc: Alexis Fidalgo alzrck@gmail.com; Sergio Charrua sergio.charrua@voip.pt 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:alice@1.2.3.4mailto:sip%3Aalice@1.2.3.4", "sip:bob@1.2.3.5mailto:sip%3Abob@1.2.3.5"] } ) # 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:alice@1.2.3.4mailto:sip%3Aalice@1.2.3.4,sip:bob@1.2.3.5mailto:sip%3Abob@1.2.3.5" # 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 <sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org> 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 -- sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.orgmailto:sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
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 hw@gilawa.com 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 sr-users@lists.kamailio.org *Sent:* Sonntag, 22. Dezember 2024 00:34 *To:* Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org *Cc:* Alexis Fidalgo alzrck@gmail.com; Sergio Charrua < sergio.charrua@voip.pt> *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:alice@1.2.3.4", "sip:bob@1.2.3.5"] } ) # 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:alice@1.2.3.4,sip:bob@1.2.3.5" # 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 < sr-users@lists.kamailio.org> 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
- 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 -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
Hello Sergio,
but you are using a htable to actually keep a state. So, your solution would be not stateless in the end. You are simply not using the tm module to keep the state, but by another means.
Cheers,
Henning
From: Sergio Charrua sergio.charrua@voip.pt Sent: Sonntag, 22. Dezember 2024 13:53 To: Henning Westerholt hw@gilawa.com Cc: Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org; Alexis Fidalgo alzrck@gmail.com Subject: Re: [SR-Users] Re: Transactions help
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 <hw@gilawa.commailto:hw@gilawa.com> 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 <sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org> Sent: Sonntag, 22. Dezember 2024 00:34 To: Kamailio (SER) - Users Mailing List <sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org> Cc: Alexis Fidalgo <alzrck@gmail.commailto:alzrck@gmail.com>; Sergio Charrua <sergio.charrua@voip.ptmailto:sergio.charrua@voip.pt> 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:alice@1.2.3.4mailto:sip%3Aalice@1.2.3.4", "sip:bob@1.2.3.5mailto:sip%3Abob@1.2.3.5"] } ) # 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:alice@1.2.3.4mailto:sip%3Aalice@1.2.3.4,sip:bob@1.2.3.5mailto:sip%3Abob@1.2.3.5" # 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 <sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org> 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 -- sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.orgmailto:sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
Not in my last code example.... Using TM and transactions ... yet, i'm still having some issues....
Atenciosamente / Kind Regards / Cordialement / Un saludo,
*Sérgio Charrua*
On Mon, Dec 23, 2024 at 3:12 PM Henning Westerholt hw@gilawa.com wrote:
Hello Sergio,
but you are using a htable to actually keep a state. So, your solution would be not stateless in the end. You are simply not using the tm module to keep the state, but by another means.
Cheers,
Henning
*From:* Sergio Charrua sergio.charrua@voip.pt *Sent:* Sonntag, 22. Dezember 2024 13:53 *To:* Henning Westerholt hw@gilawa.com *Cc:* Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org; Alexis Fidalgo alzrck@gmail.com *Subject:* Re: [SR-Users] Re: Transactions help
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 hw@gilawa.com 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 sr-users@lists.kamailio.org *Sent:* Sonntag, 22. Dezember 2024 00:34 *To:* Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org *Cc:* Alexis Fidalgo alzrck@gmail.com; Sergio Charrua < sergio.charrua@voip.pt> *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:alice@1.2.3.4", "sip:bob@1.2.3.5"] } ) # 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:alice@1.2.3.4,sip:bob@1.2.3.5" # 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 < sr-users@lists.kamailio.org> 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
- 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 -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
There aren't really too many fruitful uses of Kamailio sans TM. Most intentions to go fully stateless, while understandable and full of noble intentions, end up being abandoned once it becomes apparent that things like failover aren't possible.
The performance argument for stateless harkens back to a different era in computing and memory. The argument isn't, strictly speaking, entirely meritless in 2024, and one can go down academic rabbit holes re: DoS and such. But as a practical matter, just do stateful if you're relaying anything anywhere, or engaged in asynchronous complications.
There should be a book: "How I Learned to Stop Worrying and Love the Stateful"...
-- Alex
* There aren't really too many fruitful uses of Kamailio sans TM.
Very much agree here. There are probably some good examples of having very lightweight load balancers, etc. that might really need to be stateless, but generally speaking real world applications will want to use tm.
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]https://www.sip.us/ [img]https://www.siptrunk.com/ [img]https://www.flowroute.com/
________________________________ From: Alex Balashov via sr-users sr-users@lists.kamailio.org Sent: Monday, December 23, 2024 9:24 AM To: Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org Cc: Alex Balashov abalashov@evaristesys.com Subject: [SR-Users] Re: Transactions help
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.
There aren't really too many fruitful uses of Kamailio sans TM. Most intentions to go fully stateless, while understandable and full of noble intentions, end up being abandoned once it becomes apparent that things like failover aren't possible.
The performance argument for stateless harkens back to a different era in computing and memory. The argument isn't, strictly speaking, entirely meritless in 2024, and one can go down academic rabbit holes re: DoS and such. But as a practical matter, just do stateful if you're relaying anything anywhere, or engaged in asynchronous complications.
There should be a book: "How I Learned to Stop Worrying and Love the Stateful"...
-- Alex
-- Alex Balashov Principal Consultant Evariste Systems LLC Web: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fevaristesy...https://evaristesys.com/ Tel: +1-706-510-6800
__________________________________________________________ Kamailio - Users Mailing List - Non Commercial Discussions -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
currently I have implemented the script as stateful, using transactions (TM). It works .... *BUT* ... I get this SIP flow:
10.20.0.1:5060 10.20.20.1:5060 ──────────┬───────── ──────────┬───────── 15:44:20.013645 │ INVITE (SDP) │ +0.002128 │ ──────────────────────────> │ 15:44:20.015773 │ 100 trying -- your call is │ +0.007130 │ <────────────────────────── │ 15:44:20.022903 │ 300 Multiple Choices │ +0.001481 │ <────────────────────────── │ 15:44:20.024384 │ ACK │ +0.467452 │ ──────────────────────────> │ 15:44:20.491836 │ 300 Multiple Choices │ +0.999940 │ <<<──────────────────────── │ 15:44:21.491776 │ 300 Multiple Choices │ │ <<<──────────────────────── │ │ │
Why is Kamailio sending 300 Multiple Choices after the last ACK when it should have already "exited" from processing the call? On the main route, i added: if (is_method("ACK") ) { # don't need to bother with ACK! xlog("L_INFO","New SIP message $rm with call-ID $ci \n"); exit; }
and the RELAY route is:
route[RELAY] { xlog("L_INFO", " ******** RELAY *******"); xlog("L_INFO", "RELAY - $rm to $si responding back to $su"); send_reply("300", "Multiple Choices"); exit; }
already tried multiple parameters, but no luck...still the same behaviour.... and setting logs to debug level, doesn't show anything:
Dec 23 15:44:20 kamailio1 kamailio[4050726]: INFO: {1 1 INVITE 1-2589892@10.20.0.1} <script>: RELAY_API - API ASYNC ROUTING REQUEST: {"from":"sipp sip:sipp@10.20.0.1:5060;tag=1","to":"<sip:1@10.20.20.1:5060
","r-uri":"sip:1@10.20.20.1:5060","contact":"sip:sipp@10.20.0.1:5060
;transport=UDP>","call-id":"1-2589892@10.20.0.1","request-time":""} Dec 23 15:44:20 kamailio1 kamailio[4050726]: INFO: {1 1 INVITE 1-2589892@10.20.0.1} <script>: RELAY_API - Calling Async Query to url http://IP:PORT/URL Dec 23 15:44:20 kamailio1 kamailio[4050756]: INFO: <script>: RELAY_API_RESPONSE - RESPONSE: {#012#011"SOME HIDDEN JSON "#012} Dec 23 15:44:20 kamailio1 kamailio[4050756]: INFO: <script>: ******** RELAY ******* Dec 23 15:44:20 kamailio1 kamailio[4050756]: INFO: <script>: RELAY - INVITE to 10.20.0.1 from sip:10.20.0.1:5060 Dec 23 15:44:20 kamailio1 kamailio[4050756]: WARNING: <core> [core/dset.c:690]: print_dset(): no r-uri or branches Dec 23 15:44:20 kamailio1 kamailio[4050756]: INFO: tm [tm.c:1686]: t_release(): invalid usage - not in request route Dec 23 15:44:20 kamailio1 kamailio[4050727]: INFO: {1 1 ACK 1-2589892@10.20.0.1} <script>: New SIP message ACK with call-ID 1-2589892@10.20.0.1
and it ends with this last log message.....
any clue any one?
@Alex Balashov ... "How I Learned to Stop Worrying and Love the Stateful" .... love the title! :)
Atenciosamente / Kind Regards / Cordialement / Un saludo,
*Sérgio Charrua*
On Mon, Dec 23, 2024 at 4:39 PM Alex Balashov via sr-users < sr-users@lists.kamailio.org> wrote:
There aren't really too many fruitful uses of Kamailio sans TM. Most intentions to go fully stateless, while understandable and full of noble intentions, end up being abandoned once it becomes apparent that things like failover aren't possible.
The performance argument for stateless harkens back to a different era in computing and memory. The argument isn't, strictly speaking, entirely meritless in 2024, and one can go down academic rabbit holes re: DoS and such. But as a practical matter, just do stateful if you're relaying anything anywhere, or engaged in asynchronous complications.
There should be a book: "How I Learned to Stop Worrying and Love the Stateful"...
-- Alex
-- Alex Balashov Principal Consultant Evariste Systems LLC Web: https://evaristesys.com Tel: +1-706-510-6800
Kamailio - Users Mailing List - Non Commercial Discussions -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
Sounds like you might be missing some negative ACK handling further upstream. Refer to the has_totag() / loose_route() block in the stock config.
-- Alex
On Dec 23, 2024, at 11:01 am, Sergio Charrua sergio.charrua@voip.pt wrote:
currently I have implemented the script as stateful, using transactions (TM). It works .... *BUT* ... I get this SIP flow:
10.20.0.1:5060 10.20.20.1:5060 ──────────┬───────── ──────────┬─────────
15:44:20.013645 │ INVITE (SDP) │ +0.002128 │ ──────────────────────────> │ 15:44:20.015773 │ 100 trying -- your call is │ +0.007130 │ <────────────────────────── │ 15:44:20.022903 │ 300 Multiple Choices │ +0.001481 │ <────────────────────────── │ 15:44:20.024384 │ ACK │ +0.467452 │ ──────────────────────────> │ 15:44:20.491836 │ 300 Multiple Choices │ +0.999940 │ <<<──────────────────────── │ 15:44:21.491776 │ 300 Multiple Choices │ │ <<<──────────────────────── │ │ │
Why is Kamailio sending 300 Multiple Choices after the last ACK when it should have already "exited" from processing the call? On the main route, i added: if (is_method("ACK") ) { # don't need to bother with ACK! xlog("L_INFO","New SIP message $rm with call-ID $ci \n"); exit; }
and the RELAY route is:
route[RELAY] { xlog("L_INFO", " ******** RELAY *******"); xlog("L_INFO", "RELAY - $rm to $si responding back to $su"); send_reply("300", "Multiple Choices"); exit; }
already tried multiple parameters, but no luck...still the same behaviour.... and setting logs to debug level, doesn't show anything:
Dec 23 15:44:20 kamailio1 kamailio[4050726]: INFO: {1 1 INVITE 1-2589892@10.20.0.1} <script>: RELAY_API - API ASYNC ROUTING REQUEST: {"from":"sipp sip:sipp@10.20.0.1:5060;tag=1","to":"sip:1@10.20.20.1:5060","r-uri":"sip:1@10.20.20.1:5060","contact":"sip:sipp@10.20.0.1:5060;transport=UDP>","call-id":"1-2589892@10.20.0.1","request-time":""} Dec 23 15:44:20 kamailio1 kamailio[4050726]: INFO: {1 1 INVITE 1-2589892@10.20.0.1} <script>: RELAY_API - Calling Async Query to url http://IP:PORT/URL Dec 23 15:44:20 kamailio1 kamailio[4050756]: INFO: <script>: RELAY_API_RESPONSE - RESPONSE: {#012#011"SOME HIDDEN JSON "#012} Dec 23 15:44:20 kamailio1 kamailio[4050756]: INFO: <script>: ******** RELAY ******* Dec 23 15:44:20 kamailio1 kamailio[4050756]: INFO: <script>: RELAY - INVITE to 10.20.0.1 from sip:10.20.0.1:5060 Dec 23 15:44:20 kamailio1 kamailio[4050756]: WARNING: <core> [core/dset.c:690]: print_dset(): no r-uri or branches Dec 23 15:44:20 kamailio1 kamailio[4050756]: INFO: tm [tm.c:1686]: t_release(): invalid usage - not in request route Dec 23 15:44:20 kamailio1 kamailio[4050727]: INFO: {1 1 ACK 1-2589892@10.20.0.1} <script>: New SIP message ACK with call-ID 1-2589892@10.20.0.1
and it ends with this last log message.....
any clue any one?
@Alex Balashov ... "How I Learned to Stop Worrying and Love the Stateful" .... love the title! :)
Atenciosamente / Kind Regards / Cordialement / Un saludo,
Sérgio Charrua
On Mon, Dec 23, 2024 at 4:39 PM Alex Balashov via sr-users sr-users@lists.kamailio.org wrote: There aren't really too many fruitful uses of Kamailio sans TM. Most intentions to go fully stateless, while understandable and full of noble intentions, end up being abandoned once it becomes apparent that things like failover aren't possible.
The performance argument for stateless harkens back to a different era in computing and memory. The argument isn't, strictly speaking, entirely meritless in 2024, and one can go down academic rabbit holes re: DoS and such. But as a practical matter, just do stateful if you're relaying anything anywhere, or engaged in asynchronous complications.
There should be a book: "How I Learned to Stop Worrying and Love the Stateful"...
-- Alex
-- Alex Balashov Principal Consultant Evariste Systems LLC Web: https://evaristesys.com Tel: +1-706-510-6800
Kamailio - Users Mailing List - Non Commercial Discussions -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
* the solution needs to be stateless
Why? This seems to be arbitrary. Suppose you wanted to retrieve the data via SIP rather than http: You'd be using a transaction. There's no magic here, and the benefit of http_async_client is that you're trading off holding the the process with an increased usage in shared memory.
Regarding the re-transmission of the 3xx, the likely reason is that you don't have a Contact: header in the reply, or that the rURI of the ACK doesn't match the Contact, etc. These are the typical reasons any ACK doesn't get matched.
Regarding an example, I added an example for a 300 reply to my previous example project https://github.com/whosgonna/kamailio_http_async/tree/reply300
The difference from the main branch is:
1. 300 reply is sent 2. The reply has a contact header (which a 3xx should have, and is probably why your ACK is failing) 3. Added a new sipp testing scenario file for handling a 300, using the received Contact as the ACK ruri.
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]https://www.sip.us [img]https://www.siptrunk.com [img]https://www.flowroute.com
________________________________ From: Sergio Charrua via sr-users sr-users@lists.kamailio.org Sent: Sunday, December 22, 2024 6:52 AM To: Henning Westerholt hw@gilawa.com Cc: Kamailio (SER) - Users Mailing List sr-users@lists.kamailio.org; Alexis Fidalgo alzrck@gmail.com; Sergio Charrua sergio.charrua@voip.pt Subject: [SR-Users] Re: Transactions help
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 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 <hw@gilawa.commailto:hw@gilawa.com> 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 <sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org> Sent: Sonntag, 22. Dezember 2024 00:34 To: Kamailio (SER) - Users Mailing List <sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org> Cc: Alexis Fidalgo <alzrck@gmail.commailto:alzrck@gmail.com>; Sergio Charrua <sergio.charrua@voip.ptmailto:sergio.charrua@voip.pt> 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%5Dhttp://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:alice@1.2.3.4mailto:sip%3Aalice@1.2.3.4", "sip:bob@1.2.3.5mailto:sip%3Abob@1.2.3.5"] } ) # 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:alice@1.2.3.4mailto:sip%3Aalice@1.2.3.4,sip:bob@1.2.3.5mailto:sip%3Abob@1.2.3.5" # 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 <sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org> 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 -- sr-users@lists.kamailio.orgmailto:sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.orgmailto:sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
You probably know this article, already, but Nick vs Networking has this nice explanation:
Stateless, Stateful, Dialog Stateful and Transaction Stateful SIP Proxies | Nick vs Networking https://nickvsnetworking.com/stateless-stateful-dialog-stateful-and-transaction-stateful-sip-proxies/
Atenciosamente / Kind Regards / Cordialement / Un saludo,
*Sérgio Charrua*
On Sat, Dec 21, 2024 at 5:31 PM Alexis Fidalgo via sr-users < sr-users@lists.kamailio.org> 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
- 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 -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
Yes i did, concept is clear, what is not clear (to me) is why in a transaction, if i reply a 302, it’s retransmitted 3 times until the transaction is released.
On 21 Dec 2024, at 8:35 PM, Sergio Charrua via sr-users sr-users@lists.kamailio.org wrote:
You probably know this article, already, but Nick vs Networking has this nice explanation:
Stateless, Stateful, Dialog Stateful and Transaction Stateful SIP Proxies | Nick vs Networking https://nickvsnetworking.com/stateless-stateful-dialog-stateful-and-transaction-stateful-sip-proxies/
Atenciosamente / Kind Regards / Cordialement / Un saludo,
Sérgio Charrua
On Sat, Dec 21, 2024 at 5:31 PM Alexis Fidalgo via sr-users <sr-users@lists.kamailio.org mailto:sr-users@lists.kamailio.org> 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
- A new transaction is created before the http_async call (as the module example shows for http_async_query function
- The http_async_query call is executed, receives a response and the HTTP_REPLY route for http_async_query is executed.
- 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 -- sr-users@lists.kamailio.org mailto:sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org mailto:sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
Kamailio - Users Mailing List - Non Commercial Discussions -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
Although I admire Nick's work, and his gift for making complex concepts accessible to a lay audience--I've learned quite a bit from his posts myself--some of the misinformation and simplification in this one is unforgivable, e.g.
"A Transaction Stateful proxy stores state from the initial INVITE until a 200 OK is received. As soon as the session is setup it forgets everything. This means we won’t have any state information when the BYE is eventually received."
This is radioactively wrong.
-- Alex
On Dec 22, 2024, at 10:03 am, Alexis Fidalgo via sr-users sr-users@lists.kamailio.org wrote:
Yes i did, concept is clear, what is not clear (to me) is why in a transaction, if i reply a 302, it’s retransmitted 3 times until the transaction is released.
On 21 Dec 2024, at 8:35 PM, Sergio Charrua via sr-users sr-users@lists.kamailio.org wrote:
You probably know this article, already, but Nick vs Networking has this nice explanation:
Stateless, Stateful, Dialog Stateful and Transaction Stateful SIP Proxies | Nick vs Networking
Atenciosamente / Kind Regards / Cordialement / Un saludo,
Sérgio Charrua
On Sat, Dec 21, 2024 at 5:31 PM Alexis Fidalgo via sr-users sr-users@lists.kamailio.org 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
- A new transaction is created before the http_async call (as the module example shows for http_async_query function
- The http_async_query call is executed, receives a response and the HTTP_REPLY route for http_async_query is executed.
- 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 -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender! __________________________________________________________ Kamailio - Users Mailing List - Non Commercial Discussions -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
Kamailio - Users Mailing List - Non Commercial Discussions -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
On 22 Dec 2024, at 16:45, Alex Balashov via sr-users sr-users@lists.kamailio.org wrote:
Although I admire Nick's work, and his gift for making complex concepts accessible to a lay audience--I've learned quite a bit from his posts myself--some of the misinformation and simplification in this one is unforgivable, e.g.
"A Transaction Stateful proxy stores state from the initial INVITE until a 200 OK is received. As soon as the session is setup it forgets everything. This means we won’t have any state information when the BYE is eventually received."
This is radioactively wrong.
Apart from missing the ACK, what do you think is wrong with this?
/O
-- Alex
On Dec 22, 2024, at 10:03 am, Alexis Fidalgo via sr-users sr-users@lists.kamailio.org wrote:
Yes i did, concept is clear, what is not clear (to me) is why in a transaction, if i reply a 302, it’s retransmitted 3 times until the transaction is released.
On 21 Dec 2024, at 8:35 PM, Sergio Charrua via sr-users sr-users@lists.kamailio.org wrote:
You probably know this article, already, but Nick vs Networking has this nice explanation:
Stateless, Stateful, Dialog Stateful and Transaction Stateful SIP Proxies | Nick vs Networking
Atenciosamente / Kind Regards / Cordialement / Un saludo,
Sérgio Charrua
On Sat, Dec 21, 2024 at 5:31 PM Alexis Fidalgo via sr-users sr-users@lists.kamailio.org 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
- A new transaction is created before the http_async call (as the module example shows for http_async_query function
- The http_async_query call is executed, receives a response and the HTTP_REPLY route for http_async_query is executed.
- 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 -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender! __________________________________________________________ Kamailio - Users Mailing List - Non Commercial Discussions -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
Kamailio - Users Mailing List - Non Commercial Discussions -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
-- Alex Balashov Principal Consultant Evariste Systems LLC Web: https://evaristesys.com Tel: +1-706-510-6800
Kamailio - Users Mailing List - Non Commercial Discussions -- sr-users@lists.kamailio.org To unsubscribe send an email to sr-users-leave@lists.kamailio.org Important: keep the mailing list in the recipients, do not reply only to the sender!
On Dec 22, 2024, at 12:38 pm, Olle E. Johansson oej@edvina.net wrote:
On 22 Dec 2024, at 16:45, Alex Balashov via sr-users sr-users@lists.kamailio.org wrote:
Although I admire Nick's work, and his gift for making complex concepts accessible to a lay audience--I've learned quite a bit from his posts myself--some of the misinformation and simplification in this one is unforgivable, e.g.
"A Transaction Stateful proxy stores state from the initial INVITE until a 200 OK is received. As soon as the session is setup it forgets everything. This means we won’t have any state information when the BYE is eventually received."
This is radioactively wrong.
Apart from missing the ACK, what do you think is wrong with this?
It doesn't really describe what transactions are or how they work:
- Any request can form a transaction;
- A transaction exists for the entire lifecycle of the request, starting from the request, encapsulating zero or more 1xx provisional messages (if applicable), and a final dispositive reply;
- A 200 OK is not the only final dispositive reply at the end of a transaction life cycle.
This is so obvious to experienced SIP folks that we don't even think about it, but an article aiming to digest this subject matter closer to the entry level can do better.
-- Alex