Index: chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.574
diff -u -r1.574 chan_sip.c
--- chan_sip.c	22 Nov 2004 05:03:03 -0000	1.574
+++ chan_sip.c	23 Nov 2004 09:28:48 -0000
@@ -247,6 +247,13 @@
 	struct sip_history *next;
 };
 
+/* sip_drings: Incoming distinctive ring information */
+struct sip_drings {
+        char alert_info[3][AST_MAX_EXTENSION];
+        char context[3][AST_MAX_EXTENSION];
+};
+static struct sip_drings drings;
+
 /* sip_pvt: PVT structures are used for each SIP conversation, ie. a call  */
 static struct sip_pvt {
 	ast_mutex_t lock;			/* Channel private lock */
@@ -302,6 +309,7 @@
 	char language[MAX_LANGUAGE];		/* Default language for this call */
 	char musicclass[MAX_LANGUAGE];          /* Music on Hold class */
 	char rdnis[256];			/* Referring DNIS */
+	char alert_info[256];			/* Contents of the Alert-Info header for this call */
 	char theirtag[256];			/* Their tag */
 	char username[256];
 	char peername[256];
@@ -411,6 +419,7 @@
 	int progressinband;
 	struct ast_ha *ha;		/* ACL setting */
 	int temponly;			/* Flag for temporary users (realtime) */
+	struct sip_drings drings;	/* Distinctive Ring info for this user */
 	struct ast_variable *vars;
 	struct sip_user *next;
 };
@@ -470,6 +479,7 @@
 	int selfdestruct;
 	int lastmsg;
 	int temponly;
+	struct sip_drings drings;	/* Distinctive Ring info for this peer */
 	struct sip_peer *next;
 };
 
@@ -5267,6 +5277,25 @@
 }
 
 
