46d45
< #include <asterisk/astobj.h>
63d61
< #include <regex.h>
101a100,103
> /* --- Choices for DTMF support in SIP channel */
> #define SIP_DTMF_RFC2833	(1 << 0)	/* RTP DTMF */
> #define SIP_DTMF_INBAND		(1 << 1)	/* Inband audio, only for ULAW/ALAW */
> #define SIP_DTMF_INFO		(1 << 2)	/* SIP Info messages */
111c113
< 
---
> 						/* SIP Debug		*/
119d120
< static char *notify_config = "sip_notify.conf";
141,142d141
< static struct ast_flags global_flags = {0};		/* global SIP_ flags */
< 
155c154
< static int global_rtpkeepalive = 0;
---
> static int global_trustrpid = 0;	/* Trust RPID headers? Default off. */
157c156
< static int global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT;
---
> static int global_progressinband = 0;
159,165c158
< /* Object counters */
< static int suserobjs = 0;
< static int ruserobjs = 0;
< static int speerobjs = 0;
< static int rpeerobjs = 0;
< static int apeerobjs = 0;
< static int regobjs = 0;
---
> static int global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT;
167c160,162
< static int global_allowguest = 0;    /* allow unathuncated peers to connect? */
---
> #ifdef OSP_SUPPORT
> static int global_ospauth = 0;		/* OSP = Open Settlement Protocol */
> #endif
208a204
> static int global_dtmfmode = SIP_DTMF_RFC2833;		/* DTMF mode default */
209a206,207
> static int global_promiscredir;				/* Support of 302 REDIR - Default off */
> static int global_usereqphone;				/* User=phone support, default 0 */
259,305d256
< #define SIP_ALREADYGONE		(1 << 0)	/* Whether or not we've already been destroyed by our peer */
< #define SIP_NEEDDESTROY		(1 << 1)	/* if we need to be destroyed */
< #define SIP_NOVIDEO		(1 << 2)	/* Didn't get video in invite, don't offer */
< #define SIP_RINGING		(1 << 3)	/* Have sent 180 ringing */
< #define SIP_PROGRESS_SENT		(1 << 4)	/* Have sent 183 message progress */
< #define SIP_NEEDREINVITE	(1 << 5)	/* Do we need to send another reinvite? */
< #define SIP_PENDINGBYE		(1 << 6)	/* Need to send bye after we ack? */
< #define SIP_GOTREFER		(1 << 7)	/* Got a refer? */
< #define SIP_PROMISCREDIR	(1 << 8)	/* Promiscuous redirection */
< #define SIP_TRUSTRPID		(1 << 9)	/* Trust RPID headers? */
< #define SIP_USEREQPHONE		(1 << 10)	/* Add user=phone to numeric URI. Default off */
< #define SIP_REALTIME		(1 << 11)	/* Flag for realtime users */
< #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)	
< #define SIP_DYNAMIC		(1 << 15)	/* Is this a dynamic peer? */
< /* --- 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 */
< #define SIP_DTMF_INBAND		(1 << 16)	/* Inband audio, only for ULAW/ALAW */
< #define SIP_DTMF_INFO		(2 << 16)	/* SIP Info messages */
< /* NAT settings */
< #define SIP_NAT			(3 << 18)	/* four settings, uses two bits */
< #define SIP_NAT_NEVER		(0 << 18)	/* No nat support */
< #define SIP_NAT_RFC3581		(1 << 18)
< #define SIP_NAT_ROUTE		(2 << 18)
< #define SIP_NAT_ALWAYS		(3 << 18)
< /* re-INVITE related settings */
< #define SIP_REINVITE		(3 << 20)	/* two bits used */
< #define SIP_CAN_REINVITE	(1 << 20)	/* allow peers to be reinvited to send media directly to us */
< #define SIP_REINVITE_UPDATE	(2 << 20)	/* use UPDATE (RFC3311) when reinviting this peer */
< /* "insecure" settings */
< #define SIP_INSECURE		(3 << 22)	/* three settings, uses two bits */
< #define SIP_SECURE		(0 << 22)
< #define SIP_INSECURE_NORMAL	(1 << 22)
< #define SIP_INSECURE_VERY	(2 << 22)
< /* Sending PROGRESS in-band settings */
< #define SIP_PROG_INBAND		(3 << 24)	/* three settings, uses two bits */
< #define SIP_PROG_INBAND_NEVER	(0 << 24)
< #define SIP_PROG_INBAND_NO	(1 << 24)
< #define SIP_PROG_INBAND_YES	(2 << 24)
< /* Open Settlement Protocol authentication */
< #define SIP_OSPAUTH		(3 << 26)	/* three settings, uses two bits */
< #define SIP_OSPAUTH_NO		(0 << 26)
< #define SIP_OSPAUTH_YES		(1 << 26)
< #define SIP_OSPAUTH_EXCLUSIVE	(2 << 26)
< 
317c268,269
< 	unsigned int flags;			/* SIP_ flags */	
---
> 	int alreadygone;			/* Whether or not we've already been destroyed by or peer */
> 	int needdestroy;			/* if we need to be destroyed */
318a271
> 	int novideo;				/* Didn't get video in invite, don't offer */
323a277
> 	int outgoing;				/* Outgoing or incoming call? */
324a279
> 	int insecure;				/* Don't check source port/ip */
326a282,285
> 	int canreinvite;			/* Do we support reinvite */
> 	int ringing;				/* Have sent 180 ringing */
> 	int progress;				/* Have sent 183 message progress */
> 	int useclientcode;			/* Trust X-ClientCode info message */
327a287
> 	int nat;				/* Whether to try to support NAT */
358d317
< 	char okcontacturi[256];			/* URI from the 200 OK on INVITE */
374a334,336
> 	int needreinvite;			/* Do we need to send another reinvite? */
> 	int pendingbye;				/* Need to send bye after we ack? */
> 	int gotrefer;				/* Got a refer? */
375a338
> 	int ospauth;				/* Allow OSP Authentication */
385d347
< 	time_t lastrtptx;			/* Last RTP sent */
388d349
< 	int rtpkeepalive;			/* Send RTP packets for keepalive */
392a354,355
> 	int promiscredir;			/* Promiscuous redirection */
> 	int usereqphone;			/* Add user=phone to numeric URI. Default off */
393a357,360
> 	int trustrpid;				/* Trust RPID headers? */
> 	int progressinband;
> 	
> 	int dtmfmode;				/* DTMF to use for this call */
414c381
< 	unsigned int flags;				/* non-zero if this is a response packet (e.g. 200 OK) */
---
> 	int flags;					/* non-zero if this is a response packet (e.g. 200 OK) */
424c391
< 	ASTOBJ_COMPONENTS(struct sip_user);
---
> 	char name[80];			/* The name in sip.conf */
437c404
< 	unsigned int flags;		/* SIP_ flags */	
---
> 	int nat;			/* NAT setting */
439a407,408
> 	int insecure;			/* Insecure means don't check password */
> 	int canreinvite;		/* Do we support re-invites ? */
440a410,413
> #ifdef OSP_SUPPORT
> 	int ospauth;			/* Allow OSP Authentication */
> #endif
> 	int dtmfmode;			/* DTMF setting */
444a418,421
> 	int promiscredir;		/* Support of 302 redirect */
> 	int useclientcode;		/* SNOM clientcode support */
> 	int trustrpid;			/* Trust remote party ID from this UA */
> 	int progressinband;
445a423
> 	int temponly;			/* Flag for temporary users (realtime) */
446a425
> 	struct sip_user *next;
451c430
< 	ASTOBJ_COMPONENTS(struct sip_peer);
---
> 	char name[80];			/* Peer name in sip.conf */
470c449
< 	unsigned int flags;		/* SIP_ flags */	
---
> 	int dynamic;			/* Dynamic? Yes or no. Dynamic hosts register with us  */
476c455,460
< 	int rtpkeepalive;			/* Send RTP packets for keepalive */
---
> 	int insecure;			/* Do we want to authenticate this peer? */
> #ifdef OSP_SUPPORT
> 	int ospauth;			/* Allow OSP Authentication */
> #endif	
> 	int nat;			/* NAT support needed? */
> 	int canreinvite;		/* Does the peer support re-invites? */
478a463,468
> 	int promiscredir;		/* Support of 302 redirect? */
> 	int dtmfmode;			/* DTMF mode */
> 	int trustrpid;			/* Trust Remote Party ID headers? */
> 	int useclientcode;		/* SNOM clientcode support */
> 	int progressinband;
> 	int usereqphone;		/* Add user=phone to URI. Default off */
490a481,482
> 	int delme;
> 	int selfdestruct;
491a484,485
> 	int temponly;
> 	struct sip_peer *next;
505a500,504
> /* NAT settings */
> #define SIP_NAT_NEVER		0		/* No nat support */
> #define SIP_NAT_RFC3581		(1 << 0)
> #define SIP_NAT_ROUTE		(1 << 2)
> #define SIP_NAT_ALWAYS		(SIP_NAT_ROUTE | SIP_NAT_RFC3581)
509d507
< 	ASTOBJ_COMPONENTS_FULL(struct sip_registry,1,1);
535a534
> 	struct sip_registry *next;
540c539,540
< 	ASTOBJ_CONTAINER_COMPONENTS(struct sip_user);
---
> 	struct sip_user *users;
> 	ast_mutex_t lock;
545c545,546
< 	ASTOBJ_CONTAINER_COMPONENTS(struct sip_peer);
---
> 	struct sip_peer *peers;
> 	ast_mutex_t lock;
550c551,552
< 	ASTOBJ_CONTAINER_COMPONENTS(struct sip_registry);
---
> 	struct sip_registry *registrations;
> 	ast_mutex_t lock;
554a557,559
> #define REINVITE_INVITE		1
> #define REINVITE_UPDATE		2
> 
557a563,564
> static int global_nat = SIP_NAT_RFC3581;
> static int global_canreinvite = REINVITE_INVITE;
562,564d568
< static char externhost[256] = "";
< static time_t externexpire = 0;
< static int externrefresh = 10;
567,569d570
< /* The list of manual NOTIFY types we know how to send */
< struct ast_config *notify_types;
< 
608c609
< 	return sip_debug_test_addr(((ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE) ? &p->recv : &p->sa));
---
> 	return sip_debug_test_addr(((p->nat & SIP_NAT_ROUTE) ? &p->recv : &p->sa));
617c618
< 	if (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)
---
> 	if (p->nat & SIP_NAT_ROUTE)
629,640d629
< /*--- build_via: Build a Via header for a request ---*/
< static void build_via(struct sip_pvt *p, char *buf, int len)
< {
< 	char iabuf[INET_ADDRSTRLEN];
< 
< 	/* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
< 	if (ast_test_flag(p, SIP_NAT) != SIP_NAT_NEVER)
< 		snprintf(buf, len, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
< 	else /* Work around buggy UNIDEN UIP200 firmware */
< 		snprintf(buf, len, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
< }
< 
655,664d643
< 		if (externexpire && (time(NULL) >= externexpire)) {
< 			struct ast_hostent ahp;
< 			struct hostent *hp;
< 			time(&externexpire);
< 			externexpire += externrefresh;
< 			if ((hp = ast_gethostbyname(externhost, &ahp))) {
< 				memcpy(&externip.sin_addr, hp->h_addr, sizeof(externip.sin_addr));
< 			} else
< 				ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost);
< 		}
718c697
< 			if (ast_test_flag(pkt->owner, SIP_NAT) & SIP_NAT_ROUTE)
---
> 			if (pkt->owner->nat & SIP_NAT_ROUTE)
727,728c706,707
< 		ast_log(LOG_WARNING, "Maximum retries exceeded on call %s for seqno %d (%s %s)\n", pkt->owner->callid, pkt->seqno, (ast_test_flag(pkt, FLAG_FATAL)) ? "Critical" : "Non-critical", (ast_test_flag(pkt, FLAG_RESPONSE)) ? "Response" : "Request");
< 		append_history(pkt->owner, "MaxRetries", (ast_test_flag(pkt, FLAG_FATAL)) ? "(Critical)" : "(Non-critical)");
---
> 		ast_log(LOG_WARNING, "Maximum retries exceeded on call %s for seqno %d (%s %s)\n", pkt->owner->callid, pkt->seqno, (pkt->flags & FLAG_FATAL) ? "Critical" : "Non-critical", (pkt->flags & FLAG_RESPONSE) ? "Response" : "Request");
> 		append_history(pkt->owner, "MaxRetries", pkt->flags & FLAG_FATAL ? "(Critical)" : "(Non-critical)");
730c709
< 		if (ast_test_flag(pkt, FLAG_FATAL)) {
---
> 		if (pkt->flags & FLAG_FATAL) {
737c716
< 				ast_set_flag(pkt->owner, SIP_ALREADYGONE);
---
> 				pkt->owner->alreadygone=1;
742c721
< 				ast_set_flag(pkt->owner, SIP_NEEDDESTROY);	
---
> 				pkt->owner->needdestroy = 1;
786c765
< 		ast_set_flag(pkt, FLAG_FATAL);
---
> 		pkt->flags |= FLAG_FATAL;
851,852c830,831
< 		if ((cur->seqno == seqno) && ((ast_test_flag(cur, FLAG_RESPONSE)) == resp) &&
< 			((ast_test_flag(cur, FLAG_RESPONSE)) || 
---
> 		if ((cur->seqno == seqno) && ((cur->flags & FLAG_RESPONSE) == resp) &&
> 			((cur->flags & FLAG_RESPONSE) || 
881c860
< 		__sip_ack(p, p->packets->seqno, (ast_test_flag(p->packets, FLAG_RESPONSE)), p->packets->data);
---
> 		__sip_ack(p, p->packets->seqno, (p->packets->flags & FLAG_RESPONSE), p->packets->data);
893,894c872,873
< 		if ((cur->seqno == seqno) && ((ast_test_flag(cur, FLAG_RESPONSE)) == resp) &&
< 			((ast_test_flag(cur, FLAG_RESPONSE)) || 
---
> 		if ((cur->seqno == seqno) && ((cur->flags & FLAG_RESPONSE) == resp) &&
> 			((cur->flags & FLAG_RESPONSE) || 
928c907
< 		if (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)
---
> 		if (p->nat & SIP_NAT_ROUTE)
961c940
< 		if (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)
---
> 		if (p->nat & SIP_NAT_ROUTE)
1087c1066
< static void sip_destroy_peer(struct sip_peer *peer)
---
> static void destroy_peer(struct sip_peer *peer)
1098,1103d1076
< 	if (ast_test_flag(peer, SIP_SELFDESTRUCT))
< 		apeerobjs--;
< 	else if (ast_test_flag(peer, SIP_REALTIME))
< 		rpeerobjs--;
< 	else
< 		speerobjs--;
1110c1083
< 	if (ast_test_flag(p, SIP_REALTIME))
---
> 	if (p->temponly)
1114c1087
< static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int realtime);
---
> static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int temponly);
1117a1091,1092
> 	struct ast_variable *var, *tmp=NULL;
> 	char iabuf[80];
1119,1121c1094,1098
< 	struct ast_variable *var;
< 	struct ast_variable *tmp;
< 
---
> 	time_t nowtime, regseconds;
> 	int dynamic=0;
> 	
> 	if (sin)
> 		ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr);
1124,1127c1101
< 	else if (sin) {
< 		char iabuf[80];
< 
< 		ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr);
---
> 	else
1129,1142c1103,1139
< 	} else
< 		return NULL;
< 
< 	if (!var)
< 		return NULL;
< 
< 	tmp = var;
< 	while(tmp) {
< 		if (strcasecmp(tmp->name, "type"))
< 			continue;
< 
< 		if (!strcasecmp(tmp->value, "user")) {
< 			ast_destroy_realtime(var);
< 			return NULL;
---
> 	if (var) {
> 		/* Make sure it's not a user only... */
> 		peer = build_peer(peername, var, 1);
> 		if (peer) {
> 			/* Add some finishing touches, addresses, etc */
> 			peer->temponly = 1;
> 			tmp = var;
> 			while(tmp) {
> 				if (!strcasecmp(tmp->name, "type")) {
> 					if (strcasecmp(tmp->value, "friend") &&
> 						strcasecmp(tmp->value, "peer")) {
> 						/* Whoops, we weren't supposed to exist! */
> 						destroy_peer(peer);
> 						peer = NULL;
> 						break;
> 					} 
> 				} else if (!strcasecmp(tmp->name, "regseconds")) {
> 					if (sscanf(tmp->value, "%li", &regseconds) != 1)
> 						regseconds = 0;
> 				} else if (!strcasecmp(tmp->name, "ipaddr")) {
> 					inet_aton(tmp->value, &(peer->addr.sin_addr));
> 				} else if (!strcasecmp(tmp->name, "port")) {
> 					peer->addr.sin_port = htons(atoi(tmp->value));
> 				} else if (!strcasecmp(tmp->name, "host")) {
> 					if (!strcasecmp(tmp->value, "dynamic"))
> 						dynamic = 1;
> 				}
> 				tmp = tmp->next;
> 			}
> 			if (peer && dynamic) {
> 				time(&nowtime);
> 				if ((nowtime - regseconds) > 0) {
> 					memset(&peer->addr, 0, sizeof(peer->addr));
> 					if (option_debug)
> 						ast_log(LOG_DEBUG, "Bah, we're expired (%ld/%ld/%ld)!\n", nowtime - regseconds, regseconds, nowtime);
> 				}
> 			}
1144,1145c1141
< 
< 		tmp = tmp->next;
---
> 		ast_destroy_realtime(var);
1147,1151d1142
< 
< 	peer = build_peer(peername, var, 1);
< 	if (peer)
< 		ast_set_flag(peer, SIP_REALTIME);
< 	ast_destroy_realtime(var);
1155,1163d1145
< static int sip_addrcmp(char *name, struct sockaddr_in *sin)
< {
< 	/* We know name is the first field, so we can cast */
< 	struct sip_peer *p = (struct sip_peer *)name;
< 	return 	!(!inaddrcmp(&p->addr, sin) || 
< 					(ast_test_flag(p, SIP_INSECURE) &&
< 					(p->addr.sin_addr.s_addr == sin->sin_addr.s_addr)));
< }
< 
1169,1172c1151,1171
< 	if (peer)
< 		p = ASTOBJ_CONTAINER_FIND(&peerl,peer);
< 	else
< 		p = ASTOBJ_CONTAINER_FIND_FULL(&peerl,sin,name,sip_addr_hashfunc,1,sip_addrcmp);
---
> 	p = peerl.peers;
> 	if (peer) {
> 		/* Find by peer name */
> 		while(p) {
> 			if (!strcasecmp(p->name, peer)) {
> 				break;
> 			}
> 			p = p->next;
> 		}	
> 	}
> 	else {
> 		/* Find by sin */
> 		while(p) {
> 			if (!inaddrcmp(&p->addr, sin) || 
> 					(p->insecure &&
> 					(p->addr.sin_addr.s_addr == sin->sin_addr.s_addr))) {
> 				break;
> 			}
> 			p = p->next;
> 		}
> 	}
1181c1180
< static void sip_destroy_user(struct sip_user *user)
---
> static void destroy_user(struct sip_user *user)
1188,1191d1186
< 	if (ast_test_flag(user, SIP_REALTIME))
< 		ruserobjs--;
< 	else
< 		suserobjs--;
1195c1190
< static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime);
---
> static struct sip_user *build_user(const char *name, struct ast_variable *v);
1200,1201c1195
< 	struct sip_user *user = NULL;
< 
---
> 	struct sip_user *user=NULL;
1203,1214c1197,1215
< 
< 	if (!var)
< 		return NULL;
< 
< 	tmp = var;
< 	while (tmp) {
< 		if (strcasecmp(tmp->name, "type"))
< 			continue;
< 
< 		if (!strcasecmp(tmp->value, "peer")) {
< 			ast_destroy_realtime(var);
< 			return NULL;
---
> 	if (var) {
> 		/* Make sure it's not a user only... */
> 		user = build_user(username, var);
> 		if (user) {
> 			/* Add some finishing touches, addresses, etc */
> 			user->temponly = 1;
> 			tmp = var;
> 			while(tmp) {
> 				if (!strcasecmp(tmp->name, "type")) {
> 					if (strcasecmp(tmp->value, "friend") &&
> 						strcasecmp(tmp->value, "user")) {
> 						/* Whoops, we weren't supposed to exist! */
> 						destroy_user(user);
> 						user = NULL;
> 						break;
> 					} 
> 				}
> 				tmp = tmp->next;
> 			}
1216c1217
< 		tmp = tmp->next;
---
> 		ast_destroy_realtime(var);
1218,1227d1218
< 
< 	user = build_user(username, var, 1);
< 	if (user) {
< 		/* Move counter from s to r... */
< 		suserobjs--;
< 		ruserobjs++;
< 		/* Add some finishing touches, addresses, etc */
< 		ast_set_flag(user, SIP_REALTIME);	
< 	}
< 	ast_destroy_realtime(var);
1232c1223
< static struct sip_user *find_user(const char *name)
---
> static struct sip_user *find_user(char *name)
1235c1226,1233
< 	u = ASTOBJ_CONTAINER_FIND(&userl,name);
---
> 
> 	u = userl.users;
> 	while(u) {
> 		if (!strcasecmp(u->name, name)) {
> 			break;
> 		}
> 		u = u->next;
> 	}
1263a1262
> 	ast_mutex_lock(&peerl.lock);
1267,1312c1266,1323
< 		found++;
< 		ast_copy_flags(r, p, SIP_PROMISCREDIR | SIP_USEREQPHONE | SIP_DTMF | SIP_NAT | SIP_REINVITE | SIP_INSECURE);
< 		r->capability = p->capability;
< 		if (r->rtp) {
< 			ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", (ast_test_flag(r, SIP_NAT) & SIP_NAT_ROUTE));
< 			ast_rtp_setnat(r->rtp, (ast_test_flag(r, SIP_NAT) & SIP_NAT_ROUTE));
< 		}
< 		if (r->vrtp) {
< 			ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (ast_test_flag(r, SIP_NAT) & SIP_NAT_ROUTE));
< 			ast_rtp_setnat(r->vrtp, (ast_test_flag(r, SIP_NAT) & SIP_NAT_ROUTE));
< 		}
< 		strncpy(r->peername, p->username, sizeof(r->peername)-1);
< 		strncpy(r->authname, p->username, sizeof(r->authname)-1);
< 		strncpy(r->peersecret, p->secret, sizeof(r->peersecret)-1);
< 		strncpy(r->peermd5secret, p->md5secret, sizeof(r->peermd5secret)-1);
< 		strncpy(r->username, p->username, sizeof(r->username)-1);
< 		strncpy(r->tohost, p->tohost, sizeof(r->tohost)-1);
< 		strncpy(r->fullcontact, p->fullcontact, sizeof(r->fullcontact)-1);
< 		if (!r->initreq.headers && !ast_strlen_zero(p->fromdomain)) {
< 			if ((callhost = strchr(r->callid, '@'))) {
< 				strncpy(callhost + 1, p->fromdomain, sizeof(r->callid) - (callhost - r->callid) - 2);
< 			}
< 		}
< 		if (ast_strlen_zero(r->tohost)) {
< 			if (p->addr.sin_addr.s_addr)
< 				ast_inet_ntoa(r->tohost, sizeof(r->tohost), p->addr.sin_addr);
< 			else
< 				ast_inet_ntoa(r->tohost, sizeof(r->tohost), p->defaddr.sin_addr);
< 		}
< 		if (!ast_strlen_zero(p->fromdomain))
< 			strncpy(r->fromdomain, p->fromdomain, sizeof(r->fromdomain)-1);
< 		if (!ast_strlen_zero(p->fromuser))
< 			strncpy(r->fromuser, p->fromuser, sizeof(r->fromuser)-1);
< 		r->maxtime = p->maxms;
< 		r->callgroup = p->callgroup;
< 		r->pickupgroup = p->pickupgroup;
< 		if (ast_test_flag(r, SIP_DTMF) == SIP_DTMF_RFC2833)
< 			r->noncodeccapability |= AST_RTP_DTMF;
< 		else
< 			r->noncodeccapability &= ~AST_RTP_DTMF;
< 		strncpy(r->context, p->context,sizeof(r->context)-1);
< 		if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
< 		    (!p->maxms || ((p->lastms >= 0)  && (p->lastms <= p->maxms)))) {
< 			if (p->addr.sin_addr.s_addr) {
< 				r->sa.sin_addr = p->addr.sin_addr;
< 				r->sa.sin_port = p->addr.sin_port;
---
> 			found++;
> 			r->capability = p->capability;
> 			r->nat = p->nat;
> 			if (r->rtp) {
> 				ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", (r->nat & SIP_NAT_ROUTE));
> 				ast_rtp_setnat(r->rtp, (r->nat & SIP_NAT_ROUTE));
> 			}
> 			if (r->vrtp) {
> 				ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (r->nat & SIP_NAT_ROUTE));
> 				ast_rtp_setnat(r->vrtp, (r->nat & SIP_NAT_ROUTE));
> 			}
> 			strncpy(r->peername, p->username, sizeof(r->peername)-1);
> 			strncpy(r->authname, p->username, sizeof(r->authname)-1);
> 			strncpy(r->peersecret, p->secret, sizeof(r->peersecret)-1);
> 			strncpy(r->peermd5secret, p->md5secret, sizeof(r->peermd5secret)-1);
> 			strncpy(r->username, p->username, sizeof(r->username)-1);
> 			strncpy(r->tohost, p->tohost, sizeof(r->tohost)-1);
> 			strncpy(r->fullcontact, p->fullcontact, sizeof(r->fullcontact)-1);
> 			if (!r->initreq.headers && !ast_strlen_zero(p->fromdomain)) {
> 				if ((callhost = strchr(r->callid, '@'))) {
> 					strncpy(callhost + 1, p->fromdomain, sizeof(r->callid) - (callhost - r->callid) - 2);
> 				}
> 			}
> 			if (ast_strlen_zero(r->tohost)) {
> 				if (p->addr.sin_addr.s_addr)
> 					ast_inet_ntoa(r->tohost, sizeof(r->tohost), p->addr.sin_addr);
> 				else
> 					ast_inet_ntoa(r->tohost, sizeof(r->tohost), p->defaddr.sin_addr);
> 			}
> 			if (!ast_strlen_zero(p->fromdomain))
> 				strncpy(r->fromdomain, p->fromdomain, sizeof(r->fromdomain)-1);
> 			if (!ast_strlen_zero(p->fromuser))
> 				strncpy(r->fromuser, p->fromuser, sizeof(r->fromuser)-1);
> 			r->insecure = p->insecure;
> 			r->canreinvite = p->canreinvite;
> 			r->maxtime = p->maxms;
> 			r->callgroup = p->callgroup;
> 			r->pickupgroup = p->pickupgroup;
> 			if (p->dtmfmode) {
> 				r->dtmfmode = p->dtmfmode;
> 				if (r->dtmfmode & SIP_DTMF_RFC2833)
> 					r->noncodeccapability |= AST_RTP_DTMF;
> 				else
> 					r->noncodeccapability &= ~AST_RTP_DTMF;
> 			}
> 			r->promiscredir = p->promiscredir;
> 			r->usereqphone = p->usereqphone;
> 			strncpy(r->context, p->context,sizeof(r->context)-1);
> 			if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
> 				(!p->maxms || ((p->lastms >= 0)  && (p->lastms <= p->maxms)))) {
> 				if (p->addr.sin_addr.s_addr) {
> 					r->sa.sin_addr = p->addr.sin_addr;
> 					r->sa.sin_port = p->addr.sin_port;
> 				} else {
> 					r->sa.sin_addr = p->defaddr.sin_addr;
> 					r->sa.sin_port = p->defaddr.sin_port;
> 				}
> 				memcpy(&r->recv, &r->sa, sizeof(r->recv));
1314,1315c1325,1328
< 				r->sa.sin_addr = p->defaddr.sin_addr;
< 				r->sa.sin_port = p->defaddr.sin_port;
---
> 				if (p->temponly) {
> 					destroy_peer(p);
> 				}
> 				p = NULL;
1317,1320d1329
< 			memcpy(&r->recv, &r->sa, sizeof(r->recv));
< 		} else {
< 			ASTOBJ_UNREF(p,sip_destroy_peer);
< 		}
1321a1331
> 	ast_mutex_unlock(&peerl.lock);
1353c1363,1365
< 		ASTOBJ_UNREF(p,sip_destroy_peer);
---
> 		if (p->temponly) {
> 			destroy_peer(p);
> 		}
1425c1437
< 	ast_set_flag(p, SIP_OUTGOING);
---
> 	p->outgoing = 1;
1429d1440
< 		ast_log(LOG_DEBUG, "Disabling OSP support for this call. osptoken = %s, osphandle = %s\n", osptoken, osphandle);
1449,1466d1459
< static void sip_registry_destroy(struct sip_registry *reg)
< {
< 	/* Really delete */
< 	if (reg->call) {
< 		/* Clear registry before destroying to ensure
< 		   we don't get reentered trying to grab the registry lock */
< 		reg->call->registry = NULL;
< 		sip_destroy(reg->call);
< 	}
< 	if (reg->expire > -1)
< 		ast_sched_del(sched, reg->expire);
< 	if (reg->timeout > -1)
< 		ast_sched_del(sched, reg->timeout);
< 	regobjs--;
< 	free(reg);
< 	
< }
< 
1494,1496c1487,1496
< 		if (p->registry->call == p)
< 			p->registry->call = NULL;
< 		ASTOBJ_UNREF(p->registry,sip_registry_destroy);
---
> 		/* Carefully unlink from registry */
> 		struct sip_registry *reg;
> 		ast_mutex_lock(&regl.lock);
> 		reg = regl.registrations;
> 		while(reg) {
> 			if ((reg == p->registry) && (p->registry->call == p))
> 				p->registry->call=NULL;
> 			reg = reg->next;
> 		}
> 		ast_mutex_unlock(&regl.lock);
1551a1552
> 	ast_mutex_lock(&userl.lock);
1554a1556
> 		ast_mutex_unlock(&userl.lock);
1576c1578,1581
< 					ASTOBJ_UNREF(u,sip_destroy_user);
---
> 					ast_mutex_unlock(&userl.lock);
> 					if (u->temponly) {
> 						destroy_user(u);
> 					}
1608c1613,1616
< 	ASTOBJ_UNREF(u,sip_destroy_user);
---
> 	ast_mutex_unlock(&userl.lock);
> 	if (u->temponly) {
> 		destroy_user(u);
> 	}
1666c1674
< 	struct ast_flags locflags = {0};
---
> 	int needdestroy = 0;
1679c1687
< 	if (ast_test_flag(p, SIP_OUTGOING)) {
---
> 	if ( p->outgoing ) {
1707c1715
< 	ast_set_flag(&locflags, SIP_NEEDDESTROY);	
---
> 	needdestroy = 1; 
1709c1717
< 	if (!ast_test_flag(p, SIP_ALREADYGONE) && !ast_strlen_zero(p->initreq.data)) {
---
> 	if (!p->alreadygone && !ast_strlen_zero(p->initreq.data)) {
1711c1719
< 			if (ast_test_flag(p, SIP_OUTGOING)) {
---
> 			if (p->outgoing) {
1715c1723
< 				ast_clear_flag(&locflags, SIP_NEEDDESTROY);
---
> 				needdestroy = 0;
1720c1728
< 					if (ast_test_flag(p, SIP_OUTGOING)) {
---
> 					if ( p->outgoing ) {
1741,1742c1749,1750
< 				ast_set_flag(p, SIP_PENDINGBYE);	
< 				ast_clear_flag(p, SIP_NEEDREINVITE);	
---
> 				p->pendingbye = 1;
> 				p->needreinvite = 0;
1746c1754
< 	ast_copy_flags(p, (&locflags), SIP_NEEDDESTROY);	
---
> 	p->needdestroy = needdestroy;
1800c1808
< 				if ((ast->_state != AST_STATE_UP) && !ast_test_flag(p, SIP_PROGRESS_SENT) && !ast_test_flag(p, SIP_OUTGOING)) {
---
> 				if ((ast->_state != AST_STATE_UP) && !p->progress && !p->outgoing) {
1802c1810
< 					ast_set_flag(p, SIP_PROGRESS_SENT);	
---
> 					p->progress = 1;
1804d1811
< 				time(&p->lastrtptx);
1813c1820
< 				if ((ast->_state != AST_STATE_UP) && !ast_test_flag(p, SIP_PROGRESS_SENT) && !ast_test_flag(p, SIP_OUTGOING)) {
---
> 				if ((ast->_state != AST_STATE_UP) && !p->progress && !p->outgoing) {
1815c1822
< 					ast_set_flag(p, SIP_PROGRESS_SENT);	
---
> 					p->progress = 1;
1817d1823
< 				time(&p->lastrtptx);
1853,1856c1859
< 	int res = 0;
< 	ast_mutex_lock(&p->lock);
< 	switch (ast_test_flag(p, SIP_DTMF)) {
< 	case SIP_DTMF_INFO:
---
> 	if (p && (p->dtmfmode & SIP_DTMF_INFO)) {
1858,1865d1860
< 		break;
< 	case SIP_DTMF_RFC2833:
< 		if (p->rtp)
< 			ast_rtp_senddigit(p->rtp, digit);
< 		break;
< 	case SIP_DTMF_INBAND:
< 		res = -1;
< 		break;
1867,1868c1862,1868
< 	ast_mutex_unlock(&p->lock);
< 	return res;
---
> 	if (p && p->rtp && (p->dtmfmode & SIP_DTMF_RFC2833)) {
> 		ast_rtp_senddigit(p->rtp, digit);
> 	}
> 	/* If in-band DTMF is desired, send that */
> 	if (p->dtmfmode & SIP_DTMF_INBAND)
> 		return -1;
> 	return 0;
1877d1876
< 	ast_mutex_lock(&p->lock);
1879d1877
< 	ast_mutex_unlock(&p->lock);
1889,1891d1886
< 	int res = 0;
< 
< 	ast_mutex_lock(&p->lock);
1895,1896c1890
< 			if (!ast_test_flag(p, SIP_PROGRESS_SENT) ||
< 			    (ast_test_flag(p, SIP_PROG_INBAND) == SIP_PROG_INBAND_NEVER)) {
---
> 			if (!p->progress || !p->progressinband) {
1899,1900c1893,1894
< 				ast_set_flag(p, SIP_RINGING);
< 				if (ast_test_flag(p, SIP_PROG_INBAND) != SIP_PROG_INBAND_YES)
---
> 				p->ringing = 1;
> 				if (p->progressinband < 2)
1906,1907c1900
< 		res = -1;
< 		break;
---
> 		return -1;
1911c1904
< 			ast_set_flag(p, SIP_ALREADYGONE);	
---
> 			p->alreadygone = 1;
1915,1916c1908
< 		res = -1;
< 		break;
---
> 		return -1;
1920c1912
< 			ast_set_flag(p, SIP_ALREADYGONE);	
---
> 			p->alreadygone = 1;
1924,1925c1916
< 		res = -1;
< 		break;
---
> 		return -1;
1928c1919
< 		if ((ast->_state != AST_STATE_UP) && !ast_test_flag(p, SIP_PROGRESS_SENT) && !ast_test_flag(p, SIP_OUTGOING)) {
---
> 		if ((ast->_state != AST_STATE_UP) && !p->progress && !p->outgoing) {
1930c1921
< 			ast_set_flag(p, SIP_PROGRESS_SENT);	
---
> 			p->progress = 1;
1933,1934c1924
< 		res = -1;
< 		break;
---
> 		return -1;
1936,1937c1926
< 		res = -1;
< 		break;
---
> 		return -1;
1940,1941c1929
< 		res = -1;
< 		break;
---
> 		return -1;
1943,1944c1931
< 	ast_mutex_unlock(&p->lock);
< 	return res;
---
> 	return 0;
1985c1972
<                 if (ast_test_flag(i, SIP_DTMF) ==  SIP_DTMF_INBAND) {
---
>                 if (i->dtmfmode & SIP_DTMF_INBAND) {
2211c2198
< 	if (f && (f->frametype == AST_FRAME_DTMF) && (ast_test_flag(p, SIP_DTMF) != SIP_DTMF_RFC2833))
---
> 	if (f && (f->frametype == AST_FRAME_DTMF) && !(p->dtmfmode & SIP_DTMF_RFC2833))
2222c2209
<             if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
---
>             if ((p->dtmfmode & SIP_DTMF_INBAND) && p->vad) {
2267a2255
> 	char iabuf[INET_ADDRSTRLEN];
2313c2301
< 		ast_copy_flags(p, &global_flags, SIP_NAT);
---
> 		p->nat = global_nat;
2315c2303
< 		ast_rtp_setnat(p->rtp, (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
---
> 		ast_rtp_setnat(p->rtp, (p->nat & SIP_NAT_ROUTE));
2317c2305
< 			ast_rtp_setnat(p->vrtp, (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
---
> 			ast_rtp_setnat(p->vrtp, (p->nat & SIP_NAT_ROUTE));
2321c2309,2313
< 	build_via(p, p->via, sizeof(p->via));
---
> 	/* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
> 	if (p->nat != SIP_NAT_NEVER)
> 		snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
> 	else
> 		snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
2326c2318,2319
< 	ast_copy_flags(p, (&global_flags), SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_DTMF | SIP_REINVITE | SIP_PROG_INBAND | SIP_OSPAUTH);
---
> 	/* Assume reinvite OK and via INVITE */
> 	p->canreinvite = global_canreinvite;
2328a2322,2328
> 	p->dtmfmode = global_dtmfmode;
> 	p->promiscredir = global_promiscredir;
> 	p->trustrpid = global_trustrpid;
> 	p->progressinband = global_progressinband;
> #ifdef OSP_SUPPORT
> 	p->ospauth = global_ospauth;
> #endif
2331d2330
< 	p->rtpkeepalive = global_rtpkeepalive;
2333c2332
< 	if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833)
---
> 	if (p->dtmfmode & SIP_DTMF_RFC2833)
2458,2459d2456
< 		regobjs++;
< 		ASTOBJ_INIT(reg);
2475,2476c2472,2475
< 		ASTOBJ_CONTAINER_LINK(&regl, reg);
< 		ASTOBJ_UNREF(reg,sip_registry_destroy);
---
> 		ast_mutex_lock(&regl.lock);
> 		reg->next = regl.registrations;
> 		regl.registrations = reg;
> 		ast_mutex_unlock(&regl.lock);
2615d2613
< 	int destiterator = 0;
2623d2620
< 	time(&p->lastrtptx);
2631,2632c2628
< 	sdpLineNum_iterator_init(&destiterator);
< 	c = get_sdp_iterate(&destiterator, req, "c");
---
> 	c = get_sdp(req, "c");
2648c2644
< 	ast_set_flag(p, SIP_NOVIDEO);	
---
> 	p->novideo = 1;
2673c2669
< 			ast_clear_flag(p, SIP_NOVIDEO);	
---
> 			p->novideo = 0;
2691,2705c2687
< 	/* Check for Media-description-level-address for audio */
< 	if (pedanticsipchecking) {
< 		c = get_sdp_iterate(&destiterator, req, "c");
< 		if (!ast_strlen_zero(c)) {
< 			if (sscanf(c, "IN IP4 %256s", host) != 1) {
< 				ast_log(LOG_WARNING, "Invalid secondary host in c= line, '%s'\n", c);
< 			} else {
< 				/* XXX This could block for a long time, and block the main thread! XXX */
< 				hp = ast_gethostbyname(host, &ahp);
< 				if (!hp) {
< 					ast_log(LOG_WARNING, "Unable to lookup host in secondary c= line, '%s'\n", c);
< 				}
< 			}
< 		}
< 	}
---
> 
2719,2733d2700
< 	/* Check for Media-description-level-address for video */
< 	if (pedanticsipchecking) {
< 		c = get_sdp_iterate(&destiterator, req, "c");
< 		if (!ast_strlen_zero(c)) {
< 			if (sscanf(c, "IN IP4 %256s", host) != 1) {
< 				ast_log(LOG_WARNING, "Invalid secondary host in c= line, '%s'\n", c);
< 			} else {
< 				/* XXX This could block for a long time, and block the main thread! XXX */
< 				hp = ast_gethostbyname(host, &ahp);
< 				if (!hp) {
< 					ast_log(LOG_WARNING, "Unable to lookup host in secondary c= line, '%s'\n", c);
< 				}
< 			}
< 		}
< 	}
2793c2760
< 		ast_log(LOG_NOTICE, "No compatible codecs!\n");
---
> 		ast_log(LOG_WARNING, "No compatible codecs!\n");
2813,2814d2779
< 				if (sendonly)
< 					ast_rtp_stop(p->rtp);
2956c2921
< 			if (!copied && (ast_test_flag(p, SIP_NAT) == SIP_NAT_ALWAYS)) {
---
> 			if (!copied && (p->nat == SIP_NAT_ALWAYS)) {
3102d3066
< /*--- respprep: Prepare SIP response packet ---*/
3110,3111c3074
< 	if (msg[0] == '2')
< 		copy_all_header(resp, req, "Record-Route");
---
> 	if (msg[0] == '2') copy_all_header(resp, req, "Record-Route");
3117c3080
< 		if (!ast_strlen_zero(p->theirtag) && ast_test_flag(p, SIP_OUTGOING))
---
> 		if (!ast_strlen_zero(p->theirtag) && p->outgoing)
3119c3082
< 		else if (p->tag && !ast_test_flag(p, SIP_OUTGOING))
---
> 		else if (p->tag && !p->outgoing)
3147d3109
< /*--- reqprep: Initialize a SIP request packet ---*/
3153a3116
> 	char iabuf[INET_ADDRSTRLEN];
3168,3180c3131,3138
< 		build_via(p, p->via, sizeof(p->via));
< 	}
< 	if (!strcasecmp(msg, "CANCEL")) {
< 		c = p->initreq.rlPart2;	/* Use original URI */
< 	} else if (!strcasecmp(msg, "ACK")) {
< 		/* Use URI from Contact: in 200 OK (if INVITE) 
< 		(we only have the contacturi on INVITEs) */
< 		if (!ast_strlen_zero(p->okcontacturi))
< 			c = p->okcontacturi;
< 		else
< 			c = p->initreq.rlPart2;
< 	} else if (!ast_strlen_zero(p->okcontacturi)) {
< 		c = p->okcontacturi; /* Use for BYE or REINVITE */
---
> 		if (p->nat & SIP_NAT_RFC3581)
> 			snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
> 		else /* Some implementations (e.g. Uniden UIP200) can't handle rport being in the message!! */
> 			snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
> 	}
> 	if (!strcasecmp(msg, "CANCEL") || !strcasecmp(msg, "ACK")) {
> 		/* MUST use original URI */
> 		c = p->initreq.rlPart2;
3184,3185c3142
< 		/* We have no URI, use To: or From:  header as URI (depending on direction) */
< 		if (ast_test_flag(p, SIP_OUTGOING))
---
> 		if (p->outgoing)
3220c3177
< 		if (ast_test_flag(p, SIP_OUTGOING) && !ast_strlen_zero(p->theirtag))
---
> 		if (p->outgoing && !ast_strlen_zero(p->theirtag))
3222c3179
< 		else if (!ast_test_flag(p, SIP_OUTGOING))
---
> 		else if (!p->outgoing)
3229c3186
< 	if (ast_test_flag(p, SIP_OUTGOING)) {
---
> 	if (p->outgoing) {
3432c3389
< 			ast_verbose("Answering/Requesting with root capability 0x%x (%s)\n", p->prefcodec, ast_getformatname(p->prefcodec));
---
> 			ast_verbose("Answering/Requesting with root capability %d\n", p->prefcodec);
3519c3476
< 	if ((p->vrtp) && (!ast_test_flag(p, SIP_NOVIDEO)) && (capability & VIDEO_CODEC_MASK)) /* only if video response is appropriate */
---
> 	if ((p->vrtp) && (!p->novideo) && (capability & VIDEO_CODEC_MASK)) /* only if video response is appropriate */
3531c3488
< 	if ((p->vrtp) && (!ast_test_flag(p, SIP_NOVIDEO)) && (capability & VIDEO_CODEC_MASK)) { /* only if video response is appropriate */
---
> 	if ((p->vrtp) && (!p->novideo) && (capability & VIDEO_CODEC_MASK)) { /* only if video response is appropriate */
3537d3493
< 	time(&p->lastrtptx);
3556c3512
< /*--- transmit_response_with_sdp: Used for 200 OK and 183 early media ---*/
---
> /*--- transmit_response_with_sdp: Used for 200 OK ---*/
3617c3573
<     req->rlPart2= e;	/* URI */
---
>     req->rlPart2= e;
3631,3636c3587,3589
< /*--- transmit_reinvite_with_sdp: Transmit reinvite with SDP :-) ---*/
< /* 	A re-invite is basically a new INVITE with the same CALL-ID and TAG as the
< 	INVITE that opened the SIP dialogue 
< 	We reinvite so that the audio stream (RTP) go directly between
< 	the SIP UAs. SIP Signalling stays with * in the path.
< */
---
> /* transmit_reinvite_with_sdp: Transmit reinvite with SDP :-) ---*/
> /*   A re-invite is basically a new INVITE with the same CALL-ID and TAG as the
>      INVITE that opened the SIP dialogue */
3640c3593
< 	if (ast_test_flag(p, SIP_REINVITE_UPDATE))
---
> 	if (p->canreinvite == REINVITE_UPDATE)
3655c3608
< 	ast_set_flag(p, SIP_OUTGOING);
---
> 	p->outgoing = 1;
3703c3656
< 	if (ast_test_flag(p, SIP_USEREQPHONE)) {
---
> 	if (p->usereqphone) {
3797c3750
< /*--- transmit_invite: Build REFER/INVITE/OPTIONS message and transmit it ---*/
---
> /*--- transmit_invite: Build REFER/INVITE/OPTIONS message and trasmit it ---*/
3800a3754
> 	char iabuf[INET_ADDRSTRLEN];
3805c3759,3762
< 		build_via(p, p->via, sizeof(p->via));
---
> 		if (p->nat & SIP_NAT_RFC3581)
> 			snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
> 		else /* Work around buggy UNIDEN UIP200 firmware */
> 			snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
3821d3777
< 		ast_log(LOG_DEBUG,"Adding OSP Token: %s\n", osptoken);
3824,3827d3779
< 	else
< 	{
< 		ast_log(LOG_DEBUG,"NOT Adding OSP Token\n");
< 	}
3831c3783
< 		add_header(&req, "Alert-Info",distinctive_ring);
---
> 		add_header(&req, "Alert-info",distinctive_ring);
3936,3937d3887
< 		add_header(&req, "Event", "presence");
< 		add_header(&req, "Subscription-State", "active");
4039,4052d3988
< static int transmit_sip_request(struct sip_pvt *p,struct sip_request *req)
< {
< 	if (!p->initreq.headers) {
< 		/* Use this as the basis */
< 		copy_request(&p->initreq, req);
< 		parse(&p->initreq);
< 		if (sip_debug_test_pvt(p))
< 			ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines);
< 		determine_firstline_parts(&p->initreq);
< 	}
< 
< 	return send_request(p, req, 0, p->ocseq);
< }
< 
4114c4050
< 	struct sip_registry *r= ASTOBJ_REF((struct sip_registry *) data);
---
> 	struct sip_registry *r=(struct sip_registry *)data;
4116,4121d4051
< 	/* if we couldn't get a reference to the registry object, punt */
< 	if (!r)
< 		return 0;
< 
< 	/* Since registry's are only added/removed by the the monitor thread, this
< 	   may be overkill to reference/dereference at all here */
4124a4055
> 	ast_mutex_lock(&regl.lock);
4127c4058
< 	ASTOBJ_UNREF(r,sip_registry_destroy);
---
> 	ast_mutex_unlock(&regl.lock);
4144c4075
< 	struct sip_registry *r = ASTOBJ_REF((struct sip_registry *) data);
---
> 	struct sip_registry *r=data;
4148,4150c4079
< 	/* if we couldn't get a reference to the registry object, punt */
< 	if (!r)
< 		return 0;
---
> 	ast_mutex_lock(&regl.lock);
4157,4158c4086
< 		if (p->registry)
< 			ASTOBJ_UNREF(p->registry, sip_registry_destroy);
---
> 		p->registry = NULL;
4160c4088
< 		ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 		p->needdestroy = 1;
4168c4096
< 	ASTOBJ_UNREF(r,sip_registry_destroy);
---
> 	ast_mutex_unlock(&regl.lock);
4180a4109
> 	char iabuf[INET_ADDRSTRLEN];
4220c4149
< 		ast_set_flag(p, SIP_OUTGOING);	/* Registration is outgoing call */
---
> 		p->outgoing = 1;		/* Registration is outgoing call */
4222c4151
< 		p->registry=ASTOBJ_REF(r);	/* Add pointer to registry in packet */
---
> 		p->registry=r;			/* Add pointer to registry in packet */
4290c4219,4223
< 	build_via(p, via, sizeof(via));
---
> 	/* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
> 	if (p->nat & SIP_NAT_RFC3581)
> 		snprintf(via, sizeof(via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
> 	else /* Work around buggy UNIDEN UIP200 firmware */
> 		snprintf(via, sizeof(via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
4350c4283
< 	if (ast_test_flag(p, SIP_OUTGOING)) 
---
> 	if (p->outgoing) 
4433,4434c4366,4367
< 	if (ast_test_flag(p, SIP_SELFDESTRUCT)) {
< 		ASTOBJ_MARK(p);	
---
> 	if (p->selfdestruct) {
> 		p->delme = 1;
4507,4585d4439
< /*--- parse_ok_contact: Parse contact header for 200 OK on INVITE ---*/
< static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req)
< {
< 	char contact[250]= ""; 
< 	char *c, *n, *pt;
< 	int port;
< 	struct hostent *hp;
< 	struct ast_hostent ahp;
< 	struct sockaddr_in oldsin;
< 
< 	/* Look for brackets */
< 	strncpy(contact, get_header(req, "Contact"), sizeof(contact) - 1);
< 	c = contact;
< 	
< 	if ((n=strchr(c, '<'))) {
< 		c = n + 1;
< 		n = strchr(c, '>');
< 		/* Lose the part after the > */
< 		if (n) 
< 			*n = '\0';
< 	}
< 
< 
< 	/* Save full contact to call pvt for later bye or re-invite */
< 	strncpy(pvt->fullcontact, c, sizeof(pvt->fullcontact) - 1);	
< 
< 	/* Save URI for later ACKs, BYE or RE-invites */
< 	strncpy(pvt->okcontacturi, c, sizeof(pvt->okcontacturi) - 1);
< 	
< 	/* Make sure it's a SIP URL */
< 	if (strncasecmp(c, "sip:", 4)) {
< 		ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", c);
< 	} else
< 		c += 4;
< 
< 	/* Ditch arguments */
< 	n = strchr(c, ';');
< 	if (n) 
< 		*n = '\0';
< 
< 	/* Grab host */
< 	n = strchr(c, '@');
< 	if (!n) {
< 		n = c;
< 		c = NULL;
< 	} else {
< 		*n = '\0';
< 		n++;
< 	}
< 	pt = strchr(n, ':');
< 	if (pt) {
< 		*pt = '\0';
< 		pt++;
< 		port = atoi(pt);
< 	} else
< 		port = DEFAULT_SIP_PORT;
< 
< 	memcpy(&oldsin, &pvt->sa, sizeof(oldsin));
< 
< 	if (!(ast_test_flag(pvt, SIP_NAT) & SIP_NAT_ROUTE)) {
< 		/* XXX This could block for a long time XXX */
< 		/* We should only do this if it's a name, not an IP */
< 		hp = ast_gethostbyname(n, &ahp);
< 		if (!hp)  {
< 			ast_log(LOG_WARNING, "Invalid host '%s'\n", n);
< 			return -1;
< 		}
< 		pvt->sa.sin_family = AF_INET;
< 		memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
< 		pvt->sa.sin_port = htons(port);
< 	} else {
< 		/* Don't trust the contact field.  Just use what they came to us
< 		   with. */
< 		memcpy(&pvt->sa, &pvt->recv, sizeof(pvt->sa));
< 	}
< 	return 0;
< }
< 
< 
4667c4521
< 	if (!(ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)) {
---
> 	if (!(p->nat & SIP_NAT_ROUTE)) {
4690c4544
< 	if (!ast_test_flag(p, SIP_REALTIME))
---
> 	if (!p->temponly)
4869c4723
< 	    && ast_test_flag(p, SIP_OSPAUTH)
---
> 		&& !p->ospauth 
4882c4736
< 	else if (ast_test_flag(p, SIP_OSPAUTH)) {
---
> 	else if (p->ospauth) {
4893,4894c4747
< 		pbx_builtin_setvar_helper(p->owner, "_OSPHANDLE", tmp);
< 
---
> 		pbx_builtin_setvar_helper(p->owner, "OSPHANDLE", tmp);
4897,4898c4750
< 		if ((ast_test_flag(p, SIP_OSPAUTH) == SIP_OSPAUTH_EXCLUSIVE) ||
< 		    (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)))
---
> 		if ((p->ospauth > 1) || (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)))
5048a4901
> 	ast_mutex_lock(&peerl.lock);
5051,5052c4904,4907
< 		if (peer)
< 			ASTOBJ_UNREF(peer,sip_destroy_peer);
---
> 		if (peer && peer->temponly) {
> 			destroy_peer(peer);
> 		}
> 		peer = NULL;
5053a4909,4910
> 	ast_mutex_unlock(&peerl.lock);
> 
5055c4912
< 			if (!ast_test_flag(peer, SIP_DYNAMIC)) {
---
> 			if (!peer->dynamic) {
5058c4915
< 				ast_copy_flags(p, peer, SIP_NAT);
---
> 				p->nat = peer->nat;
5078c4935,4938
< 			ASTOBJ_CONTAINER_LINK(&peerl, peer);
---
> 			ast_mutex_lock(&peerl.lock);
> 			peer->next = peerl.peers;
> 			peerl.peers = peer;
> 			ast_mutex_unlock(&peerl.lock);
5097,5098c4957,4959
< 	if (peer)
< 		ASTOBJ_UNREF(peer,sip_destroy_peer);
---
> 	if (peer && peer->temponly) {
> 		destroy_peer(peer);
> 	}
5219,5220c5080
< 	struct ast_channel *chan = NULL, *peer = NULL;
< 
---
> 	
5314,5320c5174,5176
< 		if (p->refer_call) {
< 			if (p->refer_call == p) {
< 				ast_log(LOG_NOTICE, "Supervised transfer attempted to transfer into same call id (%s == %s)!\n", tmp5, p->callid);
< 				p->refer_call = NULL;
< 			} else
< 				return 0;
< 		} else
---
> 		if (p->refer_call)
> 			return 0;
> 		else
5324d5179
< 		
5332,5335d5186
< 		if((chan = p->owner) && (peer = ast_bridged_channel(p->owner))) {
< 			pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
< 			pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
< 		}
5426c5277
< 			ast_set_flag(p, SIP_NAT_ROUTE);
---
> 			p->nat |= SIP_NAT_ROUTE;
5428c5279
< 			if (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)
---
> 			if (p->nat & SIP_NAT_ROUTE)
5569a5421
> 	ast_mutex_lock(&userl.lock);
5572,5573c5424
< 	if (!mailbox && user && ast_apply_ha(user->ha, sin)) {
< 		ast_copy_flags(p, user, SIP_TRUSTRPID | SIP_USECLIENTCODE | SIP_NAT | SIP_PROG_INBAND | SIP_OSPAUTH);
---
> 	if (user && ast_apply_ha(user->ha, sin)) {
5581a5433,5439
> 		p->nat = user->nat;
> #ifdef OSP_SUPPORT
> 		p->ospauth = user->ospauth;
> #endif
> 		p->trustrpid = user->trustrpid;
> 		p->useclientcode = user->useclientcode;
> 		p->progressinband = user->progressinband;
5583c5441
< 		if(!ast_strlen_zero(rpid_num) && ast_test_flag(p, SIP_TRUSTRPID)) {
---
> 		if(!ast_strlen_zero(rpid_num) && p->trustrpid) {
5591,5592c5449,5450
< 			ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
< 			ast_rtp_setnat(p->rtp, (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
---
> 			ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", (p->nat & SIP_NAT_ROUTE));
> 			ast_rtp_setnat(p->rtp, (p->nat & SIP_NAT_ROUTE));
5595,5596c5453,5454
< 			ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
< 			ast_rtp_setnat(p->vrtp, (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
---
> 			ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (p->nat & SIP_NAT_ROUTE));
> 			ast_rtp_setnat(p->vrtp, (p->nat & SIP_NAT_ROUTE));
5600d5457
< 			ast_copy_flags(p, user, SIP_PROMISCREDIR | SIP_DTMF | SIP_REINVITE);
5614a5472
> 			p->canreinvite = user->canreinvite;
5623,5626c5481,5488
< 			if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833)
< 				p->noncodeccapability |= AST_RTP_DTMF;
< 			else
< 				p->noncodeccapability &= ~AST_RTP_DTMF;
---
> 			p->promiscredir = user->promiscredir;
> 			if (user->dtmfmode) {
> 				p->dtmfmode = user->dtmfmode;
> 				if (p->dtmfmode & SIP_DTMF_RFC2833)
> 					p->noncodeccapability |= AST_RTP_DTMF;
> 				else
> 					p->noncodeccapability &= ~AST_RTP_DTMF;
> 			}
5632c5494
< 			if (!mailbox && debug)
---
> 			if (debug)
5634c5496,5497
< 			ASTOBJ_UNREF(user,sip_destroy_user);
---
> 			if (user->temponly)
> 				destroy_user(user);
5638c5501,5502
< 
---
> 	/* Temp user gets cleaned up at the end */
> 	ast_mutex_unlock(&userl.lock);
5640a5505
> 		ast_mutex_lock(&peerl.lock);
5650c5515,5518
< 			ast_copy_flags(p, peer, SIP_TRUSTRPID | SIP_USECLIENTCODE | SIP_NAT | SIP_PROG_INBAND | SIP_OSPAUTH);
---
> 			p->nat = peer->nat;
> 			p->trustrpid = peer->trustrpid;
> 			p->useclientcode = peer->useclientcode;
> 			p->progressinband = peer->progressinband;
5652c5520
< 			if(!ast_strlen_zero(rpid_num) && ast_test_flag(p, SIP_TRUSTRPID)) {
---
> 			if(!ast_strlen_zero(rpid_num) && p->trustrpid) {
5657a5526,5528
> #ifdef OSP_SUPPORT
> 			p->ospauth = peer->ospauth;
> #endif
5659,5660c5530,5531
< 				ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
< 				ast_rtp_setnat(p->rtp, (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
---
> 				ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", (p->nat & SIP_NAT_ROUTE));
> 				ast_rtp_setnat(p->rtp, (p->nat & SIP_NAT_ROUTE));
5663,5664c5534,5535
< 				ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
< 				ast_rtp_setnat(p->vrtp, (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE));
---
> 				ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (p->nat & SIP_NAT_ROUTE));
> 				ast_rtp_setnat(p->vrtp, (p->nat & SIP_NAT_ROUTE));
5670c5541
< 			if (ast_test_flag(peer, SIP_INSECURE) == SIP_INSECURE_VERY) {
---
> 			if (peer->insecure > 1) {
5676c5547
< 				ast_copy_flags(p, peer, SIP_PROMISCREDIR | SIP_DTMF | SIP_REINVITE);
---
> 				p->canreinvite = peer->canreinvite;
5703,5706c5574,5581
< 				if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833)
< 					p->noncodeccapability |= AST_RTP_DTMF;
< 				else
< 					p->noncodeccapability &= ~AST_RTP_DTMF;
---
> 				p->promiscredir = peer->promiscredir;
> 				if (peer->dtmfmode) {
> 					p->dtmfmode = peer->dtmfmode;
> 					if (p->dtmfmode & SIP_DTMF_RFC2833)
> 						p->noncodeccapability |= AST_RTP_DTMF;
> 					else
> 						p->noncodeccapability &= ~AST_RTP_DTMF;
> 				}
5708,5709c5583,5585
< 			ASTOBJ_UNREF(peer,sip_destroy_peer);
< 		} else { 
---
> 			if (peer->temponly) 
> 				destroy_peer(peer);
> 		} else
5712,5722c5588
< 
< 			/* do we allow guests? */
< 			if (!global_allowguest)
< 				res = -1;  /* we don't want any guests, authentication will fail */
< #ifdef OSP_SUPPORT			
< 			else if (global_allowguest == 2) {
< 				ast_copy_flags(p, &global_flags, SIP_OSPAUTH);
< 				res = check_auth(p, req, p->randdata, sizeof(p->randdata), "", "", "", cmd, uri, reliable, ignore); 
< 			}
< #endif
< 		}
---
> 		ast_mutex_unlock(&peerl.lock);
5726,5727c5592,5594
< 	if (user)
< 		ASTOBJ_UNREF(user,sip_destroy_user);
---
> 	if (user && user->temponly) 
> 		destroy_user(user);
> 
5787a5655
> 	struct sip_user *user;
5794a5663,5664
> 	ast_mutex_lock(&userl.lock);
> 	user = userl.users;
5796,5799c5666,5668
< 	ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
< 		ASTOBJ_RDLOCK(iterator);
< 		if (iterator->incominglimit)
< 			snprintf(ilimits, sizeof(ilimits), "%d", iterator->incominglimit);
---
> 	for(user=userl.users;user;user=user->next) {
> 		if (user->incominglimit)
> 			snprintf(ilimits, sizeof(ilimits), "%d", user->incominglimit);
5802,5803c5671,5672
< 		if (iterator->outgoinglimit)
< 			snprintf(olimits, sizeof(olimits), "%d", iterator->outgoinglimit);
---
> 		if (user->outgoinglimit)
> 			snprintf(olimits, sizeof(olimits), "%d", user->outgoinglimit);
5806,5810c5675,5679
< 		snprintf(iused, sizeof(iused), "%d", iterator->inUse);
< 		snprintf(oused, sizeof(oused), "%d", iterator->outUse);
< 		ast_cli(fd, FORMAT2, iterator->name, iused, ilimits,oused,olimits);
< 		ASTOBJ_UNLOCK(iterator);
< 	} while (0) );
---
> 		snprintf(iused, sizeof(iused), "%d", user->inUse);
> 		snprintf(oused, sizeof(oused), "%d", user->outUse);
> 		ast_cli(fd, FORMAT2, user->name, iused, ilimits,oused,olimits);
> 	}
> 	ast_mutex_unlock(&userl.lock);
5835,5837d5703
< 	regex_t regexbuf;
< 	int havepattern = 0;
< 
5839,5840c5705,5706
< 
< 	if (argc > 4)
---
> 	struct sip_user *user;
> 	if (argc != 3) 
5842,5849c5708
< 	
< 	if (argc == 4) {
< 		if (regcomp(&regexbuf, argv[3], REG_EXTENDED | REG_NOSUB))
< 			return RESULT_SHOWUSAGE;
< 
< 		havepattern = 1;
< 	}
< 
---
> 	ast_mutex_lock(&userl.lock);
5851,5871c5710,5718
< 	ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
< 		ASTOBJ_RDLOCK(iterator);
< 
< 		if (havepattern && regexec(&regexbuf, iterator->name, 0, NULL, 0)) {
< 			ASTOBJ_UNLOCK(iterator);
< 			continue;
< 		}
< 
< 		ast_cli(fd, FORMAT, iterator->name, 
< 			iterator->secret, 
< 			iterator->accountcode,
< 			iterator->context,
< 			iterator->ha ? "Yes" : "No",
< 			nat2str(ast_test_flag(iterator, SIP_NAT)));
< 		ASTOBJ_UNLOCK(iterator);
< 	} while (0)
< 	);
< 
< 	if (havepattern)
< 		regfree(&regexbuf);
< 
---
> 	for(user=userl.users;user;user=user->next) {
> 		ast_cli(fd, FORMAT, user->name, 
> 				user->secret, 
> 				user->accountcode,
> 				user->context,
> 				user->ha ? "Yes" : "No",
> 				nat2str(user->nat));
> 	}
> 	ast_mutex_unlock(&userl.lock);
5879,5881d5725
< 	regex_t regexbuf;
< 	int havepattern = 0;
< 
5884c5728
< 
---
> 	struct sip_peer *peer;
5892c5736
< 	if (argc > 4)
---
> 	if (argc != 3 && argc != 5)
5894,5901c5738
< 	
< 	if (argc == 4) {
< 		if (regcomp(&regexbuf, argv[3], REG_EXTENDED | REG_NOSUB))
< 			return RESULT_SHOWUSAGE;
< 
< 		havepattern = 1;
< 	}
< 
---
> 	ast_mutex_lock(&peerl.lock);
5904c5741
< 	ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
---
> 	for (peer = peerl.peers;peer;peer = peer->next) {
5906a5744
> 		int print_line = -1;
5909,5918c5747,5749
< 		ASTOBJ_RDLOCK(iterator);
< 
< 		if (havepattern && regexec(&regexbuf, iterator->name, 0, NULL, 0)) {
< 			ASTOBJ_UNLOCK(iterator);
< 			continue;
< 		}
< 
< 		ast_inet_ntoa(nm, sizeof(nm), iterator->mask);
< 		if (!ast_strlen_zero(iterator->username))
< 			snprintf(name, sizeof(name), "%s/%s", iterator->name, iterator->username);
---
> 		ast_inet_ntoa(nm, sizeof(nm), peer->mask);
> 		if (!ast_strlen_zero(peer->username))
> 			snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
5920,5922c5751,5753
< 			strncpy(name, iterator->name, sizeof(name) - 1);
< 		if (iterator->maxms) {
< 			if (iterator->lastms < 0) {
---
> 			strncpy(name, peer->name, sizeof(name) - 1);
> 		if (peer->maxms) {
> 			if (peer->lastms < 0) {
5925,5926c5756,5757
< 			} else if (iterator->lastms > iterator->maxms) {
< 				snprintf(status, sizeof(status), "LAGGED (%d ms)", iterator->lastms);
---
> 			} else if (peer->lastms > peer->maxms) {
> 				snprintf(status, sizeof(status), "LAGGED (%d ms)", peer->lastms);
5928,5929c5759,5760
< 			} else if (iterator->lastms) {
< 				snprintf(status, sizeof(status), "OK (%d ms)", iterator->lastms);
---
> 			} else if (peer->lastms) {
> 				snprintf(status, sizeof(status), "OK (%d ms)", peer->lastms);
5933c5764
< 				if ( ntohs(iterator->addr.sin_port) == 0 ) { 
---
> 				if ( ntohs(peer->addr.sin_port) == 0 ) { 
5943c5774
< 			if ( ntohs(iterator->addr.sin_port) == 0 ) {
---
> 		        if ( ntohs(peer->addr.sin_port) == 0 ) {
5951,5965c5782,5798
< 			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, SIP_NAT) & SIP_NAT_ROUTE) ? " N " : "   ",	/* NAT=yes? */
< 			iterator->ha ? " A " : "   ", 	/* permit/deny */
< 			nm, ntohs(iterator->addr.sin_port), status);
< 
< 		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, SIP_NAT) & SIP_NAT_ROUTE) ? " N " : "   ",	/* NAT=yes? */
< 			iterator->ha ? " A " : "   ",       /* permit/deny */
< 			nm,
< 			ntohs(iterator->addr.sin_port), status);
< 
< 		ASTOBJ_UNLOCK(iterator);
---
> 			peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
> 			peer->dynamic ? " D " : "   ", 	/* Dynamic or not? */
> 			(peer->nat & SIP_NAT_ROUTE) ? " N " : "   ",	/* NAT=yes? */
> 			peer->ha ? " A " : "   ", 	/* permit/deny */
> 			nm, ntohs(peer->addr.sin_port), status);
> 
> 		if (argc == 5) {
> 			if (!strcasecmp(argv[3],"include") && strstr(srch,argv[4])) {
> 				print_line = -1;
> 			} else if (!strcasecmp(argv[3],"exclude") && !strstr(srch,argv[4])) {
> 				print_line = 1;
> 			} else if (!strcasecmp(argv[3],"begin") && !strncasecmp(srch,argv[4],strlen(argv[4]))) {
> 				print_line = -1;
> 			} else {
> 				print_line = 0;
> 			}
> 		}
5966a5800,5808
> 		if (print_line) {
> 		    ast_cli(fd, FORMAT, name, 
> 			peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
>                         peer->dynamic ? " D " : "   ",  /* Dynamic or not? */
>                         (peer->nat & SIP_NAT_ROUTE) ? " N " : "   ",	/* NAT=yes? */
>                         peer->ha ? " A " : "   ",       /* permit/deny */
> 			nm,
> 			ntohs(peer->addr.sin_port), status);
> 		}
5968,5974c5810,5812
< 	} while(0) );
< 
< 	ast_cli(fd,"%d sip peers [%d online , %d offline]\n",total_peers,peers_online,peers_offline);
< 
< 	if (havepattern)
< 		regfree(&regexbuf);
< 
---
> 	}
> 	ast_cli(fd,"%d sip peers loaded [%d online , %d offline]\n",total_peers,peers_online,peers_offline);
> 	ast_mutex_unlock(&peerl.lock);
5980,5992d5817
< static int sip_show_objects(int fd, int argc, char *argv[])
< {
< 	char tmp[256];
< 	if (argc != 3)
< 		return RESULT_SHOWUSAGE;
< 	ast_cli(fd, "-= User objects: %d static, %d realtime =-\n\n", suserobjs, ruserobjs);
< 	ASTOBJ_CONTAINER_DUMP(fd, tmp, sizeof(tmp), &userl);
< 	ast_cli(fd, "-= Peer objects: %d static, %d realtime, %d autocreate =-\n\n", speerobjs, rpeerobjs, apeerobjs);
< 	ASTOBJ_CONTAINER_DUMP(fd, tmp, sizeof(tmp), &peerl);
< 	ast_cli(fd, "-= Registry objects: %d =-\n\n", regobjs);
< 	ASTOBJ_CONTAINER_DUMP(fd, tmp, sizeof(tmp), &regl);
< 	return RESULT_SUCCESS;
< }
5996,5998c5821,5822
< 	char buf[256];
< 	ast_cli(fd, ast_print_group(buf, sizeof(buf), group) );
< }
---
> 	unsigned int i;
> 	int first=1;
6000,6023c5824,5834
< static const char *dtmfmode2str(int mode)
< {
< 	switch (mode) {
< 	case SIP_DTMF_RFC2833:
< 		return "rfc2833";
< 	case SIP_DTMF_INFO:
< 		return "info";
< 	case SIP_DTMF_INBAND:
< 		return "inband";
< 	}
< 	return "<error>";
< }
< 
< static const char *insecure2str(int mode)
< {
< 	switch (mode) {
< 	case SIP_SECURE:
< 		return "no";
< 	case SIP_INSECURE_NORMAL:
< 		return "yes";
< 	case SIP_INSECURE_VERY:
< 		return "very";
< 	}
< 	return "<error>";
---
> 	for (i=0; i<=31; i++) {	/* Max group is 31 */
> 		if (group & (1 << i)) {
> 	   		if (!first) {
> 				ast_cli(fd, ", ");
> 			} else {
> 				first=0;
> 	  		}
> 			ast_cli(fd, "%u", i);
> 		}
>     	}
> 	ast_cli(fd, " (%u)\n", group);
6038a5850
> 	ast_mutex_lock(&peerl.lock);
6055c5867
< 		ast_cli(fd, "  Dynamic      : %s\n", (ast_test_flag(peer, SIP_DYNAMIC)?"Yes":"No"));
---
> 		ast_cli(fd, "  Dynamic      : %s\n", (peer->dynamic?"Yes":"No"));
6059,6060c5871,5872
< 		ast_cli(fd, "  Insecure     : %s\n", insecure2str(ast_test_flag(peer, SIP_INSECURE)));
< 		ast_cli(fd, "  Nat          : %s\n", nat2str(ast_test_flag(peer, SIP_NAT)));
---
> 		ast_cli(fd, "  Insecure     : %s\n", (peer->insecure?((peer->insecure == 2)?"Very":"Yes"):"No") );
> 		ast_cli(fd, "  Nat          : %s\n", nat2str(peer->nat));
6062,6064c5874,5876
< 		ast_cli(fd, "  CanReinvite  : %s\n", (ast_test_flag(peer, SIP_CAN_REINVITE)?"Yes":"No"));
< 		ast_cli(fd, "  PromiscRedir : %s\n", (ast_test_flag(peer, SIP_PROMISCREDIR)?"Yes":"No"));
< 		ast_cli(fd, "  User=Phone   : %s\n", (ast_test_flag(peer, SIP_USEREQPHONE)?"Yes":"No"));
---
> 		ast_cli(fd, "  CanReinvite  : %s\n", (peer->canreinvite?"Yes":"No"));
> 		ast_cli(fd, "  PromiscRedir : %s\n", (peer->promiscredir?"Yes":"No"));
> 		ast_cli(fd, "  User=Phone   : %s\n", (peer->usereqphone?"Yes":"No"));
6067c5879,5886
< 		ast_cli(fd, "  DTMFmode     : %s\n", dtmfmode2str(ast_test_flag(peer, SIP_DTMF)));
---
> 		ast_cli(fd, "  DTMFmode     : ");
> 		if (peer->dtmfmode == SIP_DTMF_RFC2833)
>                        ast_cli(fd, "rfc2833 ");
>                 if (peer->dtmfmode == SIP_DTMF_INFO)
>                        ast_cli(fd, "info ");
>                 if (peer->dtmfmode == SIP_DTMF_INBAND)
>                         ast_cli(fd, "inband ");
>                 ast_cli(fd, "\n" );
6104d5922
< 		ASTOBJ_UNREF(peer,sip_destroy_peer);
6109a5928,5932
> 	ast_mutex_unlock(&peerl.lock);
> 
> 	if (peer && peer->temponly) {
> 		destroy_peer(peer);
> 	}
6117a5941
> 	struct sip_registry *reg;
6121a5946
> 	ast_mutex_lock(&regl.lock);
6123,6128c5948,5953
< 	ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do {
< 		ASTOBJ_RDLOCK(iterator);
< 		snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : DEFAULT_SIP_PORT);
< 		ast_cli(fd, FORMAT, host, iterator->username, iterator->refresh, regstate2str(iterator->regstate));
< 		ASTOBJ_UNLOCK(iterator);
< 	} while(0));
---
> 	for (reg = regl.registrations;reg;reg = reg->next) {
> 		snprintf(host, sizeof(host), "%s:%d", reg->hostname, reg->portno ? reg->portno : DEFAULT_SIP_PORT);
> 		ast_cli(fd, FORMAT, host,
> 					reg->username, reg->refresh, regstate2str(reg->regstate));
> 	}
> 	ast_mutex_unlock(&regl.lock);
6171c5996
< 				ast_getformatname(cur->owner ? cur->owner->nativeformats : 0), ast_test_flag(cur, SIP_NEEDDESTROY) ? "(d)" : "" );
---
> 				ast_getformatname(cur->owner ? cur->owner->nativeformats : 0), cur->needdestroy ? "(d)" : "" );
6215,6260d6039
< /*--- complete_sipnotify: Support routine for 'sip notify' CLI ---*/
< static char *complete_sipnotify(char *line, char *word, int pos, int state)
< {
< 	char *c = NULL;
< 
< 	if (pos == 2) {
< 		int which = 0;
< 		char *cat;
< 
< 		/* do completion for notify type */
< 
< 		if (!notify_types)
< 			return NULL;
< 		
< 		cat = ast_category_browse(notify_types, NULL);
< 		while(cat) {
< 			if (!strncasecmp(word, cat, strlen(word))) {
< 				if (++which > state) {
< 					c = strdup(cat);
< 					break;
< 				}
< 			}
< 			cat = ast_category_browse(notify_types, cat);
< 		}
< 		return c;
< 	}
< 
< 	if (pos > 2) {
< 		int which = 0;
< 
< 		/* do completion for peer name */
< 
< 		ASTOBJ_CONTAINER_TRAVERSE(&peerl, !c, do {
< 			/* locking of the ASTOBJ is not required because I only compare the name */
< 			if (!strncasecmp(word, iterator->name, strlen(word))) {
< 				if (++which > state) {
< 					c = strdup(iterator->name);
< 				}
< 			}
< 		} while(0) );
< 		return c;
< 	}
< 
< 	return NULL;
< }
< 
6264a6044
> 	char tmp[256];
6281c6061
< 			ast_cli(fd, "  Direction:              %s\n", ast_test_flag(cur, SIP_OUTGOING)?"Outgoing":"Incoming");
---
> 			ast_cli(fd, "  Direction:              %s\n", cur->outgoing?"Outgoing":"Incoming");
6290c6070
< 			ast_cli(fd, "  NAT Support:            %s\n", nat2str(ast_test_flag(cur, SIP_NAT)));
---
> 			ast_cli(fd, "  NAT Support:            %s\n", nat2str(cur->nat));
6302c6082
< 			ast_cli(fd, "  Need Destroy:           %d\n", ast_test_flag(cur, SIP_NEEDDESTROY));
---
> 			ast_cli(fd, "  Need Destroy:           %d\n", cur->needdestroy);
6304c6084
< 			ast_cli(fd, "  Promiscuous Redir:      %s\n", ast_test_flag(cur, SIP_PROMISCREDIR) ? "Yes" : "No");
---
> 			ast_cli(fd, "  Promiscuous Redir:      %s\n", cur->promiscredir ? "Yes" : "No");
6306c6086,6093
< 			ast_cli(fd, "  DTMF Mode:              %s\n\n", dtmfmode2str(ast_test_flag(cur, SIP_DTMF)));
---
> 			tmp[0] = '\0';
> 			if (cur->dtmfmode & SIP_DTMF_RFC2833)
> 				strncat(tmp, "rfc2833 ", sizeof(tmp) - strlen(tmp) - 1);
> 			if (cur->dtmfmode & SIP_DTMF_INFO)
> 				strncat(tmp, "info ", sizeof(tmp) - strlen(tmp) - 1);
> 			if (cur->dtmfmode & SIP_DTMF_INBAND)
> 				strncat(tmp, "inband ", sizeof(tmp) - strlen(tmp) - 1);
> 			ast_cli(fd, "  DTMF Mode:              %s\n\n", tmp);
6415c6202
< 			ast_set_flag(p, SIP_NEEDDESTROY);
---
> 			p->needdestroy = 1;
6420c6207
< 		if (ast_test_flag(p, SIP_USECLIENTCODE)) {
---
> 		if (p->useclientcode) {
6478c6265,6271
< 	peer = find_peer(argv[3], NULL);
---
> 	ast_mutex_lock(&peerl.lock);
> 	for (peer = peerl.peers;peer;peer = peer->next)
> 		if (!strcmp(peer->name, argv[3])) 
> 			break;
> 	ast_mutex_unlock(&peerl.lock);
> 	if (!peer)
> 		peer = realtime_peer(argv[3], NULL);
6488c6281,6283
< 		ASTOBJ_UNREF(peer,sip_destroy_peer);
---
> 		if (peer->temponly)
> 			destroy_peer(peer);
> 		peer = NULL;
6511,6565d6305
< static int sip_notify(int fd, int argc, char *argv[])
< {
< 	struct ast_variable *varlist;
< 	int i;
< 
< 	if (argc < 4)
< 		return RESULT_SHOWUSAGE;
< 
< 	if (!notify_types) {
< 		ast_cli(fd, "No %s file found, or no types listed there\n", notify_config);
< 		return RESULT_FAILURE;
< 	}
< 
< 	varlist = ast_variable_browse(notify_types, argv[2]);
< 
< 	if (!varlist) {
< 		ast_cli(fd, "Unable to find notify type '%s'\n", argv[2]);
< 		return RESULT_FAILURE;
< 	}
< 
< 	for (i = 3; i < argc; i++) {
< 		struct sip_pvt *p;
< 		struct sip_request req;
< 		struct ast_variable *var;
< 
< 		p = sip_alloc(NULL, NULL, 0);
< 		if (!p) {
< 			ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n");
< 			return RESULT_FAILURE;
< 		}
< 
< 		if (create_addr(p, argv[i])) {
< 			/* Maybe they're not registered, etc. */
< 			sip_destroy(p);
< 			ast_cli(fd, "Could not create address fo '%s'\n", argv[i]);
< 			continue;
< 		}
< 
< 		initreqprep(&req, p, "NOTIFY", NULL);
< 
< 		for (var = varlist; var; var = var->next)
< 			add_header(&req, var->name, var->value);
< 
< 		/* Recalculate our side, and recalculate Call ID */
< 		if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
< 			memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
< 		build_via(p, p->via, sizeof(p->via));
< 		build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
< 		ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", argv[2], argv[i]);
< 		transmit_sip_request(p, &req);
< 		sip_scheddestroy(p, 15000);
< 	}
< 
< 	return RESULT_SUCCESS;
< }
6590d6329
< 
6609c6348
<  		if (sip_debug_test_pvt(p) && p->registry)
---
>  		if (sip_debug_test_pvt(p))
6614c6353
<  	if (sip_debug_test_pvt(p) && p->registry)
---
>  	if (sip_debug_test_pvt(p))
6786,6789d6524
< static char notify_usage[] =
< "Usage: sip notify <type> <peer> [<peer>...]\n"
< "       Send a NOTIFY message to a SIP peer or peers\n"
< "       Message types are defined in sip_notify.conf\n";
6792,6794c6527,6528
< "Usage: sip show users [pattern]\n"
< "       Lists all known SIP users.\n"
< "       Optional regular expression pattern is used to filter the user list.\n";
---
> "Usage: sip show users\n"
> "       Lists all users known to the SIP (Session Initiation Protocol) subsystem.\n";
6813,6815c6547,6548
< "Usage: sip show peers [pattern]\n"
< "       Lists all known SIP peers.\n"
< "       Optional regular expression pattern is used to filter the peer list.\n";
---
> "Usage: sip show peers\n"
> "       Lists all known SIP peers.\n";
6855,6862c6588
< static char show_objects_usage[] =
< "Usage: sip show objects\n" 
< "       Shows status of known SIP objects\n";
< 
< static struct ast_cli_entry  cli_notify =
< 	{ { "sip", "notify", NULL }, sip_notify, "Send a notify packet to a SIP peer", notify_usage, complete_sipnotify };
< static struct ast_cli_entry  cli_show_objects = 
< 	{ { "sip", "show", "objects", NULL }, sip_show_objects, "Show all SIP object allocations", show_objects_usage };
---
> 
6866c6592
< 	{ { "sip", "show", "subscriptions", NULL }, sip_show_subscriptions, "Show active SIP subscriptions", show_subscriptions_usage};
---
>         { { "sip", "show", "subscriptions", NULL }, sip_show_subscriptions, "Show active SIP subscriptions", show_subscriptions_usage};
6880a6607,6612
> static struct ast_cli_entry  cli_show_peers_include =
>         { { "sip", "show", "peers", "include", NULL }, sip_show_peers, "Show defined SIP peers", show_peers_usage };
> static struct ast_cli_entry  cli_show_peers_exclude =
>         { { "sip", "show", "peers", "exclude", NULL }, sip_show_peers, "Show defined SIP peers", show_peers_usage };
> static struct ast_cli_entry  cli_show_peers_begin =
>         { { "sip", "show", "peers", "begin", NULL }, sip_show_peers, "Show defined SIP peers", show_peers_usage };
6904c6636
< 	if (ast_test_flag(p, SIP_PROMISCREDIR)) {
---
> 	if (p->promiscredir) {
6928d6659
< /*--- check_pendings: Check pending actions on SIP call ---*/
6932c6663
< 	if (ast_test_flag(p, SIP_PENDINGBYE)) {
---
> 	if (p->pendingbye) {
6934,6936c6665,6667
< 		ast_set_flag(p, SIP_NEEDDESTROY);	
< 		ast_clear_flag(p, SIP_NEEDREINVITE);	
< 	} else if (ast_test_flag(p, SIP_NEEDREINVITE)) {
---
> 		p->needdestroy = 1;
> 		p->needreinvite = 0;
> 	} else if (p->needreinvite) {
6940c6671
< 		ast_clear_flag(p, SIP_NEEDREINVITE);	
---
> 		p->needreinvite = 0;
7023c6754
< 			ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 			p->needdestroy = 1;
7030c6761
< 	} else if (ast_test_flag(p, SIP_OUTGOING)) {
---
> 	} else if (p->outgoing) {
7072c6803
< 					   	ast_set_flag(p, SIP_NEEDDESTROY); 
---
> 					    p->needdestroy = 1;
7080,7084d6810
< 
< 				/* Parse contact header for continued conversation */
< 				/* When we get 200 OK, we now which device (and IP) to contact for this call */
< 				/* This is important when we have a SIP proxy between us and the phone */
< 				parse_ok_contact(p, req);
7099c6825
< 					ast_set_flag(p, SIP_PENDINGBYE);	
---
> 					p->pendingbye = 1;
7120c6846
< 					ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 					p->needdestroy = 1;
7165d6890
< 					ASTOBJ_UNREF(r, sip_registry_destroy);
7178c6903
< 					ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 					p->needdestroy = 1;
7183c6908
< 					ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 					p->needdestroy = 1;
7186c6911
< 				ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 				p->needdestroy = 1;
7195c6920
< 				ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 				p->needdestroy = 1;
7198c6923
< 				ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 				p->needdestroy = 1;
7212c6937
< 						ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 						p->needdestroy = 1;
7221c6946
< 					ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 					p->needdestroy = 1;
7226c6951
< 					ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 					p->needdestroy = 1;
7229c6954
< 				ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 				p->needdestroy = 1;
7243c6968
< 				ast_set_flag(p, SIP_ALREADYGONE);	
---
> 				p->alreadygone = 1;
7264c6989
< 					if (ast_test_flag(p, SIP_OUTGOING)) {
---
> 					if ( p->outgoing ) {
7303c7028
< 				ast_set_flag(p, SIP_ALREADYGONE);	
---
> 				p->alreadygone = 1;
7305c7030
< 					ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 					p->needdestroy = 1;
7335c7060
< 					ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 					p->needdestroy = 1;
7565c7290
< 		} else if (p->icseq && (p->icseq == seqno) && (strcasecmp(cmd, "CANCEL") || ast_test_flag(p, SIP_ALREADYGONE))) {
---
> 		} else if (p->icseq && (p->icseq == seqno) && (strcasecmp(cmd, "CANCEL") || p->alreadygone)) {
7587c7312
< 			ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 			p->needdestroy = 1;
7621c7346
< 			ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 			p->needdestroy = 1;
7623c7348
< 		if (ast_test_flag(p, SIP_OUTGOING) && p->owner && (p->owner->_state != AST_STATE_UP)) {
---
> 		if (p->outgoing && p->owner && (p->owner->_state != AST_STATE_UP)) {
7638c7363
< 			ast_clear_flag(p, SIP_OUTGOING);
---
> 			p->outgoing = 0;
7665c7390
< 					ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 					p->needdestroy = 1;
7678c7403
< 					ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 					p->needdestroy = 1;
7702c7427
< 				ast_set_flag(p, SIP_NEEDDESTROY);		
---
> 				p->needdestroy = 1;
7751c7476
< 						ast_set_flag(p, SIP_ALREADYGONE);	
---
> 						p->alreadygone = 1;
7780,7794c7505,7511
< 			if (p && !ast_test_flag(p, SIP_NEEDDESTROY)) {
< 				if (!p->jointcapability) {
< 					if (ignore)
< 						transmit_response(p, "488 Not Acceptable Here", req);
< 					else
< 						transmit_response_reliable(p, "488 Not Acceptable Here", req, 1);
< 					ast_set_flag(p, SIP_NEEDDESTROY);	
< 				} else {
< 					ast_log(LOG_NOTICE, "Unable to create/find channel\n");
< 					if (ignore)
< 						transmit_response(p, "503 Unavailable", req);
< 					else
< 						transmit_response_reliable(p, "503 Unavailable", req, 1);
< 					ast_set_flag(p, SIP_NEEDDESTROY);	
< 				}
---
> 			if (p && !p->needdestroy) {
> 				ast_log(LOG_NOTICE, "Unable to create/find channel\n");
> 				if (ignore)
> 					transmit_response(p, "503 Unavailable", req);
> 				else
> 					transmit_response_reliable(p, "503 Unavailable", req, 1);
> 				p->needdestroy = 1;
7816c7533
< 					ast_set_flag(p, SIP_GOTREFER);	
---
> 					p->gotrefer = 1;
7842c7559
< 					ast_set_flag(p, SIP_GOTREFER);	
---
> 					p->gotrefer = 1;
7849c7566
< 					ast_set_flag(p, SIP_ALREADYGONE);	
---
> 					p->alreadygone = 1;
7855c7572
< 		ast_set_flag(p, SIP_ALREADYGONE);	
---
> 		p->alreadygone = 1;
7867c7584
< 			ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 			p->needdestroy = 1;
7878c7595
< 		ast_set_flag(p, SIP_ALREADYGONE);	
---
> 		p->alreadygone = 1;
7911c7628
< 			ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 			p->needdestroy = 1;
7926c7643
< 			ast_clear_flag(p, SIP_OUTGOING);
---
> 			p->outgoing = 0;
7933a7651
> 			char rbox[256];
7935d7652
< 
7941c7658
< 					ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 					p->needdestroy = 1;
7956c7673
< 				ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 				p->needdestroy = 1;
7964,7977c7681,7682
< 
< 					/* At this point, we should check if they subscribe to a mailbox that
< 					  has the same extension as the peer or the mailbox id. If we configure
< 					  the context to be the same as a SIP domain, we could check mailbox
< 					  context as well. To be able to securely accept subscribes on mailbox
< 					  IDs, not extensions, we need to check the digest auth user to make
< 					  sure that the user has access to the mailbox.
< 					 
< 					  Since we do not act on this subscribe anyway, we might as well 
< 					  accept any authenticated peer with a mailbox definition in their 
< 					  config section.
< 					
< 					*/
< 					if (!ast_strlen_zero(mailbox)) {
---
> 					snprintf(rbox, sizeof(rbox), ",%s@%s,", p->exten, p->context);
> 					if (strstr(mailbox, rbox))
7978a7684,7687
> 					if (!found) {
> 						snprintf(rbox, sizeof(rbox), ",%s,", p->exten);
> 						if (strstr(mailbox, rbox))
> 							found++;
7980d7688
< 
7985c7693
< 						ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 						p->needdestroy = 1;
7999c7707
< 		if (p && !ast_test_flag(p, SIP_NEEDDESTROY)) {
---
> 		if (p && !p->needdestroy) {
8002c7710
< 			ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 			p->needdestroy = 1;
8026,8027c7734
< 		if (!p->lastinvite) 
< 			ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 		if (!p->lastinvite) p->needdestroy = 1;
8053c7760
< 			ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 			p->needdestroy = 1;
8068c7775
< 			ast_set_flag(p, SIP_NEEDDESTROY);	
---
> 			p->needdestroy = 1;
8149a7857
> 	char iabuf[INET_ADDRSTRLEN];
8158a7867
> 		ast_mutex_unlock(&peerl.lock);
8164a7874
> 		ast_mutex_unlock(&peerl.lock);
8168a7879
> 	ast_mutex_unlock(&peerl.lock);
8177c7888,7892
< 	build_via(p, p->via, sizeof(p->via));
---
> 	/* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
> 	if (p->nat & SIP_NAT_RFC3581)
> 		snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
> 	else /* UNIDEN UIP200 bug */
> 		snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
8180c7895
< 	ast_set_flag(p, SIP_OUTGOING);
---
> 	p->outgoing = 1;
8191c7906
< 	struct sip_peer *peer = NULL;
---
> 	struct sip_peer *peer;
8223,8229c7938,7939
< 			if (sip->rtp && sip->owner && (sip->owner->_state == AST_STATE_UP) && !sip->redirip.sin_addr.s_addr) {
< 				if (sip->lastrtptx && sip->rtpkeepalive && t > sip->lastrtptx + sip->rtpkeepalive) {
< 					/* Need to send an empty RTP packet */
< 					time(&sip->lastrtptx);
< 					ast_rtp_sendcng(sip->rtp, 0);
< 				}
< 				if (sip->lastrtprx && (sip->rtptimeout || sip->rtpholdtimeout) && t > sip->lastrtprx + sip->rtptimeout) {
---
> 			if (sip->rtp && sip->owner && (sip->owner->_state == AST_STATE_UP) && sip->lastrtprx && (sip->rtptimeout || sip->rtpholdtimeout) && !sip->redirip.sin_addr.s_addr) {
> 				if (t > sip->lastrtprx + sip->rtptimeout) {
8253c7963
< 			if (ast_test_flag(sip, SIP_NEEDDESTROY) && !sip->packets && !sip->owner) {
---
> 			if (sip->needdestroy && !sip->packets && !sip->owner) {
8284a7995,7996
> 		ast_mutex_lock(&peerl.lock);
> 		peer = peerl.peers;
8288,8290c8000,8002
< 		peer = NULL;
< 		ASTOBJ_CONTAINER_TRAVERSE(&peerl, !peer, do {
< 			if ((curpeernum > lastpeernum) && !ast_strlen_zero(iterator->mailbox) && ((t - iterator->lastmsgcheck) > global_mwitime)) {
---
> 		while(peer) {
> 			if ((curpeernum > lastpeernum) && !ast_strlen_zero(peer->mailbox) && ((t - peer->lastmsgcheck) > global_mwitime)) {
> 				sip_send_mwi_to_peer(peer);
8293,8294c8005,8006
< 				peer = ASTOBJ_REF(iterator);
< 			};
---
> 				break;
> 			}
8296,8303c8008,8011
< 		} while (0)
< 		);
< 		if (peer) {
< 			ASTOBJ_WRLOCK(peer);
< 			sip_send_mwi_to_peer(peer);
< 			ASTOBJ_UNLOCK(peer);
< 			ASTOBJ_UNREF(peer,sip_destroy_peer);
< 		} else {
---
> 			peer = peer->next;
> 		}
> 		/* Remember, sip_send_mwi_to_peer releases the lock if we've called it */
> 		if (!peer) {
8305a8014
> 			ast_mutex_unlock(&peerl.lock);
8372a8082
> 	char iabuf[INET_ADDRSTRLEN];
8408c8118,8122
< 	build_via(p, p->via, sizeof(p->via));
---
> 	/* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
> 	if (p->nat & SIP_NAT_RFC3581)
> 		snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
> 	else
> 		snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
8414c8128
< 	ast_set_flag(p, SIP_OUTGOING);
---
> 	p->outgoing = 1;
8451a8166
> 	ast_mutex_lock(&peerl.lock);
8461a8177
> 	ast_mutex_unlock(&peerl.lock);
8468,8469c8184,8186
< 	if (p)
< 		ASTOBJ_UNREF(p,sip_destroy_peer);
---
> 	if (p && p->temponly) {
> 		destroy_peer(p);
> 	}
8481a8199
> 	char iabuf[INET_ADDRSTRLEN];
8527c8245,8249
< 	build_via(p, p->via, sizeof(p->via));
---
> 	/* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
> 	if (p->nat & SIP_NAT_RFC3581)
> 		snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
> 	else /* UNIDEN bug */
> 		snprintf(p->via, sizeof(p->via), "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
8552,8627d8273
< /*--- handle_common_options: Handle flag-type options common to users and peers ---*/
< static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v)
< {
< 	int res = 0;
< 
< 	if (!strcasecmp(v->name, "trustrpid")) {
< 		ast_set_flag(mask, SIP_TRUSTRPID);
< 		ast_set2_flag(flags, ast_true(v->value), SIP_TRUSTRPID);
< 		res = 1;
< 	} else if (!strcasecmp(v->name, "useclientcode")) {
< 		ast_set_flag(mask, SIP_USECLIENTCODE);
< 		ast_set2_flag(flags, ast_true(v->value), SIP_USECLIENTCODE);
< 		res = 1;
< 	} else if (!strcasecmp(v->name, "dtmfmode")) {
< 		ast_set_flag(mask, SIP_DTMF);
< 		ast_clear_flag(flags, SIP_DTMF);
< 		if (!strcasecmp(v->value, "inband"))
< 			ast_set_flag(flags, SIP_DTMF_INBAND);
< 		else if (!strcasecmp(v->value, "rfc2833"))
< 			ast_set_flag(flags, SIP_DTMF_RFC2833);
< 		else if (!strcasecmp(v->value, "info"))
< 			ast_set_flag(flags, SIP_DTMF_INFO);
< 		else {
< 			ast_log(LOG_WARNING, "Unknown dtmf mode '%s' on line %d, using rfc2833\n", v->value, v->lineno);
< 			ast_set_flag(flags, SIP_DTMF_RFC2833);
< 		}
< 	} else if (!strcasecmp(v->name, "nat")) {
< 		ast_set_flag(mask, SIP_NAT);
< 		ast_clear_flag(flags, SIP_NAT);
< 		if (!strcasecmp(v->value, "never"))
< 			ast_set_flag(flags, SIP_NAT_NEVER);
< 		else if (!strcasecmp(v->value, "route"))
< 			ast_set_flag(flags, SIP_NAT_ROUTE);
< 		else if (ast_true(v->value))
< 			ast_set_flag(flags, SIP_NAT_ALWAYS);
< 		else
< 			ast_set_flag(flags, SIP_NAT_RFC3581);
< 	} else if (!strcasecmp(v->name, "canreinvite")) {
< 		ast_set_flag(mask, SIP_REINVITE);
< 		ast_clear_flag(flags, SIP_REINVITE);
< 		if (!strcasecmp(v->value, "update"))
< 			ast_set_flag(flags, SIP_REINVITE_UPDATE | SIP_CAN_REINVITE);
< 		else
< 			ast_set2_flag(flags, ast_true(v->value), SIP_CAN_REINVITE);
< 	} else if (!strcasecmp(v->name, "insecure")) {
< 		ast_set_flag(mask, SIP_INSECURE);
< 		ast_clear_flag(flags, SIP_INSECURE);
< 		if (!strcasecmp(v->value, "very"))
< 			ast_set_flag(flags, SIP_INSECURE_VERY);
< 		else
< 			ast_set2_flag(flags, ast_true(v->value), SIP_INSECURE_NORMAL);
< 	} else if (!strcasecmp(v->name, "progressinband")) {
< 		ast_set_flag(mask, SIP_PROG_INBAND);
< 		ast_clear_flag(flags, SIP_PROG_INBAND);
< 		if (strcasecmp(v->value, "never"))
< 			ast_set_flag(flags, SIP_PROG_INBAND_NO);
< 		else if (ast_true(v->value))
< 			ast_set_flag(flags, SIP_PROG_INBAND_YES);
< #ifdef OSP_SUPPORT
< 	} else if (!strcasecmp(v->name, "ospauth")) {
< 		ast_set_flag(mask, SIP_OSPAUTH);
< 		ast_clear_flag(flags, SIP_OSPAUTH);
< 		if (!strcasecmp(v->value, "exclusive"))
< 			ast_set_flag(flags, SIP_OSPAUTH_EXCLUSIVE);
< 		else
< 			ast_set2_flag(flags, ast_true(v->value), SIP_OSPAUTH_YES);
< #endif
< 	} else if (!strcasecmp(v->name, "promiscredir")) {
< 		ast_set_flag(mask, SIP_PROMISCREDIR);
< 		ast_set2_flag(flags, ast_true(v->value), SIP_PROMISCREDIR);
< 		res = 1;
< 	}
< 
< 	return res;
< }
< 
8629c8275
< static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime)
---
> static struct sip_user *build_user(const char *name, struct ast_variable *v)
8639,8641d8284
< 		struct ast_flags userflags = {(0)};
< 		struct ast_flags mask = {(0)};
< 
8643,8644d8285
< 		suserobjs++;
< 		ASTOBJ_INIT(user);
8651d8291
< 		ast_copy_flags(user, &global_flags, SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_USECLIENTCODE | SIP_DTMF | SIP_NAT | SIP_REINVITE | SIP_INSECURE | SIP_PROG_INBAND | SIP_OSPAUTH);
8652a8293,8296
> 		user->canreinvite = global_canreinvite;
> 		user->trustrpid = global_trustrpid;
> 		user->dtmfmode = global_dtmfmode;
> 		user->progressinband = global_progressinband;
8653a8298,8300
> #ifdef OSP_SUPPORT
> 		user->ospauth = global_ospauth;
> #endif
8659,8663d8305
< 			if (handle_common_options(&userflags, &mask, v)) {
< 				v = v->next;
< 				continue;
< 			}
< 
8683a8326,8352
> 			} else if (!strcasecmp(v->name, "promiscredir")) {
> 				user->promiscredir = ast_true(v->value);
> 			} else if (!strcasecmp(v->name, "dtmfmode")) {
> 				if (!strcasecmp(v->value, "inband"))
> 					user->dtmfmode=SIP_DTMF_INBAND;
> 				else if (!strcasecmp(v->value, "rfc2833"))
> 					user->dtmfmode = SIP_DTMF_RFC2833;
> 				else if (!strcasecmp(v->value, "info"))
> 					user->dtmfmode = SIP_DTMF_INFO;
> 				else {
> 					ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
> 					user->dtmfmode = SIP_DTMF_RFC2833;
> 				}
> 			} else if (!strcasecmp(v->name, "canreinvite")) {
> 				if (!strcasecmp(v->value, "update"))
> 					user->canreinvite = REINVITE_UPDATE;
> 				else
> 					user->canreinvite = ast_true(v->value);
> 			} else if (!strcasecmp(v->name, "nat")) {
> 				if (!strcasecmp(v->value, "never"))
> 					user->nat = SIP_NAT_NEVER;
> 				else if (!strcasecmp(v->value, "route"))
> 					user->nat = SIP_NAT_ROUTE;
> 				else if (ast_true(v->value))
> 					user->nat = SIP_NAT_ALWAYS;
> 				else
> 					user->nat = SIP_NAT_RFC3581;
8714a8384,8385
> 			} else if (!strcasecmp(v->name, "insecure")) {
> 				user->insecure = ast_true(v->value);
8716a8388,8407
> 			} else if (!strcasecmp(v->name, "trustrpid")) {
> 				user->trustrpid = ast_true(v->value);
> 			} else if (!strcasecmp(v->name, "useclientcode")) {
> 				user->useclientcode = ast_true(v->value);
> 			} else if (!strcasecmp(v->name, "progressinband")) {
> 				if (!strcasecmp(v->value, "never"))
> 					user->progressinband = 0;
> 				else if (ast_true(v->value))
> 					user->progressinband = 2;
> 				else
> 					user->progressinband = 1;
> #ifdef OSP_SUPPORT
> 			} else if (!strcasecmp(v->name, "ospauth")) {
> 				if (!strcasecmp(v->value, "exclusive")) {
> 					user->ospauth = 2;
> 				} else if (ast_true(v->value)) {
> 					user->ospauth = 1;
> 				} else
> 					user->ospauth = 0;
> #endif
8723d8413
< 		ast_copy_flags(user, &userflags, mask.flags);
8738,8740d8427
< 	apeerobjs++;
< 	ASTOBJ_INIT(peer);
< 
8744d8430
< 	ast_copy_flags(peer, &global_flags, SIP_PROMISCREDIR | SIP_USEREQPHONE | SIP_TRUSTRPID | SIP_USECLIENTCODE | SIP_DTMF | SIP_NAT | SIP_REINVITE | SIP_INSECURE | SIP_PROG_INBAND | SIP_OSPAUTH);
8751a8438,8443
> 	/* Assume can reinvite */
> 	peer->canreinvite = global_canreinvite;
> 	peer->dtmfmode = global_dtmfmode;
> 	peer->promiscredir = global_promiscredir;
> 	peer->usereqphone = global_usereqphone;
> 	peer->nat = global_nat;
8754,8756c8446,8449
< 	peer->rtpkeepalive = global_rtpkeepalive;
< 	ast_set_flag(peer, SIP_SELFDESTRUCT);
< 	ast_set_flag(peer, SIP_DYNAMIC);
---
> 	peer->selfdestruct = 1;
> 	peer->dynamic = 1;
> 	peer->trustrpid = global_trustrpid;
> 	peer->progressinband = global_progressinband;
8757a8451,8453
> #ifdef OSP_SUPPORT
> 	peer->ospauth = global_ospauth;
> #endif
8763c8459
< static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int realtime)
---
> static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int temponly)
8765c8461,8462
< 	struct sip_peer *peer = NULL;
---
> 	struct sip_peer *peer;
> 	struct sip_peer *prev;
8770,8774d8466
< 	time_t regseconds;
< 
< 	if (!realtime)
< 		/* Note we do NOT use find_peer here, to avoid realtime recursion */
< 		peer = ASTOBJ_CONTAINER_FIND_UNLINK(&peerl, name);
8775a8468,8481
> 	prev = NULL;
> 	ast_mutex_lock(&peerl.lock);
> 	if (temponly) {
> 		peer = NULL;
> 	} else {
> 		peer = peerl.peers;
> 		while(peer) {
> 			if (!strcasecmp(peer->name, name)) {	
> 				break;
> 			}
> 			prev = peer;
> 			peer = peer->next;
> 		}
> 	}
8777d8482
< 		/* Already in the list, remove it and it will be added back (or FREE'd)  */
8778a8484,8490
> 		/* Already in the list, remove it and it will be added back (or FREE'd) */
> 		if (prev) {
> 			prev->next = peer->next;
> 		} else {
> 			peerl.peers = peer->next;
> 		}
> 		ast_mutex_unlock(&peerl.lock);
8779a8492
> 		ast_mutex_unlock(&peerl.lock);
8783,8787d8495
< 			if (realtime)
< 				rpeerobjs++;
< 			else
< 				speerobjs++;
< 			ASTOBJ_INIT(peer);
8792d8499
< 	/* Note that our peer HAS had its reference count incrased */
8794,8796d8500
< 		struct ast_flags peerflags = {(0)};
< 		struct ast_flags mask = {(0)};
< 
8808c8512
< 			ast_copy_flags(peer, &global_flags, SIP_USEREQPHONE);
---
> 			peer->usereqphone = global_usereqphone;
8814d8517
< 		ast_copy_flags(peer, &global_flags, SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_USECLIENTCODE | SIP_DTMF | SIP_REINVITE | SIP_INSECURE | SIP_PROG_INBAND | SIP_OSPAUTH);
8815a8519,8520
> 		/* Assume can reinvite */
> 		peer->canreinvite = global_canreinvite;
8817a8523,8529
> 		peer->dtmfmode = global_dtmfmode;
> 		peer->promiscredir = global_promiscredir;
> 		peer->trustrpid = global_trustrpid;
> 		peer->progressinband = global_progressinband;
> #ifdef OSP_SUPPORT
> 		peer->ospauth = global_ospauth;
> #endif
8819,8829c8531
< 			if (handle_common_options(&peerflags, &mask, v)) {
< 				v = v->next;
< 				continue;
< 			}
< 
< 			if (realtime && !strcasecmp(v->name, "regseconds")) {
< 				if (sscanf(v->value, "%li", &regseconds) != 1)
< 					regseconds = 0;
< 			} else if (realtime && !strcasecmp(v->name, "ipaddr")) {
< 				inet_aton(v->value, &(peer->addr.sin_addr));
< 			} else if (realtime && !strcasecmp(v->name, "name"))
---
> 			if (!strcasecmp(v->name, "name"))
8835c8537,8542
< 			else if (!strcasecmp(v->name, "callerid")) {
---
> 			else if (!strcasecmp(v->name, "canreinvite")) {
> 				if (!strcasecmp(v->value, "update"))
> 					peer->canreinvite = REINVITE_UPDATE;
> 				else
> 					peer->canreinvite = ast_true(v->value);
> 			} else if (!strcasecmp(v->name, "callerid")) {
8836a8544,8552
> 			} else if (!strcasecmp(v->name, "nat")) {
> 				if (!strcasecmp(v->value, "rfc3581"))
> 					peer->nat = SIP_NAT_RFC3581;
> 				else if (!strcasecmp(v->value, "route")) 
> 					peer->nat = SIP_NAT_ROUTE;
> 				else if (ast_true(v->value))
> 					peer->nat = SIP_NAT_ALWAYS;
> 				else
> 					peer->nat = SIP_NAT_NEVER;
8842c8558,8560
< 				ast_set2_flag(peer, ast_true(v->value), SIP_USEREQPHONE);
---
> 				peer->usereqphone = ast_true(v->value);
> 			else if (!strcasecmp(v->name, "promiscredir"))
> 				peer->promiscredir = ast_true(v->value);
8845c8563,8574
< 			else if (!strcasecmp(v->name, "host") || !strcasecmp(v->name, "outboundproxy")) {
---
>             else if (!strcasecmp(v->name, "dtmfmode")) {
> 				if (!strcasecmp(v->value, "inband"))
> 					peer->dtmfmode=SIP_DTMF_INBAND;
> 				else if (!strcasecmp(v->value, "rfc2833"))
> 					peer->dtmfmode = SIP_DTMF_RFC2833;
> 				else if (!strcasecmp(v->value, "info"))
> 					peer->dtmfmode = SIP_DTMF_INFO;
> 				else {
> 					ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
> 					peer->dtmfmode = SIP_DTMF_RFC2833;
> 				}
> 			} else if (!strcasecmp(v->name, "host") || !strcasecmp(v->name, "outboundproxy")) {
8851c8580
< 						ast_set_flag(peer, SIP_DYNAMIC);
---
> 						peer->dynamic = 1;
8868c8597
< 					ast_clear_flag(peer, SIP_DYNAMIC);	
---
> 					peer->dynamic = 0;
8871c8600
< 							ASTOBJ_UNREF(peer, sip_destroy_peer);
---
> 							destroy_peer(peer);
8884c8613
< 					ASTOBJ_UNREF(peer, sip_destroy_peer);
---
> 					destroy_peer(peer);
8894c8623
< 				if (!realtime && ast_test_flag(peer, SIP_DYNAMIC))
---
> 				if (peer->dynamic)
8915a8645,8651
> 			} else if (!strcasecmp(v->name, "insecure")) {
> 				if (!strcasecmp(v->value, "very")) {
> 					peer->insecure = 2;
> 				} else if (ast_true(v->value))
> 					peer->insecure = 1;
> 				else
> 					peer->insecure = 0;
8926,8930d8661
< 			} else if (!strcasecmp(v->name, "rtpkeepalive")) {
< 				if ((sscanf(v->value, "%d", &peer->rtpkeepalive) != 1) || (peer->rtpkeepalive < 0)) {
< 					ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d.  Using default.\n", v->value, v->lineno);
< 					peer->rtpkeepalive = global_rtpkeepalive;
< 				}
8939a8671,8690
> 			} else if (!strcasecmp(v->name, "useclientcode")) {
> 				peer->useclientcode = ast_true(v->value);
> 			} else if (!strcasecmp(v->name, "trustrpid")) {
> 				peer->trustrpid = ast_true(v->value);
> 			} else if (!strcasecmp(v->name, "progressinband")) {
> 				if (!strcasecmp(v->value, "never"))
> 					peer->progressinband = 0;
> 				else if (ast_true(v->value))
> 					peer->progressinband = 2;
> 				else
> 					peer->progressinband = 1;
> #ifdef OSP_SUPPORT
> 			} else if (!strcasecmp(v->name, "ospauth")) {
> 				if (!strcasecmp(v->value, "exclusive")) {
> 					peer->ospauth = 2;
> 				} else if (ast_true(v->value)) {
> 					peer->ospauth = 1;
> 				} else
> 					peer->ospauth = 0;
> #endif
8946,8957c8697
< 		if (realtime && ast_test_flag(peer, SIP_DYNAMIC)) {
< 			time_t nowtime;
< 
< 			time(&nowtime);
< 			if ((nowtime - regseconds) > 0) {
< 				memset(&peer->addr, 0, sizeof(peer->addr));
< 				if (option_debug)
< 					ast_log(LOG_DEBUG, "Bah, we're expired (%ld/%ld/%ld)!\n", nowtime - regseconds, regseconds, nowtime);
< 			}
< 		}
< 		ast_copy_flags(peer, &peerflags, mask.flags);
< 		if (!found && ast_test_flag(peer, SIP_DYNAMIC))
---
> 		if (!found && peer->dynamic)
8959c8699
< 		ASTOBJ_UNMARK(peer);
---
> 		peer->delme = 0;
8984c8724
< 	struct ast_flags dummy;
---
> 
9005a8746
> 	global_nat = SIP_NAT_RFC3581;
9009,9011d8749
< 	externhost[0] = '\0';
< 	externexpire = 0;
< 	externrefresh = 10;
9019a8758
> 	global_canreinvite = REINVITE_INVITE;
9026d8764
< 	global_rtpkeepalive = 0;
9028,9031c8766,8769
< 	ast_clear_flag(&global_flags, AST_FLAGS_ALL);
< 	ast_set_flag(&global_flags, SIP_DTMF_RFC2833);
< 	ast_set_flag(&global_flags, SIP_NAT_RFC3581);
< 	ast_set_flag(&global_flags, SIP_CAN_REINVITE);
---
> 	global_dtmfmode = SIP_DTMF_RFC2833;
> 	global_promiscredir = 0;
> 	global_trustrpid = 0;
> 	global_progressinband = 0;
9038d8775
< 	global_allowguest = 1;
9039a8777,8780
> #ifdef OSP_SUPPORT
> 	global_ospauth = 0;		/* OSP = Open Settlement Protocol */
> #endif
> 	
9043,9047d8783
< 		if (handle_common_options(&global_flags, &dummy, v)) {
< 			v = v->next;
< 			continue;
< 		}
< 
9059c8795
< 			ast_set2_flag((&global_flags), ast_true(v->value), SIP_USEREQPHONE);	
---
> 			global_usereqphone = ast_true(v->value);
9061a8798,8810
> 		} else if (!strcasecmp(v->name, "promiscredir")) {
> 			global_promiscredir = ast_true(v->value);
> 		} else if (!strcasecmp(v->name, "dtmfmode")) {
> 			if (!strcasecmp(v->value, "inband"))
> 				global_dtmfmode=SIP_DTMF_INBAND;
> 			else if (!strcasecmp(v->value, "rfc2833"))
> 				global_dtmfmode = SIP_DTMF_RFC2833;
> 			else if (!strcasecmp(v->value, "info"))
> 				global_dtmfmode = SIP_DTMF_INFO;
> 			else {
> 				ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
> 				global_dtmfmode = SIP_DTMF_RFC2833;
> 			}
9077,9081d8825
< 		} else if (!strcasecmp(v->name, "rtpkeepalive")) {
< 			if ((sscanf(v->value, "%d", &global_rtpkeepalive) != 1) || (global_rtpkeepalive < 0)) {
< 				ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d.  Using default.\n", v->value, v->lineno);
< 				global_rtpkeepalive = 0;
< 			}
9100a8845,8853
> 		} else if (!strcasecmp(v->name, "nat")) {
> 			if (!strcasecmp(v->value, "rfc3581"))
> 				global_nat = SIP_NAT_RFC3581;
> 			else if (!strcasecmp(v->value, "route"))
> 				global_nat = SIP_NAT_ROUTE;
> 			else if (ast_true(v->value))
> 				global_nat = SIP_NAT_ALWAYS;
> 			else
> 				global_nat = SIP_NAT_NEVER;
9111a8865,8882
> 		} else if (!strcasecmp(v->name, "trustrpid")) {
> 			global_trustrpid = ast_true(v->value);
> 		} else if (!strcasecmp(v->name, "progressinband")) {
> 			if (!strcasecmp(v->value, "never"))
> 				global_progressinband = 0;
> 			else if (ast_true(v->value))
> 				global_progressinband = 2;
> 			else
> 				global_progressinband = 1;
> #ifdef OSP_SUPPORT
> 		} else if (!strcasecmp(v->name, "ospauth")) {
> 			if (!strcasecmp(v->value, "exclusive")) {
> 				global_ospauth = 2;
> 			} else if (ast_true(v->value)) {
> 				global_ospauth = 1;
> 			} else
> 				global_ospauth = 0;
> #endif
9113a8885,8889
> 		} else if (!strcasecmp(v->name, "canreinvite")) {
> 			if (!strcasecmp(v->value, "update"))
> 				global_canreinvite = REINVITE_UPDATE;
> 			else
> 				global_canreinvite = ast_true(v->value);
9145,9157d8920
< 			externexpire = 0;
< 		} else if (!strcasecmp(v->name, "externhost")) {
< 			strncpy(externhost, v->value, sizeof(externhost) - 1);
< 			if (!(hp = ast_gethostbyname(externhost, &ahp))) 
< 				ast_log(LOG_WARNING, "Invalid address for externhost keyword: %s\n", externhost);
< 			else
< 				memcpy(&externip.sin_addr, hp->h_addr, sizeof(externip.sin_addr));
< 			time(&externexpire);
< 		} else if (!strcasecmp(v->name, "externrefresh")) {
< 			if (sscanf(v->value, "%i", &externrefresh) != 1) {
< 				ast_log(LOG_WARNING, "Invalid externrefresh value '%s', must be an integer >0 at line %d\n", v->value, v->lineno);
< 				externrefresh = 10;
< 			}
9201c8964
< 					user = build_user(cat, ast_variable_browse(cfg, cat), 0);
---
> 					user = build_user(cat, ast_variable_browse(cfg, cat));
9203,9204c8966,8969
< 						ASTOBJ_CONTAINER_LINK(&userl,user);
< 						ASTOBJ_UNREF(user, sip_destroy_user);
---
> 						ast_mutex_lock(&userl.lock);
> 						user->next = userl.users;
> 						userl.users = user;
> 						ast_mutex_unlock(&userl.lock);
9210,9211c8975,8978
< 						ASTOBJ_CONTAINER_LINK(&peerl,peer);
< 						ASTOBJ_UNREF(peer, sip_destroy_peer);
---
> 						ast_mutex_lock(&peerl.lock);
> 						peer->next = peerl.peers;
> 						peerl.peers = peer;
> 						ast_mutex_unlock(&peerl.lock);
9276,9281d9042
< 
< 	/* Load the list of manual NOTIFY types to support */
< 	if (notify_types)
< 		ast_destroy(notify_types);
< 	notify_types = ast_load(notify_config);
< 
9285d9045
< /*--- sip_get_rtp_peer: Returns null if we can't reinvite */
9293c9053
< 		if (p->rtp && ast_test_flag(p, SIP_CAN_REINVITE))
---
> 		if (p->rtp && p->canreinvite)
9307c9067
< 		if (p->vrtp && ast_test_flag(p, SIP_CAN_REINVITE))
---
> 		if (p->vrtp && p->canreinvite)
9314d9073
< /*--- sip_set_rtp_peer: Set the RTP peer for this call ---*/
9330c9089
< 		if (!ast_test_flag(p, SIP_GOTREFER)) {
---
> 		if (!p->gotrefer) {
9333c9092
< 			else if (!ast_test_flag(p, SIP_PENDINGBYE)) {
---
> 			else if (!p->pendingbye) {
9335c9094
< 				ast_set_flag(p, SIP_NEEDREINVITE);	
---
> 				p->needreinvite = 1;
9340d9098
< 		time(&p->lastrtptx);
9393,9404c9151,9156
< 		if (!strcasecmp(mode,"info")) {
< 			ast_clear_flag(p, SIP_DTMF);
< 			ast_set_flag(p, SIP_DTMF_INFO);
< 		}
< 		else if (!strcasecmp(mode,"rfc2833")) {
< 			ast_clear_flag(p, SIP_DTMF);
< 			ast_set_flag(p, SIP_DTMF_RFC2833);
< 		}
< 		else if (!strcasecmp(mode,"inband")) { 
< 			ast_clear_flag(p, SIP_DTMF);
< 			ast_set_flag(p, SIP_DTMF_INBAND);
< 		}
---
> 		if (!strcasecmp(mode,"info"))
> 			p->dtmfmode = SIP_DTMF_INFO;
> 		else if (!strcasecmp(mode,"rfc2833"))
> 			p->dtmfmode = SIP_DTMF_RFC2833;
> 		else if (!strcasecmp(mode,"inband"))
> 			p->dtmfmode = SIP_DTMF_INBAND;
9407,9412c9159,9164
< 		if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) {
< 			if (!p->vad) {
< 				p->vad = ast_dsp_new();
< 				ast_dsp_set_features(p->vad, DSP_FEATURE_DTMF_DETECT);
< 			}
< 		} else {
---
>         if (p->dtmfmode & SIP_DTMF_INBAND) {
> 				if (!p->vad) {
> 	               p->vad = ast_dsp_new();
> 	               ast_dsp_set_features(p->vad, DSP_FEATURE_DTMF_DETECT);
> 				}
>         } else {
9509d9260
< /*--- sip_get_codec: Return peers codec ---*/
9516d9266
< /*--- sip_rtp: Interface structure with callbacks used to connect to rtp module --*/
9527a9278,9281
> 	struct sip_user *user, *userlast;
> 	struct sip_peer *peer;
> 	struct sip_registry *reg, *regn;
> 
9529,9531c9283,9318
< 	ASTOBJ_CONTAINER_DESTROYALL(&userl,sip_destroy_user);
< 	ASTOBJ_CONTAINER_DESTROYALL(&regl,sip_registry_destroy);
< 	ASTOBJ_CONTAINER_MARKALL(&peerl);
---
> 	ast_mutex_lock(&userl.lock);
> 	for (user=userl.users;user;) {
> 		userlast = user;
> 		user=user->next;
> 		destroy_user(userlast);
> 	}
> 	userl.users=NULL;
> 	ast_mutex_unlock(&userl.lock);
> 
> 	ast_mutex_lock(&regl.lock);
> 	for (reg = regl.registrations;reg;) {
> 		regn = reg->next;
> 		/* Really delete */
> 		if (reg->call) {
> 			/* Clear registry before destroying to ensure
> 			   we don't get reentered trying to grab the registry lock */
> 			reg->call->registry = NULL;
> 			sip_destroy(reg->call);
> 		}
> 		if (reg->expire > -1)
> 			ast_sched_del(sched, reg->expire);
> 		if (reg->timeout > -1)
> 			ast_sched_del(sched, reg->timeout);
> 		free(reg);
> 		reg = regn;
> 	}
> 	regl.registrations = NULL;
> 	ast_mutex_unlock(&regl.lock);
> 	
> 	ast_mutex_lock(&peerl.lock);
> 	for (peer=peerl.peers;peer;) {
> 		/* Assume all will be deleted, and we'll find out for sure later */
> 		peer->delme = 1;
> 		peer = peer->next;
> 	}
> 	ast_mutex_unlock(&peerl.lock);
9538,9560c9325,9340
< 	ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl,sip_destroy_peer);
< }
< 
< /*--- sip_poke_all_peers: Send a poke to all known peers */
< static void sip_poke_all_peers(void)
< {
< 	ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
< 		ASTOBJ_WRLOCK(iterator);
< 		sip_poke_peer(iterator);
< 		ASTOBJ_UNLOCK(iterator);
< 	} while (0)
< 	);
< }
< 
< /*--- sip_send_all_registers: Send all known registrations */
< static void sip_send_all_registers(void)
< {
< 	ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do {
< 		ASTOBJ_WRLOCK(iterator);
< 		__sip_do_register(iterator);
< 		ASTOBJ_UNLOCK(iterator);
< 	} while (0)
< 	);
---
> 	struct sip_peer *peer, *peerlast, *peernext;
> 	ast_mutex_lock(&peerl.lock);
> 	peerlast = NULL;
> 	for (peer=peerl.peers;peer;) {
> 		peernext = peer->next;
> 		if (peer->delme) {
> 			destroy_peer(peer);
> 			if (peerlast)
> 				peerlast->next = peernext;
> 			else
> 				peerl.peers = peernext;
> 		} else
> 			peerlast = peer;
> 		peer=peernext;
> 	}
> 	ast_mutex_unlock(&peerl.lock);
9565a9346,9347
> 	struct sip_registry *reg;
> 	struct sip_peer *peer;
9569,9570c9351,9359
< 	sip_poke_all_peers();
< 	sip_send_all_registers();
---
> 	/* And start the monitor for the first time */
> 	ast_mutex_lock(&regl.lock);
> 	for (reg = regl.registrations; reg; reg = reg->next) 
> 		__sip_do_register(reg);
> 	ast_mutex_unlock(&regl.lock);
> 	ast_mutex_lock(&peerl.lock);
> 	for (peer = peerl.peers; peer; peer = peer->next)
> 		sip_poke_peer(peer);
> 	ast_mutex_unlock(&peerl.lock);
9600a9390,9391
> 	struct sip_peer *peer;
> 	struct sip_registry *reg;
9602,9604c9393,9395
< 	ASTOBJ_CONTAINER_INIT(&userl);
< 	ASTOBJ_CONTAINER_INIT(&peerl);
< 	ASTOBJ_CONTAINER_INIT(&regl);
---
> 	ast_mutex_init(&userl.lock);
> 	ast_mutex_init(&peerl.lock);
> 	ast_mutex_init(&regl.lock);
9622d9412
< 		ast_cli_register(&cli_notify);
9624d9413
< 		ast_cli_register(&cli_show_objects);
9630a9420,9422
> 		ast_cli_register(&cli_show_peers_begin);
> 		ast_cli_register(&cli_show_peers_include);
> 		ast_cli_register(&cli_show_peers_exclude);
9645,9646c9437,9445
< 		sip_poke_all_peers();
< 		sip_send_all_registers();
---
> 		ast_mutex_lock(&peerl.lock);
> 		for (peer = peerl.peers; peer; peer = peer->next)
> 			sip_poke_peer(peer);
> 		ast_mutex_unlock(&peerl.lock);
> 
> 		ast_mutex_lock(&regl.lock);
> 		for (reg = regl.registrations; reg; reg = reg->next) 
> 			__sip_do_register(reg);
> 		ast_mutex_unlock(&regl.lock);
9662d9460
< 	ast_cli_unregister(&cli_notify);
9664d9461
< 	ast_cli_unregister(&cli_show_objects);
9669a9467,9469
> 	ast_cli_unregister(&cli_show_peers_include);
> 	ast_cli_unregister(&cli_show_peers_exclude);
> 	ast_cli_unregister(&cli_show_peers_begin);
9731,9733c9531,9533
< 	ASTOBJ_CONTAINER_DESTROY(&userl);
< 	ASTOBJ_CONTAINER_DESTROY(&peerl);
< 	ASTOBJ_CONTAINER_DESTROY(&regl);
---
> 	ast_mutex_destroy(&userl.lock);
> 	ast_mutex_destroy(&peerl.lock);
> 	ast_mutex_destroy(&regl.lock);
