aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_sip.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/chan_sip.c')
-rw-r--r--channels/chan_sip.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index e68fc7333..6887e81f1 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -3339,8 +3339,26 @@ static int retrans_pkt(const void *data)
pkt->owner->owner->hangupcause = AST_CAUSE_NO_USER_RESPONSE;
}
if (pkt->owner->owner) {
- sip_alreadygone(pkt->owner);
ast_log(LOG_WARNING, "Hanging up call %s - no reply to our critical packet (see doc/sip-retransmit.txt).\n", pkt->owner->callid);
+
+ if (pkt->is_resp &&
+ (pkt->response_code >= 200) &&
+ (pkt->response_code < 300) &&
+ pkt->owner->pendinginvite &&
+ ast_test_flag(&pkt->owner->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED)) {
+ /* This is a timeout of the 2XX response to a pending INVITE. In this case terminate the INVITE
+ * transaction just as if we received the ACK, but immediately hangup with a BYE (sip_hangup
+ * will send the BYE as long as the dialog is not set as "alreadygone")
+ * RFC 3261 section 13.3.1.4.
+ * "If the server retransmits the 2xx response for 64*T1 seconds without receiving
+ * an ACK, the dialog is confirmed, but the session SHOULD be terminated. This is
+ * accomplished with a BYE, as described in Section 15." */
+ pkt->owner->invitestate = INV_TERMINATED;
+ pkt->owner->pendinginvite = 0;
+ } else {
+ /* there is nothing left to do, mark the dialog as gone */
+ sip_alreadygone(pkt->owner);
+ }
ast_queue_hangup_with_cause(pkt->owner->owner, AST_CAUSE_PROTOCOL_ERROR);
ast_channel_unlock(pkt->owner->owner);
} else {