mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	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
This commit is contained in:
		
							
								
								
									
										1
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								CHANGES
									
									
									
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
|  -- Management interface improvements | ||||
|  -- Add "hint" support | ||||
|  -- Improve call forwarding using new "Local" channel driver. | ||||
|  -- Add "Local" channel | ||||
|   | ||||
| @@ -193,6 +193,8 @@ static struct sip_pvt { | ||||
| 	char realm[256];				/* Authorization realm */ | ||||
| 	char nonce[256];				/* Authorization nonce */ | ||||
| 	int amaflags;						/* AMA Flags */ | ||||
| 	int pendinginvite;					/* Any pending invite */ | ||||
| 	int pendingbye;						/* Need to send bye after we ack? */ | ||||
| 	struct sip_request initreq;			/* Initial request */ | ||||
| 	 | ||||
| 	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; | ||||
| 	p->packets = pkt; | ||||
| 	__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; | ||||
| } | ||||
|  | ||||
| @@ -457,9 +463,15 @@ static int __sip_ack(struct sip_pvt *p, int seqno, int resp) | ||||
| { | ||||
| 	struct sip_pkt *cur, *prev = NULL; | ||||
| 	int res = -1; | ||||
| 	int resetinvite = 0; | ||||
| 	cur = p->packets; | ||||
| 	while(cur) { | ||||
| 		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 */ | ||||
| 			if (prev) | ||||
| 				prev->next = cur->next; | ||||
| @@ -905,7 +917,7 @@ static int sip_hangup(struct ast_channel *ast) | ||||
| 	if (!p->alreadygone && strlen(p->initreq.data)) { | ||||
| 		if (needcancel) { | ||||
| 			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  | ||||
| 				   INVITE, but do set an autodestruct just in case. */ | ||||
| 				p->needdestroy = 0; | ||||
| @@ -913,8 +925,13 @@ static int sip_hangup(struct ast_channel *ast) | ||||
| 			} else | ||||
| 				transmit_response_reliable(p, "403 Forbidden", &p->initreq); | ||||
| 		} else { | ||||
| 			/* Send a hangup */ | ||||
| 			transmit_request_with_auth(p, "BYE", 1, 1); | ||||
| 			if (!p->pendinginvite) { | ||||
| 				/* Send a hangup */ | ||||
| 				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); | ||||
| @@ -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) | ||||
| { | ||||
| 	/* Add contact header */ | ||||
| 	char contact2[256] ="", *c, contact[256]; | ||||
| 	char contact2[256] ="", *c, *c2, contact[256]; | ||||
| 	char *from; | ||||
| 	if (p->outgoing) | ||||
| 		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); | ||||
| 	if (strlen(contact2)) { | ||||
| 		c = ditch_braces(contact2); | ||||
| 		c2 = strchr(c, ';'); | ||||
| 		if (c2) *c2 = '\0'; | ||||
| 		snprintf(contact, sizeof(contact), "<%s>", c); | ||||
| 		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=")) { | ||||
| 		/* Add the proper tag if we don't have it already.  If they have specified | ||||
| 		   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); | ||||
| 		else if (p->tag) | ||||
| 			snprintf(newto, sizeof(newto), "%s;tag=%08x", ot, p->tag); | ||||
| 		else if (p->tag && !p->outgoing) | ||||
| 			snprintf(newto, sizeof(newto), "%s;tag=as%08x", ot, p->tag); | ||||
| 		else | ||||
| 			strncpy(newto, ot, sizeof(newto) - 1); | ||||
| 		ot = newto; | ||||
| @@ -1907,7 +1926,7 @@ static int respprep(struct sip_request *resp, struct sip_pvt *p, char *msg, stru | ||||
| 	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; | ||||
| 	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)); | ||||
| 	 | ||||
| 	if (inc) | ||||
| 	if (!seqno) { | ||||
| 		p->ocseq++; | ||||
| 		seqno = p->ocseq; | ||||
| 	} | ||||
|  | ||||
| 	if (p->outgoing) | ||||
| 		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 | ||||
| 		c = stripped; | ||||
| 	n = strchr(c, '>'); | ||||
| 	if (n) | ||||
| 		*n = '\0'; | ||||
| 	n = strchr(c, ';'); | ||||
| 	if (n) | ||||
| 		*n = '\0'; | ||||
| 	 | ||||
| 	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); | ||||
| 	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)) | ||||
| 			snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->theirtag); | ||||
| 		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 | ||||
| 			snprintf(newto, sizeof(newto), "%s", ot); | ||||
| 		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) | ||||
| { | ||||
| 	struct sip_request resp; | ||||
| 	struct sip_request req; | ||||
| 	if (p->canreinvite == REINVITE_UPDATE) | ||||
| 		reqprep(&resp, p, "UPDATE", 1); | ||||
| 		reqprep(&req, p, "UPDATE", 0); | ||||
| 	else | ||||
| 		reqprep(&resp, p, "INVITE", 1); | ||||
| 	add_sdp(&resp, p, rtp); | ||||
| 	return send_request(p, &resp, 1, p->ocseq); | ||||
| 		reqprep(&req, p, "INVITE", 0); | ||||
| 	add_sdp(&req, p, rtp); | ||||
| 	/* 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) | ||||
| @@ -2236,9 +2265,9 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, char *cmd, c | ||||
| 	if (!n) | ||||
| 		n = l; | ||||
| 	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 | ||||
| 		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 (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; | ||||
| 		 | ||||
| 	reqprep(&req, p, "NOTIFY", 1); | ||||
| 	reqprep(&req, p, "NOTIFY", 0); | ||||
|  | ||||
| 	if (p->subscribed == 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); | ||||
| 	} | ||||
|  | ||||
| 	snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%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(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=as%08x", r->username, inet_ntoa(r->addr.sin_addr), p->tag); | ||||
| 	 | ||||
| 	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) | ||||
| { | ||||
| 	struct sip_request req; | ||||
| 	reqprep(&req, p, "MESSAGE", 1); | ||||
| 	reqprep(&req, p, "MESSAGE", 0); | ||||
| 	add_text(&req, text); | ||||
| 	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) | ||||
| { | ||||
| 	struct sip_request req; | ||||
| 	reqprep(&req, p, "INFO", 1); | ||||
| 	reqprep(&req, p, "INFO", 0); | ||||
| 	add_digit(&req, digit); | ||||
| 	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; | ||||
| 	reqprep(&resp, p, msg, inc); | ||||
| 	reqprep(&resp, p, msg, seqno); | ||||
| 	add_header(&resp, "Content-Length", "0"); | ||||
| 	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; | ||||
| 	reqprep(&resp, p, msg, inc); | ||||
| 	reqprep(&resp, p, msg, seqno); | ||||
| 	if (*p->realm) | ||||
| 	{ | ||||
| 		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_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) | ||||
| @@ -3705,7 +3734,7 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_ | ||||
| 			if (peer->pokeexpire > -1) | ||||
| 				ast_sched_del(sched, peer->pokeexpire); | ||||
| 			if (!strcasecmp(msg, "INVITE")) | ||||
| 				transmit_request(p, "ACK", 0, 0); | ||||
| 				transmit_request(p, "ACK", seqno, 0); | ||||
| 			p->needdestroy = 1; | ||||
| 			/* Try again eventually */ | ||||
| 			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); | ||||
| 					} | ||||
| 				} | ||||
| 				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")) { | ||||
| 				/* char *exp; */ | ||||
| 				int expires; | ||||
| @@ -3795,30 +3829,13 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_ | ||||
| 			} | ||||
| 			break; | ||||
| 		case 401: /* Not authorized on REGISTER */ | ||||
| 			/* XXX: Do I need to ACK the 401?  | ||||
| 			transmit_request(p, "ACK", 0); | ||||
| 			*/ | ||||
| 			do_register_auth(p, req); | ||||
| 			break; | ||||
| 		case 407: | ||||
| 			/* First we ACK */ | ||||
| 			transmit_request(p, "ACK", 0, 0); | ||||
| 			transmit_request(p, "ACK", seqno, 0); | ||||
| 			/* Then we AUTH */ | ||||
| 			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; | ||||
| 		default: | ||||
| 			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); | ||||
| 					break; | ||||
| 				} | ||||
| 				transmit_request(p, "ACK", 0, 0); | ||||
| 				transmit_request(p, "ACK", seqno, 0); | ||||
| 				p->alreadygone = 1; | ||||
| 				if (!p->owner) | ||||
| 					p->needdestroy = 1; | ||||
| @@ -3872,7 +3889,7 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_ | ||||
| 			switch(resp) { | ||||
| 			case 200: | ||||
| 				if (!strcasecmp(msg, "INVITE") || !strcasecmp(msg, "REGISTER") ) | ||||
| 					transmit_request(p, "ACK", 0, 0); | ||||
| 					transmit_request(p, "ACK", seqno, 0); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| @@ -4187,7 +4204,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc | ||||
| 				} | ||||
| 			} | ||||
| 			/* Always increment on a BYE */ | ||||
| 			transmit_request_with_auth(p, "BYE", 1, 1); | ||||
| 			transmit_request_with_auth(p, "BYE", 0, 1); | ||||
| 			p->alreadygone = 1; | ||||
| 		} | ||||
| 	} else if (!strcasecmp(cmd, "CANCEL")) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user