From 9aa763f2600525c0a0c8d5dd72114b4d5d7b1b90 Mon Sep 17 00:00:00 2001 From: hishamway Date: Thu, 15 Jan 2026 15:04:08 +0530 Subject: [PATCH] res_pjsip_session.c: Prevent INVITE failover when session is cancelled When an outbound INVITE transaction times out (408) or receives a 503 error, check_request_status() attempts to failover to the next available address by restarting the INVITE session. However, the function did not check if the inv_session was already cancelled before attempting the failover. This caused unexpected behavior when a caller hung up during a ring group scenario: after CANCEL was sent but the remote endpoint failed to respond with 487 (e.g., due to network disconnection), the transaction timeout would trigger a NEW outbound INVITE to the next address, even though the session was already terminated. This violates RFC 3261 Section 9.1 which states that if no final response is received after CANCEL within 64*T1 seconds, the client should consider the transaction cancelled and destroy it, not retry to another address. The fix adds a check for both PJSIP_INV_STATE_DISCONNECTED and inv->cancelling at the beginning of check_request_status(). This ensures that: - Failover is blocked when the user explicitly cancelled the call (CANCEL sent) - Failover is still allowed for legitimate timeout/503 scenarios where no CANCEL was initiated (e.g., SRV failover when first server is unreachable) Resolves: #1716 --- res/res_pjsip_session.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index 135aa19279..a731d3ec65 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -4556,6 +4556,10 @@ static int check_request_status(pjsip_inv_session *inv, pjsip_event *e) struct ast_sip_session *session = inv->mod_data[session_module.id]; pjsip_transaction *tsx = e->body.tsx_state.tsx; + if (inv->state == PJSIP_INV_STATE_DISCONNECTED && inv->cancelling) { + return 0; + } + if (tsx->status_code != 503 && tsx->status_code != 408) { return 0; }