[asterisk-commits] branch oej/subscribemwi r9118 - /team/oej/subscribemwi/channels/chan_sip.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Thu Feb 2 14:26:59 MST 2006


Author: oej
Date: Thu Feb  2 15:26:56 2006
New Revision: 9118

URL: http://svn.digium.com/view/asterisk?rev=9118&view=rev
Log:
Playing around with subscription of MWI notification to support AVM ATAs

Modified:
    team/oej/subscribemwi/channels/chan_sip.c

Modified: team/oej/subscribemwi/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/subscribemwi/channels/chan_sip.c?rev=9118&r1=9117&r2=9118&view=diff
==============================================================================
--- team/oej/subscribemwi/channels/chan_sip.c (original)
+++ team/oej/subscribemwi/channels/chan_sip.c Thu Feb  2 15:26:56 2006
@@ -177,7 +177,8 @@
 	XPIDF_XML,
 	DIALOG_INFO_XML,
 	CPIM_PIDF_XML,
-	PIDF_XML
+	PIDF_XML,
+	MWI_NOTIFICATION
 };
 
 static const struct cfsubscription_types {
@@ -191,7 +192,8 @@
 	{ DIALOG_INFO_XML, "dialog",   "application/dialog-info+xml", "dialog-info+xml" },
 	{ CPIM_PIDF_XML,   "presence", "application/cpim-pidf+xml",   "cpim-pidf+xml" },  /* RFC 3863 */
 	{ PIDF_XML,        "presence", "application/pidf+xml",        "pidf+xml" },       /* RFC 3863 */
-	{ XPIDF_XML,       "presence", "application/xpidf+xml",       "xpidf+xml" }       /* Pre-RFC 3863 with MS additions */
+	{ XPIDF_XML,       "presence", "application/xpidf+xml",       "xpidf+xml" },       /* Pre-RFC 3863 with MS additions */
+	{ MWI_NOTIFICATION,	"message-summary", "application/simple-message-summary", "mwi" } /* Mailbox notification */
 };
 
 enum sipmethod {
@@ -821,6 +823,7 @@
 	struct sockaddr_in defaddr;	/*!<  Default IP address, used until registration */
 	struct ast_ha *ha;		/*!<  Access control list */
 	struct ast_variable *chanvars;	/*!<  Variables to set for channel created by user */
+	struct sip_pvt *mwipvt;		/*!<  Subscription for MWI */
 	int lastmsg;
 };
 
@@ -968,6 +971,7 @@
 static int restart_monitor(void);
 static void set_peer_defaults(struct sip_peer *peer);
 static struct sip_peer *temp_peer(const char *name);
+static int sip_send_mwi_to_peer(struct sip_peer *peer);
 
 
 /*----- RTP interface functions */
@@ -2161,7 +2165,6 @@
 
 	if (sip_debug_test_pvt(p) || option_debug > 2)
 		ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text);
-
 	if (dumphistory)
 		sip_dump_history(p);
 
@@ -7053,7 +7056,7 @@
 	\return 0 on success, -1 on failure, and 1 on challenge sent
 	-2 on authentication error from chedck_auth()
 */
-static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, int reliable, struct sockaddr_in *sin, int ignore, char *mailbox, int mailboxlen)
+static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, int reliable, struct sockaddr_in *sin, int ignore, struct sip_peer **authpeer)
 {
 	struct sip_user *user = NULL;
 	struct sip_peer *peer;
@@ -7122,7 +7125,7 @@
 	if (ast_strlen_zero(of))
 		return 0;
 
-	if (!mailbox)	/* If it's a mailbox SUBSCRIBE, don't check users */
+	if (!authpeer)	/* If we are looking for a peer, don't check the user objects (or realtime) */
 		user = find_user(of, 1);
 
 	/* Find user based on user name in the from header */
@@ -7207,7 +7210,7 @@
 			ast_verbose("Found user '%s'\n", user->name);
 	} else {
 		if (user) {
-			if (!mailbox && debug)
+			if (!authpeer && debug)
 				ast_verbose("Found user '%s', but fails host access\n", user->name);
 			ASTOBJ_UNREF(user,sip_destroy_user);
 		}
@@ -7229,6 +7232,7 @@
 		if (peer) {
 			if (debug)
 				ast_verbose("Found peer '%s'\n", peer->name);
+
 			/* Take the peer */
 			ast_copy_flags(p, peer, SIP_FLAGS_TO_COPY);
 
@@ -7282,8 +7286,10 @@
 						p->chanvars = tmpvar;
 					}
 				}
