From 06c111b877a5c9d03b6fc252ec19c104963612e4 Mon Sep 17 00:00:00 2001 From: renny678 <131391490+renny678@users.noreply.github.com> Date: Wed, 14 Oct 2026 09:57:48 +0800 Subject: [PATCH] nta: ACK and BYE an orphan 2xx over the connection the INVITE was sent on When a 2xx arrives for an INVITE client transaction that was already cancelled, outgoing_recv() calls nta_msg_ackbye(), which routes the ACK and BYE by the Contact of the 2xx. A SIP WebSocket client (RFC 7118) puts a random ".invalid" host there, so the ACK fails with "transport ws is not supported". The client keeps retransmitting the 2xx for 64*T1 and rejects new INVITEs with 486 meanwhile. Send the ACK and BYE over the transport of the original INVITE. It is used only when it is an established connection (TCP, TLS, WS, WSS), so routing over UDP is unchanged. Co-Authored-By: Claude Opus 5.5 --- libsofia-sip-ua/nta/nta.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libsofia-sip-ua/nta/nta.c b/libsofia-sip-ua/nta/nta.c index e5f788d7..bcde6074 100644 --- a/libsofia-sip-ua/nta/nta.c +++ b/libsofia-sip-ua/nta/nta.c @@ -3930,7 +3930,17 @@ int complete_response(msg_t *response, * let it terminate the session. As of @VERSION_1_12_7, this function just * returns -1. */ +static int nta_msg_ackbye_tport(nta_agent_t *agent, msg_t *msg, tport_t *tport); + int nta_msg_ackbye(nta_agent_t *agent, msg_t *msg) +{ + return nta_msg_ackbye_tport(agent, msg, NULL); +} + +/* ACK and BYE over the transport the orphan 2XX arrived on when given: + * WebSocket clients (RFC 7118) use an unroutable ".invalid" Contact and + * are reachable only over their existing connection. */ +static int nta_msg_ackbye_tport(nta_agent_t *agent, msg_t *msg, tport_t *tport) { sip_t *sip = sip_object(msg); msg_t *amsg = nta_msg_create(agent, 0); @@ -3992,6 +4002,7 @@ int nta_msg_ackbye(nta_agent_t *agent, msg_t *msg) if (!(ack = nta_outgoing_mcreate(agent, NULL, NULL, NULL, amsg, NTATAG_ACK_BRANCH(sip->sip_via->v_branch), NTATAG_STATELESS(1), + TAG_IF(tport, NTATAG_TPORT(tport)), TAG_END()))) goto err; else @@ -4011,6 +4022,7 @@ int nta_msg_ackbye(nta_agent_t *agent, msg_t *msg) if (!nta_outgoing_mcreate(agent, NULL, NULL, NULL, bmsg, NTATAG_STATELESS(1), + TAG_IF(tport, NTATAG_TPORT(tport)), TAG_END())) goto err; @@ -9549,7 +9561,7 @@ int outgoing_recv(nta_outgoing_t *_orq, if (orq->orq_uas && su_strcasecmp(sip->sip_to->a_tag, orq->orq_tag) != 0) { /* Orphan 200 Ok to INVITE. ACK and BYE it */ SU_DEBUG_5(("nta: Orphan 200 Ok send ACK&BYE %p\n", (void *)orq)); - return nta_msg_ackbye(sa, msg); + return nta_msg_ackbye_tport(sa, msg, orq->orq_tport); } return -1; /* Proxy statelessly (RFC3261 section 16.11) */ } @@ -9611,7 +9623,7 @@ int outgoing_recv(nta_outgoing_t *_orq, /* Orphan 200 Ok to INVITE. ACK and BYE it */ SU_DEBUG_5(("nta: Orphan 200 Ok send ACK&BYE" VA_NONE)); - return nta_msg_ackbye(sa, msg); + return nta_msg_ackbye_tport(sa, msg, orq->orq_tport); } }