aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-05-24 20:09:24 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-05-24 20:09:24 +0000
commitf7d22e8dcf6a9daf1b0fbd9e35ec94476a7a6f77 (patch)
treea7517a2324f655fcea6623be19c6b37fc6dfc804
parent0306fcce5b10ed9f68cb7d0b1bf3840cd8350b5c (diff)
don't send CANCEL on a pending INVITE if we haven't received a provisional response yet... mark it pending until the first response is received (issue #7079)
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.2@30069 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--channels/chan_sip.c74
1 files changed, 50 insertions, 24 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 18929876a..ed1b8f5b9 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -530,7 +530,7 @@ struct sip_auth {
#define SIP_USECLIENTCODE (1 << 12) /*!< Trust X-ClientCode info message */
#define SIP_OUTGOING (1 << 13) /*!< Is this an outgoing call? */
#define SIP_SELFDESTRUCT (1 << 14) /*!< This is an autocreated peer */
-#define SIP_DYNAMIC (1 << 15) /*!< Is this a dynamic peer? */
+#define SIP_CAN_BYE (1 << 15) /*!< Can we send BYE for this dialog? */
/* --- Choices for DTMF support in SIP channel */
#define SIP_DTMF (3 << 16) /*!< three settings, uses two bits */
#define SIP_DTMF_RFC2833 (0 << 16) /*!< RTP DTMF */
@@ -580,6 +580,7 @@ struct sip_auth {
#define SIP_PAGE2_RTAUTOCLEAR (1 << 2)
#define SIP_PAGE2_IGNOREREGEXPIRE (1 << 3)
#define SIP_PAGE2_RT_FROMCONTACT (1 << 4)
+#define SIP_PAGE2_DYNAMIC (1 << 5) /*!< Is this a dynamic peer? */
/* SIP packet flags */
#define SIP_PKT_DEBUG (1 << 0) /*!< Debug this packet */
@@ -2456,12 +2457,18 @@ static int sip_hangup(struct ast_channel *ast)
/* stop retransmitting an INVITE that has not received a response */
__sip_pretend_ack(p);
- /* Send a new request: CANCEL */
- transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, 1, 0);
- /* Actually don't destroy us yet, wait for the 487 on our original
- INVITE, but do set an autodestruct just in case we never get it. */
- ast_clear_flag(&locflags, SIP_NEEDDESTROY);
- sip_scheddestroy(p, 32000);
+ /* are we allowed to send CANCEL yet? if not, mark
+ it pending */
+ if (!ast_test_flag(p, SIP_CAN_BYE)) {
+ ast_set_flag(p, SIP_PENDINGBYE);
+ } else {
+ /* Send a new request: CANCEL */
+ transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, 1, 0);
+ /* Actually don't destroy us yet, wait for the 487 on our original
+ INVITE, but do set an autodestruct just in case we never get it. */
+ ast_clear_flag(&locflags, SIP_NEEDDESTROY);
+ sip_scheddestroy(p, 32000);
+ }
if ( p->initid != -1 ) {
/* channel still up - reverse dec of inUse counter
only if the channel is not auto-congested */
@@ -6495,7 +6502,7 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si
ASTOBJ_UNREF(peer,sip_destroy_peer);
}
if (peer) {
- if (!ast_test_flag(peer, SIP_DYNAMIC)) {
+ if (!ast_test_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC)) {
ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name);
} else {
ast_copy_flags(p, peer, SIP_NAT);
@@ -7644,7 +7651,7 @@ static int _sip_show_peers(int fd, int *total, struct mansession *s, struct mess
snprintf(srch, sizeof(srch), FORMAT, name,
iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), iterator->addr.sin_addr) : "(Unspecified)",
- ast_test_flag(iterator, SIP_DYNAMIC) ? " D " : " ", /* Dynamic or not? */
+ ast_test_flag(&iterator->flags_page2, SIP_PAGE2_DYNAMIC) ? " D " : " ", /* Dynamic or not? */
(ast_test_flag(iterator, SIP_NAT) & SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */
iterator->ha ? " A " : " ", /* permit/deny */
ntohs(iterator->addr.sin_port), status);
@@ -7652,7 +7659,7 @@ static int _sip_show_peers(int fd, int *total, struct mansession *s, struct mess
if (!s) {/* Normal CLI list */
ast_cli(fd, FORMAT, name,
iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), iterator->addr.sin_addr) : "(Unspecified)",
- ast_test_flag(iterator, SIP_DYNAMIC) ? " D " : " ", /* Dynamic or not? */
+ ast_test_flag(&iterator->flags_page2, SIP_PAGE2_DYNAMIC) ? " D " : " ", /* Dynamic or not? */
(ast_test_flag(iterator, SIP_NAT) & SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */
iterator->ha ? " A " : " ", /* permit/deny */
@@ -7674,7 +7681,7 @@ static int _sip_show_peers(int fd, int *total, struct mansession *s, struct mess
iterator->name,
iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), iterator->addr.sin_addr) : "-none-",
ntohs(iterator->addr.sin_port),
- ast_test_flag(iterator, SIP_DYNAMIC) ? "yes" : "no", /* Dynamic or not? */
+ ast_test_flag(&iterator->flags_page2, SIP_PAGE2_DYNAMIC) ? "yes" : "no", /* Dynamic or not? */
(ast_test_flag(iterator, SIP_NAT) & SIP_NAT_ROUTE) ? "yes" : "no", /* NAT=yes? */
iterator->ha ? "yes" : "no", /* permit/deny */
status);
@@ -8047,7 +8054,7 @@ static int _sip_show_peer(int type, int fd, struct mansession *s, struct message
ast_cli(fd, " VM Extension : %s\n", peer->vmexten);
ast_cli(fd, " LastMsgsSent : %d\n", peer->lastmsgssent);
ast_cli(fd, " Call limit : %d\n", peer->call_limit);
- ast_cli(fd, " Dynamic : %s\n", (ast_test_flag(peer, SIP_DYNAMIC)?"Yes":"No"));
+ ast_cli(fd, " Dynamic : %s\n", (ast_test_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC)?"Yes":"No"));
ast_cli(fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
ast_cli(fd, " Expire : %d\n", peer->expire);
ast_cli(fd, " Insecure : %s\n", insecure2str(ast_test_flag(peer, SIP_INSECURE_PORT), ast_test_flag(peer, SIP_INSECURE_INVITE)));
@@ -8119,7 +8126,7 @@ static int _sip_show_peer(int type, int fd, struct mansession *s, struct message
ast_cli(fd, "VoiceMailbox: %s\r\n", peer->mailbox);
ast_cli(fd, "LastMsgsSent: %d\r\n", peer->lastmsgssent);
ast_cli(fd, "Call limit: %d\r\n", peer->call_limit);
- ast_cli(fd, "Dynamic: %s\r\n", (ast_test_flag(peer, SIP_DYNAMIC)?"Y":"N"));
+ ast_cli(fd, "Dynamic: %s\r\n", (ast_test_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC)?"Y":"N"));
ast_cli(fd, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, ""));
ast_cli(fd, "RegExpire: %ld seconds\r\n", ast_sched_when(sched,peer->expire));
ast_cli(fd, "SIP-AuthInsecure: %s\r\n", insecure2str(ast_test_flag(peer, SIP_INSECURE_PORT), ast_test_flag(peer, SIP_INSECURE_INVITE)));
@@ -9383,7 +9390,7 @@ static char *function_sippeer(struct ast_channel *chan, char *cmd, char *data, c
} else if (!strcasecmp(colname, "expire")) {
snprintf(buf, len, "%d", peer->expire);
} else if (!strcasecmp(colname, "dynamic")) {
- ast_copy_string(buf, (ast_test_flag(peer, SIP_DYNAMIC) ? "yes" : "no"), len);
+ ast_copy_string(buf, (ast_test_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC) ? "yes" : "no"), len);
} else if (!strcasecmp(colname, "callerid_name")) {
ast_copy_string(buf, peer->cid_name, len);
} else if (!strcasecmp(colname, "callerid_num")) {
@@ -9543,11 +9550,18 @@ static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req)
/*! \brief check_pendings: Check pending actions on SIP call ---*/
static void check_pendings(struct sip_pvt *p)
{
- /* Go ahead and send bye at this point */
if (ast_test_flag(p, SIP_PENDINGBYE)) {
- transmit_request_with_auth(p, SIP_BYE, 0, 1, 1);
- ast_set_flag(p, SIP_NEEDDESTROY);
- ast_clear_flag(p, SIP_NEEDREINVITE);
+ /* if we can't BYE, then this is really a pending CANCEL */
+ if (!ast_test_flag(p, SIP_CAN_BYE)) {
+ transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, 1, 0);
+ /* Actually don't destroy us yet, wait for the 487 on our original
+ INVITE, but do set an autodestruct just in case we never get it. */
+ sip_scheddestroy(p, 32000);
+ } else {
+ transmit_request_with_auth(p, SIP_BYE, 0, 1, 1);
+ ast_set_flag(p, SIP_NEEDDESTROY);
+ ast_clear_flag(p, SIP_NEEDREINVITE);
+ }
} else if (ast_test_flag(p, SIP_NEEDREINVITE)) {
ast_log(LOG_DEBUG, "Sending pending reinvite on '%s'\n", p->callid);
/* Didn't get to reinvite yet, so do it now */
@@ -9577,6 +9591,10 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
switch (resp) {
case 100: /* Trying */
sip_cancel_destroy(p);
+ /* must call check_pendings before setting CAN_BYE, so that
+ if PENDINGBYE is set it will know to send CANCEL instead */
+ check_pendings(p);
+ ast_set_flag(p, SIP_CAN_BYE);
break;
case 180: /* 180 Ringing */
sip_cancel_destroy(p);
@@ -9592,6 +9610,10 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
}
}
+ /* must call check_pendings before setting CAN_BYE, so that
+ if PENDINGBYE is set it will know to send CANCEL instead */
+ check_pendings(p);
+ ast_set_flag(p, SIP_CAN_BYE);
break;
case 183: /* Session progress */
sip_cancel_destroy(p);
@@ -9603,6 +9625,10 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
}
}
+ /* must call check_pendings before setting CAN_BYE, so that
+ if PENDINGBYE is set it will know to send CANCEL instead */
+ check_pendings(p);
+ ast_set_flag(p, SIP_CAN_BYE);
break;
case 200: /* 200 OK on invite - someone's answering our call */
sip_cancel_destroy(p);
@@ -12151,7 +12177,7 @@ static struct sip_peer *temp_peer(const char *name)
peer->rtpholdtimeout = global_rtpholdtimeout;
peer->rtpkeepalive = global_rtpkeepalive;
ast_set_flag(peer, SIP_SELFDESTRUCT);
- ast_set_flag(peer, SIP_DYNAMIC);
+ ast_set_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC);
peer->prefs = prefs;
reg_source_db(peer);
@@ -12282,7 +12308,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
ast_log(LOG_WARNING, "You can't have a dynamic outbound proxy, you big silly head at line %d.\n", v->lineno);
} else {
/* They'll register with us */
- ast_set_flag(peer, SIP_DYNAMIC);
+ ast_set_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC);
if (!found) {
/* Initialize stuff iff we're not found, otherwise
we keep going with what we had */
@@ -12299,7 +12325,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
if (peer->expire > -1)
ast_sched_del(sched, peer->expire);
peer->expire = -1;
- ast_clear_flag(peer, SIP_DYNAMIC);
+ ast_clear_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC);
if (!obproxyfound || !strcasecmp(v->name, "outboundproxy")) {
if (ast_get_ip_or_srv(&peer->addr, v->value, "_sip._udp")) {
ASTOBJ_UNREF(peer, sip_destroy_peer);
@@ -12322,7 +12348,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
} else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
peer->ha = ast_append_ha(v->name, v->value, peer->ha);
} else if (!strcasecmp(v->name, "port")) {
- if (!realtime && ast_test_flag(peer, SIP_DYNAMIC))
+ if (!realtime && ast_test_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC))
peer->defaddr.sin_port = htons(atoi(v->value));
else
peer->addr.sin_port = htons(atoi(v->value));
@@ -12404,7 +12430,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
*/
v=v->next;
}
- if (!ast_test_flag((&global_flags_page2), SIP_PAGE2_IGNOREREGEXPIRE) && ast_test_flag(peer, SIP_DYNAMIC) && realtime) {
+ if (!ast_test_flag((&global_flags_page2), SIP_PAGE2_IGNOREREGEXPIRE) && ast_test_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC) && realtime) {
time_t nowtime;
time(&nowtime);
@@ -12416,7 +12442,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
}
}
ast_copy_flags(peer, &peerflags, mask.flags);
- if (!found && ast_test_flag(peer, SIP_DYNAMIC) && !ast_test_flag(peer, SIP_REALTIME))
+ if (!found && ast_test_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC) && !ast_test_flag(peer, SIP_REALTIME))
reg_source_db(peer);
ASTOBJ_UNMARK(peer);
ast_free_ha(oldha);