[asterisk-commits] dvossel: trunk r185846 - in /trunk: ./ channels/chan_sip.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Apr 1 14:03:38 CDT 2009
Author: dvossel
Date: Wed Apr 1 14:03:32 2009
New Revision: 185846
URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=185846
Log:
Merged revisions 185845 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r185845 | dvossel | 2009-04-01 14:02:00 -0500 (Wed, 01 Apr 2009) | 10 lines
Fixes issue with dropped calles due to re-Invite glare and re-Invites never executing after a 491
Acknowledgement for 491 responses were never being processed because it didn't match our pending invite's seqno. Since the ACK was never processed, the 491 frame would continue to be retransmitted until eventually the call was dropped due to max retries. Now during a pending invite, if we receive another invite, we send an 491 and hold on to that glare invite's seqno in the "glareinvite" variable for that sip_pvt struct. When ACK's are received, we first check to see if it is in response to our pending invite, if not we check to see if it is in response to a glare invite. In this case, it is in response to the glare invite and must be dealt with or the call is dropped. I've changed the wait time for resending the re-Invite after receving a 491 response to comply with RFC 3261. Before this patch the scheduled re-Invite would only change a flag indicating that the re-Invite should be sent out, now it actually sends it out as well.
(closes issue #12013)
Reported by: alx
Review: http://reviewboard.digium.com/r/213/
........
Modified:
trunk/ (props changed)
trunk/channels/chan_sip.c
Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.
Modified: trunk/channels/chan_sip.c
URL: http://svn.digium.com/svn-view/asterisk/trunk/channels/chan_sip.c?view=diff&rev=185846&r1=185845&r2=185846
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Wed Apr 1 14:03:32 2009
@@ -1670,17 +1670,19 @@
struct ast_channel *owner; /*!< Who owns us (if we have an owner) */
struct sip_route *route; /*!< Head of linked list of routing steps (fm Record-Route) */
int route_persistant; /*!< Is this the "real" route? */
- struct ast_variable *notify_headers; /*!< Custom notify type */
+ struct ast_variable *notify_headers; /*!< Custom notify type */
struct sip_auth *peerauth; /*!< Realm authentication */
int noncecount; /*!< Nonce-count */
char lastmsg[256]; /*!< Last Message sent/received */
int amaflags; /*!< AMA Flags */
int pendinginvite; /*!< Any pending INVITE or state NOTIFY (in subscribe pvt's) ? (seqno of this) */
+ int glareinvite; /*!< A invite received while a pending invite is already present is stored here. Its seqno is the
+ value. Since this glare invite's seqno is not the same as the pending invite's, it must be
+ held in order to properly process acknowledgements for our 491 response. */
struct sip_request initreq; /*!< Latest request that opened a new transaction
within this dialog.
- NOT the request that opened the dialog
- */
-
+ NOT the request that opened the dialog */
+
int initid; /*!< Auto-congest ID if appropriate (scheduler) */
int waitid; /*!< Wait ID for scheduler after 491 or other delays */
int autokillid; /*!< Auto-kill ID (scheduler) */
@@ -1691,9 +1693,9 @@
int stateid; /*!< SUBSCRIBE: ID for devicestate subscriptions */
int laststate; /*!< SUBSCRIBE: Last known extension state */
int dialogver; /*!< SUBSCRIBE: Version for subscription dialog-info */
-
+
struct ast_dsp *vad; /*!< Inband DTMF Detection dsp */
-
+
struct sip_peer *relatedpeer; /*!< If this dialog is related to a peer, which one
Used in peerpoke, mwi subscriptions */
struct sip_registry *registry; /*!< If this is a REGISTER dialog, to which registry */
@@ -16504,12 +16506,15 @@
to avoid race conditions between asterisk servers.
Called from the scheduler.
*/
-static int sip_reinvite_retry(const void *data)
+static int sip_reinvite_retry(const void *data)
{
struct sip_pvt *p = (struct sip_pvt *) data;
- ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
+ sip_pvt_lock(p); /* called from schedule thread which requires a lock */
+ ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
p->waitid = -1;
+ check_pendings(p);
+ sip_pvt_unlock(p);
dialog_unref(p, "unref the dialog ptr from sip_reinvite_retry, because it held a dialog ptr");
return 0;
}
@@ -16524,7 +16529,7 @@
int reinvite = (p->owner && p->owner->_state == AST_STATE_UP);
char *p_hdrval;
int rtn;
-
+
if (reinvite)
ast_debug(4, "SIP response %d to RE-invite on %s call %s\n", resp, outgoing ? "outgoing" : "incoming", p->callid);
else
@@ -16800,8 +16805,15 @@
/* This is a re-invite that failed. */
/* Reset the flag after a while
*/
- int wait = 3 + ast_random() % 5;
- p->waitid = ast_sched_add(sched, wait, sip_reinvite_retry, dialog_ref(p, "passing dialog ptr into sched structure based on waitid for sip_reinvite_retry."));
+ int wait;
+ /* RFC 3261, if owner of call, wait between 2.1 to 4 seconds,
+ * if not owner of call, wait 0 to 2 seconds */
+ if (p->outgoing_call) {
+ wait = 2100 + ast_random() % 2000;
+ } else {
+ wait = ast_random() % 2000;
+ }
+ p->waitid = ast_sched_add(sched, wait, sip_reinvite_retry, dialog_ref(p, "passing dialog ptr into sched structure based on waitid for sip_reinvite_retry."));
ast_log(LOG_WARNING, "just did sched_add waitid(%d) for sip_reinvite_retry for dialog %s in handle_response_invite\n", p->waitid, p->callid);
ast_debug(2, "Reinvite race. Waiting %d secs before retry\n", wait);
}
@@ -18675,9 +18687,10 @@
return transmit_invite(p, SIP_INVITE, 1, 3);
}
}
-
+
if (!req->ignore && p->pendinginvite) {
/* We already have a pending invite. Sorry. You are on hold. */
+ p->glareinvite = seqno; /* must hold on to this seqno to process ack and retransmit correctly */
transmit_response_reliable(p, "491 Request Pending", req);
ast_debug(1, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid);
/* Don't destroy dialog here */
@@ -20551,8 +20564,12 @@
if (find_sdp(req)) {
if (process_sdp(p, req, SDP_T38_NONE))
return -1;
- }
+ }
check_pendings(p);
+ } else if (p->glareinvite == seqno) {
+ /* handle ack for the 491 pending sent for glareinvite */
+ p->glareinvite = 0;
+ __sip_ack(p, seqno, 1, 0);
}
/* Got an ACK that we did not match. Ignore silently */
if (!p->lastinvite && ast_strlen_zero(p->randdata)) {
More information about the asterisk-commits
mailing list