Fix contact header, don't transmit BYE when INVITE are still outstanding

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@765 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Mark Spencer 23 years ago
parent 1680ccf66c
commit 5c18d407c5

@ -1,3 +1,4 @@
-- Management interface improvements
-- Add "hint" support -- Add "hint" support
-- Improve call forwarding using new "Local" channel driver. -- Improve call forwarding using new "Local" channel driver.
-- Add "Local" channel -- Add "Local" channel

@ -193,6 +193,8 @@ static struct sip_pvt {
char realm[256]; /* Authorization realm */ char realm[256]; /* Authorization realm */
char nonce[256]; /* Authorization nonce */ char nonce[256]; /* Authorization nonce */
int amaflags; /* AMA Flags */ int amaflags; /* AMA Flags */
int pendinginvite; /* Any pending invite */
int pendingbye; /* Need to send bye after we ack? */
struct sip_request initreq; /* Initial request */ struct sip_request initreq; /* Initial request */
int maxtime; /* Max time for first response */ int maxtime; /* Max time for first response */
@ -420,6 +422,10 @@ static int __sip_reliable_xmit(struct sip_pvt *p, int seqno, int resp, char *dat
pkt->next = p->packets; pkt->next = p->packets;
p->packets = pkt; p->packets = pkt;
__sip_xmit(pkt->owner, pkt->data, pkt->packetlen); __sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
if (!strncasecmp(pkt->data, "INVITE", 6)) {
/* Note this is a pending invite */
p->pendinginvite = seqno;
}
return 0; return 0;
} }
@ -457,9 +463,15 @@ static int __sip_ack(struct sip_pvt *p, int seqno, int resp)
{ {
struct sip_pkt *cur, *prev = NULL; struct sip_pkt *cur, *prev = NULL;
int res = -1; int res = -1;
int resetinvite = 0;
cur = p->packets; cur = p->packets;
while(cur) { while(cur) {
if ((cur->seqno == seqno) && (cur->resp == resp)) { if ((cur->seqno == seqno) && (cur->resp == resp)) {
if (!resp && (seqno == p->pendinginvite)) {
ast_log(LOG_DEBUG, "Acked pending invite %d\n", p->pendinginvite);
p->pendinginvite = 0;
resetinvite = 1;
}
/* this is our baby */ /* this is our baby */
if (prev) if (prev)
prev->next = cur->next; prev->next = cur->next;
@ -905,7 +917,7 @@ static int sip_hangup(struct ast_channel *ast)
if (!p->alreadygone && strlen(p->initreq.data)) { if (!p->alreadygone && strlen(p->initreq.data)) {
if (needcancel) { if (needcancel) {
if (p->outgoing) { if (p->outgoing) {
transmit_request_with_auth(p, "CANCEL", 0, 1); transmit_request_with_auth(p, "CANCEL", p->ocseq, 1);
/* Actually don't destroy us yet, wait for the 487 on our original /* Actually don't destroy us yet, wait for the 487 on our original
INVITE, but do set an autodestruct just in case. */ INVITE, but do set an autodestruct just in case. */
p->needdestroy = 0; p->needdestroy = 0;
@ -913,8 +925,13 @@ static int sip_hangup(struct ast_channel *ast)
} else } else
transmit_response_reliable(p, "403 Forbidden", &p->initreq); transmit_response_reliable(p, "403 Forbidden", &p->initreq);
} else { } else {
if (!p->pendinginvite) {
/* Send a hangup */ /* Send a hangup */
transmit_request_with_auth(p, "BYE", 1, 1); transmit_request_with_auth(p, "BYE", 0, 1);
} else {
/* Note we will need a BYE when this all settles out */
p->pendingbye = 1;
}
} }
} }
ast_pthread_mutex_unlock(&p->lock); ast_pthread_mutex_unlock(&p->lock);
@ -1838,7 +1855,7 @@ static int init_req(struct sip_request *req, char *resp, char *recip)
static void append_contact(struct sip_request *req, struct sip_pvt *p) static void append_contact(struct sip_request *req, struct sip_pvt *p)
{ {
/* Add contact header */ /* Add contact header */
char contact2[256] ="", *c, contact[256]; char contact2[256] ="", *c, *c2, contact[256];
char *from; char *from;
if (p->outgoing) if (p->outgoing)
from = get_header(req, "From"); from = get_header(req, "From");
@ -1847,6 +1864,8 @@ static void append_contact(struct sip_request *req, struct sip_pvt *p)
strncpy(contact2, from, sizeof(contact2)-1); strncpy(contact2, from, sizeof(contact2)-1);
if (strlen(contact2)) { if (strlen(contact2)) {
c = ditch_braces(contact2); c = ditch_braces(contact2);
c2 = strchr(c, ';');
if (c2) *c2 = '\0';
snprintf(contact, sizeof(contact), "<%s>", c); snprintf(contact, sizeof(contact), "<%s>", c);
add_header(req, "Contact", contact); add_header(req, "Contact", contact);
} }
@ -1864,10 +1883,10 @@ static int respprep(struct sip_request *resp, struct sip_pvt *p, char *msg, stru
if (!strstr(ot, "tag=")) { if (!strstr(ot, "tag=")) {
/* Add the proper tag if we don't have it already. If they have specified /* Add the proper tag if we don't have it already. If they have specified
their tag, use it. Otherwise, use our own tag */ their tag, use it. Otherwise, use our own tag */
if (strlen(p->theirtag)) if (strlen(p->theirtag) && p->outgoing)
snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->theirtag); snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->theirtag);
else if (p->tag) else if (p->tag && !p->outgoing)
snprintf(newto, sizeof(newto), "%s;tag=%08x", ot, p->tag); snprintf(newto, sizeof(newto), "%s;tag=as%08x", ot, p->tag);
else else
strncpy(newto, ot, sizeof(newto) - 1); strncpy(newto, ot, sizeof(newto) - 1);
ot = newto; ot = newto;
@ -1907,7 +1926,7 @@ static int respprep(struct sip_request *resp, struct sip_pvt *p, char *msg, stru
return 0; return 0;
} }
static int reqprep(struct sip_request *req, struct sip_pvt *p, char *msg, int inc) static int reqprep(struct sip_request *req, struct sip_pvt *p, char *msg, int seqno)
{ {
struct sip_request *orig = &p->initreq; struct sip_request *orig = &p->initreq;
char stripped[80] =""; char stripped[80] ="";
@ -1918,8 +1937,10 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, char *msg, int in
memset(req, 0, sizeof(struct sip_request)); memset(req, 0, sizeof(struct sip_request));
if (inc) if (!seqno) {
p->ocseq++; p->ocseq++;
seqno = p->ocseq;
}
if (p->outgoing) if (p->outgoing)
strncpy(stripped, get_header(orig, "To"), sizeof(stripped) - 1); strncpy(stripped, get_header(orig, "To"), sizeof(stripped) - 1);
@ -1932,12 +1953,15 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, char *msg, int in
else else
c = stripped; c = stripped;
n = strchr(c, '>'); n = strchr(c, '>');
if (n)
*n = '\0';
n = strchr(c, ';');
if (n) if (n)
*n = '\0'; *n = '\0';
init_req(req, msg, c); init_req(req, msg, c);
snprintf(tmp, sizeof(tmp), "%d %s", p->ocseq, msg); snprintf(tmp, sizeof(tmp), "%d %s", seqno, msg);
add_header(req, "Via", p->via); add_header(req, "Via", p->via);
if (p->route) { if (p->route) {
@ -1956,7 +1980,7 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, char *msg, int in
if (p->outgoing && strlen(p->theirtag)) if (p->outgoing && strlen(p->theirtag))
snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->theirtag); snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->theirtag);
else if (!p->outgoing) else if (!p->outgoing)
snprintf(newto, sizeof(newto), "%s;tag=%08x", ot, p->tag); snprintf(newto, sizeof(newto), "%s;tag=as%08x", ot, p->tag);
else else
snprintf(newto, sizeof(newto), "%s", ot); snprintf(newto, sizeof(newto), "%s", ot);
ot = newto; ot = newto;
@ -2208,13 +2232,18 @@ static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_r
static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp) static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp)
{ {
struct sip_request resp; struct sip_request req;
if (p->canreinvite == REINVITE_UPDATE) if (p->canreinvite == REINVITE_UPDATE)
reqprep(&resp, p, "UPDATE", 1); reqprep(&req, p, "UPDATE", 0);
else else
reqprep(&resp, p, "INVITE", 1); reqprep(&req, p, "INVITE", 0);
add_sdp(&resp, p, rtp); add_sdp(&req, p, rtp);
return send_request(p, &resp, 1, p->ocseq); /* Use this as the basis */
copy_request(&p->initreq, &req);
parse(&p->initreq);
p->lastinvite = p->ocseq;
p->outgoing = 1;
return send_request(p, &req, 1, p->ocseq);
} }
static void initreqprep(struct sip_request *req, struct sip_pvt *p, char *cmd, char *vxml_url) static void initreqprep(struct sip_request *req, struct sip_pvt *p, char *cmd, char *vxml_url)
@ -2236,9 +2265,9 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, char *cmd, c
if (!n) if (!n)
n = l; n = l;
if (ourport != 5060) if (ourport != 5060)
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%08x", n, l, strlen(p->fromdomain) ? p->fromdomain : inet_ntoa(p->ourip), ourport, p->tag); snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=as%08x", n, l, strlen(p->fromdomain) ? p->fromdomain : inet_ntoa(p->ourip), ourport, p->tag);
else else
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%08x", n, l, strlen(p->fromdomain) ? p->fromdomain : inet_ntoa(p->ourip), p->tag); snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=as%08x", n, l, strlen(p->fromdomain) ? p->fromdomain : inet_ntoa(p->ourip), p->tag);
if (strlen(p->username)) { if (strlen(p->username)) {
if (ntohs(p->sa.sin_port) != DEFAULT_SIP_PORT) { if (ntohs(p->sa.sin_port) != DEFAULT_SIP_PORT) {
@ -2325,7 +2354,7 @@ static int transmit_state_notify(struct sip_pvt *p, int state, int full)
} }
mfrom = c; mfrom = c;
reqprep(&req, p, "NOTIFY", 1); reqprep(&req, p, "NOTIFY", 0);
if (p->subscribed == 1) { if (p->subscribed == 1) {
strncpy(to, get_header(&p->initreq, "To"), sizeof(to)-1); strncpy(to, get_header(&p->initreq, "To"), sizeof(to)-1);
@ -2487,8 +2516,8 @@ static int transmit_register(struct sip_registry *r, char *cmd, char *auth)
ast_log(LOG_NOTICE, "Scheduled a timeout # %d\n", r->timeout); ast_log(LOG_NOTICE, "Scheduled a timeout # %d\n", r->timeout);
} }
snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%08x", r->username, inet_ntoa(r->addr.sin_addr), p->tag); snprintf(from, sizeof(from), "<sip:%s@%s>;tag=as%08x", r->username, inet_ntoa(r->addr.sin_addr), p->tag);
snprintf(to, sizeof(to), "<sip:%s@%s>;tag=%08x", r->username, inet_ntoa(r->addr.sin_addr), p->tag); snprintf(to, sizeof(to), "<sip:%s@%s>;tag=as%08x", r->username, inet_ntoa(r->addr.sin_addr), p->tag);
snprintf(addr, sizeof(addr), "sip:%s", inet_ntoa(r->addr.sin_addr)); snprintf(addr, sizeof(addr), "sip:%s", inet_ntoa(r->addr.sin_addr));
@ -2525,7 +2554,7 @@ static int transmit_register(struct sip_registry *r, char *cmd, char *auth)
static int transmit_message_with_text(struct sip_pvt *p, char *text) static int transmit_message_with_text(struct sip_pvt *p, char *text)
{ {
struct sip_request req; struct sip_request req;
reqprep(&req, p, "MESSAGE", 1); reqprep(&req, p, "MESSAGE", 0);
add_text(&req, text); add_text(&req, text);
return send_request(p, &req, 1, p->ocseq); return send_request(p, &req, 1, p->ocseq);
} }
@ -2533,24 +2562,24 @@ static int transmit_message_with_text(struct sip_pvt *p, char *text)
static int transmit_info_with_digit(struct sip_pvt *p, char digit) static int transmit_info_with_digit(struct sip_pvt *p, char digit)
{ {
struct sip_request req; struct sip_request req;
reqprep(&req, p, "INFO", 1); reqprep(&req, p, "INFO", 0);
add_digit(&req, digit); add_digit(&req, digit);
return send_request(p, &req, 1, p->ocseq); return send_request(p, &req, 1, p->ocseq);
} }
static int transmit_request(struct sip_pvt *p, char *msg, int inc, int reliable) static int transmit_request(struct sip_pvt *p, char *msg, int seqno, int reliable)
{ {
struct sip_request resp; struct sip_request resp;
reqprep(&resp, p, msg, inc); reqprep(&resp, p, msg, seqno);
add_header(&resp, "Content-Length", "0"); add_header(&resp, "Content-Length", "0");
add_blank_header(&resp); add_blank_header(&resp);
return send_request(p, &resp, reliable, p->ocseq); return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);
} }
static int transmit_request_with_auth(struct sip_pvt *p, char *msg, int inc, int reliable) static int transmit_request_with_auth(struct sip_pvt *p, char *msg, int seqno, int reliable)
{ {
struct sip_request resp; struct sip_request resp;
reqprep(&resp, p, msg, inc); reqprep(&resp, p, msg, seqno);
if (*p->realm) if (*p->realm)
{ {
char digest[256]; char digest[256];
@ -2561,7 +2590,7 @@ static int transmit_request_with_auth(struct sip_pvt *p, char *msg, int inc, int
add_header(&resp, "Content-Length", "0"); add_header(&resp, "Content-Length", "0");
add_blank_header(&resp); add_blank_header(&resp);
return send_request(p, &resp, reliable, p->ocseq); return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);
} }
static int expire_register(void *data) static int expire_register(void *data)
@ -3705,7 +3734,7 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
if (peer->pokeexpire > -1) if (peer->pokeexpire > -1)
ast_sched_del(sched, peer->pokeexpire); ast_sched_del(sched, peer->pokeexpire);
if (!strcasecmp(msg, "INVITE")) if (!strcasecmp(msg, "INVITE"))
transmit_request(p, "ACK", 0, 0); transmit_request(p, "ACK", seqno, 0);
p->needdestroy = 1; p->needdestroy = 1;
/* Try again eventually */ /* Try again eventually */
if ((peer->lastms < 0) || (peer->lastms > peer->maxms)) if ((peer->lastms < 0) || (peer->lastms > peer->maxms))
@ -3772,7 +3801,12 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
ast_queue_control(p->owner, AST_CONTROL_ANSWER, 0); ast_queue_control(p->owner, AST_CONTROL_ANSWER, 0);
} }
} }
transmit_request(p, "ACK", 0, 0); transmit_request(p, "ACK", seqno, 0);
/* Go ahead and send bye at this point */
if (p->pendingbye) {
transmit_request(p, "BYE", 0, 1);
p->needdestroy = 1;
}
} else if (!strcasecmp(msg, "REGISTER")) { } else if (!strcasecmp(msg, "REGISTER")) {
/* char *exp; */ /* char *exp; */
int expires; int expires;
@ -3795,30 +3829,13 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
} }
break; break;
case 401: /* Not authorized on REGISTER */ case 401: /* Not authorized on REGISTER */
/* XXX: Do I need to ACK the 401?
transmit_request(p, "ACK", 0);
*/
do_register_auth(p, req); do_register_auth(p, req);
break; break;
case 407: case 407:
/* First we ACK */ /* First we ACK */
transmit_request(p, "ACK", 0, 0); transmit_request(p, "ACK", seqno, 0);
/* Then we AUTH */ /* Then we AUTH */
do_proxy_auth(p, req); do_proxy_auth(p, req);
/* This is just a hack to kill the channel while testing */
/*
p->alreadygone = 1;
if (p->rtp) {
rtp = p->rtp;
p->rtp = NULL;
ast_rtp_destroy(rtp);
}
if (p->owner)
ast_queue_hangup(p->owner,0);
transmit_request(p,"ACK",0);
sip_destroy(p);
p = NULL;
*/
break; break;
default: default:
if ((resp >= 300) && (resp < 700)) { if ((resp >= 300) && (resp < 700)) {
@ -3855,7 +3872,7 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
ast_queue_hangup(p->owner, 0); ast_queue_hangup(p->owner, 0);
break; break;
} }
transmit_request(p, "ACK", 0, 0); transmit_request(p, "ACK", seqno, 0);
p->alreadygone = 1; p->alreadygone = 1;
if (!p->owner) if (!p->owner)
p->needdestroy = 1; p->needdestroy = 1;
@ -3872,7 +3889,7 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
switch(resp) { switch(resp) {
case 200: case 200:
if (!strcasecmp(msg, "INVITE") || !strcasecmp(msg, "REGISTER") ) if (!strcasecmp(msg, "INVITE") || !strcasecmp(msg, "REGISTER") )
transmit_request(p, "ACK", 0, 0); transmit_request(p, "ACK", seqno, 0);
break; break;
} }
} }
@ -4187,7 +4204,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
} }
} }
/* Always increment on a BYE */ /* Always increment on a BYE */
transmit_request_with_auth(p, "BYE", 1, 1); transmit_request_with_auth(p, "BYE", 0, 1);
p->alreadygone = 1; p->alreadygone = 1;
} }
} else if (!strcasecmp(cmd, "CANCEL")) { } else if (!strcasecmp(cmd, "CANCEL")) {

Loading…
Cancel
Save