-				if (mailbox)
-					snprintf(mailbox, mailboxlen, ",%s,", peer->mailbox);
+				if (authpeer) {
+					(*authpeer) = peer;	/* We might want to add a ref to the object here, to keep it in memory a bit longer if it is realtime */
+					ASTOBJ_REF(peer);	/* Any function that uses authpeer needs to ASTOBJ_UNREF */
+				}
 				if (!ast_strlen_zero(peer->username)) {
 					ast_string_field_set(p, username, peer->username);
 					/* Use the default username for authentication on outbound calls */
@@ -7348,7 +7354,7 @@
 */
 static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, int reliable, struct sockaddr_in *sin, int ignore)
 {
-	return check_user_full(p, req, sipmethod, uri, reliable, sin, ignore, NULL, 0);
+	return check_user_full(p, req, sipmethod, uri, reliable, sin, ignore, NULL);
 }
 
 /*! \brief  Get text out of a SIP MESSAGE packet */
@@ -10777,6 +10783,7 @@
 	int gotdest;
 	int res = 0;
 	int firststate = AST_EXTENSION_REMOVED;
+	struct sip_peer *authpeer = NULL;
 
 	if (p->initreq.headers) {	
 		/* We already have a dialog */
@@ -10804,19 +10811,12 @@
 		ast_verbose("Ignoring this SUBSCRIBE request\n");
 
 	if (!p->lastinvite) {
-		char mailboxbuf[256]="";
-		char *mailbox = NULL;
-		int mailboxsize = 0;
 
 		char *event = get_header(req, "Event");	/* Get Event package name */
 		char *accept = get_header(req, "Accept");
 
- 		if (!strcmp(event, "message-summary") && !strcmp(accept, "application/simple-message-summary")) {
-			mailbox = mailboxbuf;
-			mailboxsize = sizeof(mailboxbuf);
-		}
 		/* Handle authentication if this is our first subscribe */
-		res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, ignore, mailbox, mailboxsize);
+		res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, ignore, &authpeer);
 		if (res) {
 			if (res < 0) {
 				ast_log(LOG_NOTICE, "Failed to authenticate user %s for SUBSCRIBE\n", get_header(req, "From"));
@@ -10879,9 +10879,11 @@
 				  config section.
 				
 				*/
-				if (!ast_strlen_zero(mailbox)) {
+				if (authpeer && !ast_strlen_zero(authpeer->mailbox)) {
 					transmit_response(p, "200 OK", req);
-					ast_set_flag(p, SIP_NEEDDESTROY);	
+ 					p->subscribed = MWI_NOTIFICATION;
+					authpeer->mwipvt = p;	/* Link from peer to pvt */
+					/* Do I need another the other way for destruction? */
 				} else {
 					transmit_response(p, "404 Not found", req);
 					ast_set_flag(p, SIP_NEEDDESTROY);	
@@ -10917,47 +10919,56 @@
 		if (p->expiry > 0)
 			sip_scheddestroy(p, (p->expiry + 10) * 1000);	/* Set timer for destruction of call at expiration */
 
-		if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) {
-			ast_log(LOG_ERROR, "Got SUBSCRIBE for extensions without hint. Please add hint to %s in context %s\n", p->exten, p->context);
-			transmit_response(p, "404 Not found", req);
-			ast_set_flag(p, SIP_NEEDDESTROY);	
-			return 0;
+		if (p->subscribed == MWI_NOTIFICATION) {
+			if (authpeer)	/* Send first notification */
+				ASTOBJ_WRLOCK(authpeer);
+				sip_send_mwi_to_peer(authpeer);
+				ASTOBJ_UNLOCK(authpeer);
 		} else {
-			struct sip_pvt *p_old;
-
-			transmit_response(p, "200 OK", req);
-			transmit_state_notify(p, firststate, 1);	/* Send first notification */
-			append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate));
-
-			/* remove any old subscription from this peer for the same exten/context,
-			   as the peer has obviously forgotten about it and it's wasteful to wait
-			   for it to expire and send NOTIFY messages to the peer only to have them
-			   ignored (or generate errors)
-			*/
-			ast_mutex_lock(&iflock);
-			for (p_old = iflist; p_old; p_old = p_old->next) {
-				if (p_old == p)
-					continue;
-				if (p_old->initreq.method != SIP_SUBSCRIBE)
-					continue;
-				if (p_old->subscribed == NONE)
-					continue;
-				ast_mutex_lock(&p_old->lock);
-				if (!strcmp(p_old->username, p->username)) {
-					if (!strcmp(p_old->exten, p->exten) &&
-					    !strcmp(p_old->context, p->context)) {
-						ast_set_flag(p_old, SIP_NEEDDESTROY);
-						ast_mutex_unlock(&p_old->lock);
-						break;
+			if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) {
+				ast_log(LOG_ERROR, "Got SUBSCRIBE for extensions without hint. Please add hint to %s in context %s\n", p->exten, p->context);
+				transmit_response(p, "404 Not found", req);
+				ast_set_flag(p, SIP_NEEDDESTROY);	
+				return 0;
+			} else {
+				struct sip_pvt *p_old;
+	
+				transmit_response(p, "200 OK", req);
+				transmit_state_notify(p, firststate, 1);	/* Send first notification */
+				append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate));
+
+				/* remove any old subscription from this peer for the same exten/context,
+			   	as the peer has obviously forgotten about it and it's wasteful to wait
+			   	for it to expire and send NOTIFY messages to the peer only to have them
+			   	ignored (or generate errors)
+				*/
+				ast_mutex_lock(&iflock);
+				for (p_old = iflist; p_old; p_old = p_old->next) {
+					if (p_old == p)
+						continue;
+					if (p_old->initreq.method != SIP_SUBSCRIBE)
+						continue;
+					if (p_old->subscribed == NONE)
+						continue;
+					ast_mutex_lock(&p_old->lock);
+					if (!strcmp(p_old->username, p->username)) {
+						if (!strcmp(p_old->exten, p->exten) &&
+					    	!strcmp(p_old->context, p->context)) {
+							ast_set_flag(p_old, SIP_NEEDDESTROY);
+							ast_mutex_unlock(&p_old->lock);
+							break;
+						}
 					}
+					ast_mutex_unlock(&p_old->lock);
 				}
-				ast_mutex_unlock(&p_old->lock);
+				ast_mutex_unlock(&iflock);
 			}
-			ast_mutex_unlock(&iflock);
 		}
 		if (!p->expiry)
 			ast_set_flag(p, SIP_NEEDDESTROY);
 	}
+	if (authpeer)
+		ASTOBJ_UNREF(authpeer, sip_destroy_peer);
 	return 1;
 }
 
@@ -11289,20 +11300,25 @@
 		return 0;
 	}
 	
-	if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY)))
-		return -1;
 	
 	peer->lastmsgssent = ((newmsgs << 8) | (oldmsgs));
-	if (create_addr_from_peer(p, peer)) {
-		/* Maybe they're not registered, etc. */
-		sip_destroy(p);
-		return 0;
-	}
-	/* 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);
-	build_callid_pvt(p);
+
+	if (!peer->mwipvt) {
+		if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY)))
+			return -1;
+		if (create_addr_from_peer(p, peer)) {
+			/* Maybe they're not registered, etc. */
+			sip_destroy(p);
+			return 0;
+		}
+		/* 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);
+		build_callid_pvt(p);
+	} else {
+		p = peer->mwipvt;
+	}
 	/* Send MWI */
 	ast_set_flag(p, SIP_OUTGOING);
 	transmit_notify_with_mwi(p, newmsgs, oldmsgs, peer->vmexten);



More information about the asterisk-commits mailing list