sergey-safarov created an issue (kamailio/kamailio#4315)
### Description Use case WebRTC client connected to Kaamilio Edge proxy.
For network connectivity reasons, the flow token may no longer be valid. In this case, behavior should be described in the [RFC5626, 5.3.1 Processing Incoming Requests](https://datatracker.ietf.org/doc/html/rfc5626#section-5.3.1)
If the flow no longer exists, the proxy SHOULD send a 430 (Flow Failed) response to the request.
Also [9.3 Incoming Call and Proxy Crash](https://datatracker.ietf.org/doc/html/rfc5626#section-9.3)
Bob's authoritative proxy first tries the flow to EP1, but EP1 no longer has a flow to Bob, so it responds with a 430 (Flow Failed) response.
To get it working, it will be fine to use construction like ``` if (!loose_route()) { switch($rc) { case -4: sl_send_reply("403", "Flow Failed"); exit; case -2: sl_send_reply("403", "Forbidden"); exit; default: xlog("L_ERR", "in request_route\n"); sl_reply_error(); exit; } } ``` Where `loose_route` returns a new error code (`-4` for example). This error code is generated when the flow token points to not existing TCP/TLS/WSS connection.
### Expected behavior Kamailio `loose_route` allows the check of flow token validity before messages related via non-existent TCP/TLS/WSS connections.
#### Actual observed behavior For now, Kamailio tries to relay messages to non-existent client connections and generate an error message like ``` 477 Unfortunately error on sending to next hop occurred (477/TM) 500 Message processing error (2/TM) ```
#### How to reproduce
Required to start Kamailio with a config like ``` listen=udp:127.0.0.1:5060 listen=tcp:127.0.0.1:5060
loadmodule "pv.so" loadmodule "xlog.so" loadmodule "sl.so" loadmodule "tm.so" loadmodule "siputils.so" loadmodule "rr.so"
loadmodule "stun.so" loadmodule "outbound.so" modparam("outbound", "force_outbound_flag", 1) modparam("outbound", "flow_token_secret", "kamailio")
loadmodule "debugger.so" modparam("debugger", "cfgtrace", 1) modparam("debugger", "log_level_name", "exec")
request_route { loose_route(); switch($rc) { case -3: xlog("L_ERR", "loose_route code -3\n"); break; case -2: xlog("L_ERR", "loose_route code -2\n"); break; case -1: xlog("L_ERR", "loose_route code -1\n"); break; case 1: xlog("L_ERR", "loose_route code 1\n"); break; case 2: xlog("L_ERR", "loose_route code 2\n"); break; } record_route();
if (has_totag()) { t_relay(); } else { t_relay_to_udp("127.0.0.1", "5080"); } } ``` Then need to start SIPp server script using the command ``` sipp -sf uas.xml -p 5080 -d 4000 -bind_local 127.0.0.1 ``` And then start SIPp client script using the command ``` sipp -sf uac.xml -m 1 -t t1 127.0.0.1 ``` Where `uac.xml` and `uas.xml` are attached
[sipp-scripts.tar.gz](https://github.com/user-attachments/files/21187724/sipp-scripts.tar.gz)
miconda left a comment (kamailio/kamailio#4315)
I think you can leverage the tcpops already to figure out if the connection to target is active or not:
- https://www.kamailio.org/docs/modules/devel/modules/tcpops.html#tcpops.f.tcp...
sergey-safarov left a comment (kamailio/kamailio#4315)
I have updated the Kamailio configuration, and it is now working.
<details> <summary>config</summary> ``` listen=udp:127.0.0.1:5060 listen=tcp:127.0.0.1:5060
loadmodule "tm.so"
loadmodule "pv.so" loadmodule "xlog.so" loadmodule "sl.so" loadmodule "siputils.so" loadmodule "tcpops.so" loadmodule "textops.so" loadmodule "rr.so"
loadmodule "stun.so" loadmodule "outbound.so" modparam("outbound", "force_outbound_flag", 1) modparam("outbound", "flow_token_secret", "kamailio")
loadmodule "debugger.so" modparam("debugger", "cfgtrace", 1) modparam("debugger", "log_level_name", "exec")
request_route { loose_route(); switch($rc) { case -3: xlog("L_ERR", "loose_route code -3\n"); break; case -2: xlog("L_ERR", "loose_route code -2\n"); break; case -1: xlog("L_ERR", "loose_route code -1\n"); break; case 1: xlog("L_ERR", "loose_route code 1\n"); break; case 2: xlog("L_ERR", "loose_route code 2\n"); route(TRY_TCP_CONN); break; } record_route();
if (has_totag()) { t_relay(); } else { t_relay_to_udp("127.0.0.1", "5080"); } }
route[TRY_TCP_CONN] { if($(du{uri.transport}{s.tolower})=="udp") { return; }
$var(host_port) = $_s($(du{uri.tosocket}{s.tolower}{re.subst,/^tcp://})); if(!tcp_con_alive("$var(host_port)")) { sl_send_reply("430", "Flow Failed"); exit; } } ``` </details>
Can something be used with the `UDP` transport? Usecase: "outbound client" uses UDP, and the Kamailio outbound module sends keepalives to the client. When no response, then send "430 Flow Failed" response.