+/*--- sip_get_dring_context: Look up distinctive ring context based on alert_info ---*/
+static char *sip_get_dring_context(struct sip_drings *my_drings, char *alert_info) {
+	int i;
+	char *ret = NULL;
+
+	if (!ast_strlen_zero(alert_info)) {
+		for (i = 0; i < 3; i++) {
+			if (ast_strlen_zero(my_drings->alert_info[i]) || ast_strlen_zero(my_drings->context[i]))
+				continue;
+			if (!strncmp(my_drings->alert_info[i], alert_info, strlen(my_drings->alert_info[i]))) {
+				ret = my_drings->context[i];
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
+
 /*--- check_user: Check if matching user or peer is defined ---*/
 static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd, char *uri, int reliable, struct sockaddr_in *sin, int ignore, char *mailbox, int mailboxlen)
 {
@@ -5274,6 +5303,7 @@
 	struct sip_peer *peer;
 	char *of, from[256] = "", *c;
 	char *rpid,rpid_num[50];
+	char *dcontext;
 	char iabuf[INET_ADDRSTRLEN];
 	int res = 0;
 	char *t;
@@ -5361,6 +5391,9 @@
 			sip_cancel_destroy(p);
 			if (!ast_strlen_zero(user->context))
 				strncpy(p->context, user->context, sizeof(p->context) - 1);
+			/* See if we have a user Distinctive Ring context */
+			if (NULL != (dcontext = sip_get_dring_context(&user->drings, p->alert_info)))
+				strncpy(p->context, dcontext, sizeof(p->context) - 1);
 			if (!ast_strlen_zero(user->cid_num) && !ast_strlen_zero(p->cid_num))  {
 				strncpy(p->cid_num, user->cid_num, sizeof(p->cid_num) - 1);
 				ast_shrink_phone_number(p->cid_num);
@@ -5466,6 +5499,9 @@
 				strncpy(p->fullcontact, peer->fullcontact, sizeof(p->fullcontact) - 1);
 				if (!ast_strlen_zero(peer->context))
 					strncpy(p->context, peer->context, sizeof(p->context) - 1);
+				/* See if we have a peer Distinctive Ring context */
+				if (NULL != (dcontext = sip_get_dring_context(&peer->drings, p->alert_info)))
+					strncpy(p->context, dcontext, sizeof(p->context) - 1);
 				strncpy(p->peersecret, peer->secret, sizeof(p->peersecret) - 1);
 				strncpy(p->peermd5secret, peer->md5secret, sizeof(p->peermd5secret) - 1);
 				strncpy(p->language, peer->language, sizeof(p->language)  -1);
@@ -5834,6 +5870,12 @@
 		ast_cli(fd, "%s\n",status);
  		ast_cli(fd, "  Useragent    : %s\n", peer->useragent);
  		ast_cli(fd, "  Full Contact : %s\n", peer->fullcontact);
+		ast_cli(fd, "  DR1 Alrt-Nfo : %s\n", peer->drings.alert_info[0]);
+		ast_cli(fd, "  DR1 Context  : %s\n", peer->drings.context[0]);
+		ast_cli(fd, "  DR2 Alrt-Nfo : %s\n", peer->drings.alert_info[1]);
+		ast_cli(fd, "  DR2 Context  : %s\n", peer->drings.context[1]);
+		ast_cli(fd, "  DR3 Alrt-Nfo : %s\n", peer->drings.alert_info[2]);
+		ast_cli(fd, "  DR3 Context  : %s\n", peer->drings.context[2]);
 		ast_cli(fd,"\n");
 	} else {
 		ast_cli(fd,"Peer %s not found.\n", argv[3]);
@@ -7122,6 +7164,7 @@
 	char *from;
 	char *e;
 	char *useragent;
+	char *alert_info;
 	struct ast_channel *c=NULL;
 	struct ast_channel *transfer_to;
 	int seqno;
@@ -7160,6 +7203,10 @@
 	useragent = get_header(req, "User-Agent");
 	strncpy(p->useragent, useragent, sizeof(p->useragent)-1);
 
+	/* Save Distinctive Ring information (Alert-Info header) */
+	alert_info = get_header(req, "Alert-Info");
+	if (!ast_strlen_zero(alert_info))
+		strncpy(p->alert_info, alert_info, sizeof(p->alert_info) - 1);
 	
 	if (strcasecmp(cmd, "SIP/2.0")) {
 		/* Request coming in */			
@@ -8155,6 +8202,7 @@
 {
 	struct sip_user *user;
 	int format;
+	int i;
 	struct ast_ha *oldha = NULL;
 	char *varname = NULL, *varval = NULL;
 	struct ast_variable *tmpvar = NULL;
@@ -8178,6 +8226,11 @@
 #endif
 		/* set default context */
 		strncpy(user->context, default_context, sizeof(user->context)-1);
+		/* set default distinctive ring contexts */
+		for (i = 0; i < 3; i++) {
+			strncpy(user->drings.alert_info[i], drings.alert_info[i], sizeof(user->drings.alert_info[i])-1);
+			strncpy(user->drings.context[i], drings.context[i], sizeof(user->drings.context[i])-1);
+		}
 		strncpy(user->language, default_language, sizeof(user->language)-1);
 		strncpy(user->musicclass, global_musicclass, sizeof(user->musicclass)-1);
 		while(v) {
@@ -8291,6 +8344,18 @@
 				} else
 					user->ospauth = 0;
 #endif
+			} else if (!strcasecmp(v->name, "dring1context")) {
+				strncpy(user->drings.context[0], v->value,sizeof(user->drings.context[0])-1);
+			} else if (!strcasecmp(v->name, "dring2context")) {
+				strncpy(user->drings.context[1], v->value,sizeof(user->drings.context[1])-1);
+			} else if (!strcasecmp(v->name, "dring3context")) {
+				strncpy(user->drings.context[2], v->value,sizeof(user->drings.context[2])-1);
+			} else if (!strcasecmp(v->name, "dring1")) {
+				strncpy(user->drings.alert_info[0],v->value,sizeof(user->drings.alert_info[0])-1);
+			} else if (!strcasecmp(v->name, "dring2")) {
+				strncpy(user->drings.alert_info[1],v->value,sizeof(user->drings.alert_info[1])-1);
+			} else if (!strcasecmp(v->name, "dring3")) {
+				strncpy(user->drings.alert_info[2],v->value,sizeof(user->drings.alert_info[2])-1);
 			}
 			/*else if (strcasecmp(v->name,"type"))
 			 *	ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
@@ -8347,6 +8412,7 @@
 	int maskfound=0;
 	int format;
 	int found=0;
+	int i;
 
 	prev = NULL;
 	ast_mutex_lock(&peerl.lock);
@@ -8407,6 +8473,11 @@
 #ifdef OSP_SUPPORT
 		peer->ospauth = global_ospauth;
 #endif
+		/* set default distinctive ring contexts */
+		for (i = 0; i < 3; i++) {
+			strncpy(peer->drings.alert_info[i], drings.alert_info[i], sizeof(peer->drings.alert_info[i])-1);
+			strncpy(peer->drings.context[i], drings.context[i], sizeof(peer->drings.context[i])-1);
+		}
 		while(v) {
 			if (!strcasecmp(v->name, "secret")) 
 				strncpy(peer->secret, v->value, sizeof(peer->secret)-1);
@@ -8563,6 +8634,18 @@
 				} else
 					peer->ospauth = 0;
 #endif
+			} else if (!strcasecmp(v->name, "dring1context")) {
+				strncpy(peer->drings.context[0], v->value,sizeof(peer->drings.context[0])-1);
+			} else if (!strcasecmp(v->name, "dring2context")) {
+				strncpy(peer->drings.context[1], v->value,sizeof(peer->drings.context[1])-1);
+			} else if (!strcasecmp(v->name, "dring3context")) {
+				strncpy(peer->drings.context[2], v->value,sizeof(peer->drings.context[2])-1);
+			} else if (!strcasecmp(v->name, "dring1")) {
+				strncpy(peer->drings.alert_info[0], v->value,sizeof(peer->drings.alert_info[0])-1);
+			} else if (!strcasecmp(v->name, "dring2")) {
+				strncpy(peer->drings.alert_info[1], v->value,sizeof(peer->drings.alert_info[1])-1);
+			} else if (!strcasecmp(v->name, "dring3")) {
+				strncpy(peer->drings.alert_info[2], v->value,sizeof(peer->drings.alert_info[2])-1);
 			}
 			/* else if (strcasecmp(v->name,"type"))
 			 *	ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
@@ -8595,6 +8678,7 @@
 	struct hostent *hp;
 	int format;
 	int oldport = ntohs(bindaddr.sin_port);
+	int i;
 	char iabuf[INET_ADDRSTRLEN];
 
 	
@@ -8645,6 +8729,10 @@
 	regcontext[0] = '\0';
 	tos = 0;
 	expiry = DEFAULT_EXPIRY;
+	for (i = 0; i < 3; i++) {
+		drings.alert_info[i][0] = '\0';
+		drings.context[i][0] = '\0';
+	}
 
 #ifdef OSP_SUPPORT
 	global_ospauth = 0;		/* OSP = Open Settlement Protocol */
@@ -8816,6 +8904,18 @@
 			} else {
 				ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
 			}
+		} else if (!strcasecmp(v->name, "dring1context")) {
+			strncpy(drings.context[0], v->value,sizeof(drings.context[0])-1);
+		} else if (!strcasecmp(v->name, "dring2context")) {
+			strncpy(drings.context[1], v->value,sizeof(drings.context[1])-1);
+		} else if (!strcasecmp(v->name, "dring3context")) {
+			strncpy(drings.context[2], v->value,sizeof(drings.context[2])-1);
+		} else if (!strcasecmp(v->name, "dring1")) {
+			strncpy(drings.alert_info[0], v->value,sizeof(drings.alert_info[0])-1);
+		} else if (!strcasecmp(v->name, "dring2")) {
+			strncpy(drings.alert_info[1], v->value,sizeof(drings.alert_info[1])-1);
+		} else if (!strcasecmp(v->name, "dring3")) {
+			strncpy(drings.alert_info[2], v->value,sizeof(drings.alert_info[2])-1);
 		}
 		/* else if (strcasecmp(v->name,"type"))
 		 *	ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
