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; /*!< Request that opened the latest transaction
within this SIP dialog */
-
+
int maxtime; /*!< Max time for first response */
int initid; /*!< Auto-congest ID if appropriate (scheduler) */
int waitid; /*!< Wait ID for scheduler after 491 or other delays */
ast_log(LOG_DEBUG, "Sending pending reinvite on '%s'\n", p->callid);
/* Didn't get to reinvite yet, so do it now */
transmit_reinvite_with_sdp(p);
- ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE);
+ ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE);
}
}
}
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);
+ ast_mutex_lock(&p->lock); /* called from schedule thread which requires a lock */
+ ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
p->waitid = -1;
+ check_pendings(p);
+ ast_mutex_unlock(&p->lock);
return 0;
}
int xmitres = 0;
int reinvite = (p->owner && p->owner->_state == AST_STATE_UP);
struct ast_channel *bridgepeer = NULL;
-
+
if (option_debug > 3) {
if (reinvite)
ast_log(LOG_DEBUG, "SIP response %d to RE-invite on %s call %s\n", resp, outgoing ? "outgoing" : "incoming", p->callid);
if (p->owner && !ast_test_flag(req, SIP_PKT_IGNORE)) {
if (p->owner->_state != AST_STATE_UP) {
ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
} else {
/* 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, p);
+ 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 (ast_test_flag(&p->flags[1], SIP_PAGE2_OUTGOING_CALL)) {
+ wait = 2100 + ast_random() % 2000;
+ } else {
+ wait = ast_random() % 2000;
+ }
+ p->waitid = ast_sched_add(sched, wait, sip_reinvite_retry, p);
if (option_debug > 2)
ast_log(LOG_DEBUG, "Reinvite race. Waiting %d secs before retry\n", wait);
}
if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->pendinginvite) {
/* We already have a pending invite. Sorry. You are on hold. */
+ p->glareinvite = seqno;
transmit_response_reliable(p, "491 Request Pending", req);
if (option_debug)
ast_log(LOG_DEBUG, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid);
if (find_sdp(req)) {
if (process_sdp(p, req))
return -1;
- }
+ }
check_pendings(p);
+ } else if (p->glareinvite == seqno) {
+ /* handle ack for the 491 pending send 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))