[svn-commits] mmichelson: branch group/issue8824 r147812 - in /team/group/issue8824: ./ cha...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Oct 9 10:07:42 CDT 2008


Author: mmichelson
Date: Thu Oct  9 10:07:41 2008
New Revision: 147812

URL: http://svn.digium.com/view/asterisk?view=rev&rev=147812
Log:
Resolve conflict and reset automerge.


Modified:
    team/group/issue8824/   (props changed)
    team/group/issue8824/CHANGES
    team/group/issue8824/channels/chan_iax2.c
    team/group/issue8824/channels/chan_oss.c
    team/group/issue8824/channels/chan_sip.c
    team/group/issue8824/channels/chan_usbradio.c
    team/group/issue8824/channels/console_gui.c
    team/group/issue8824/channels/console_video.c
    team/group/issue8824/channels/vcodecs.c
    team/group/issue8824/configs/sip.conf.sample
    team/group/issue8824/configure
    team/group/issue8824/configure.ac
    team/group/issue8824/doc/CODING-GUIDELINES
    team/group/issue8824/include/asterisk.h
    team/group/issue8824/include/asterisk/autoconfig.h.in
    team/group/issue8824/main/astobj2.c
    team/group/issue8824/main/cli.c
    team/group/issue8824/main/config.c
    team/group/issue8824/main/pbx.c
    team/group/issue8824/main/rtp.c
    team/group/issue8824/main/translate.c
    team/group/issue8824/utils/extconf.c

Propchange: team/group/issue8824/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/group/issue8824/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Thu Oct  9 10:07:41 2008
@@ -1,1 +1,1 @@
-/trunk:1-147737
+/trunk:1-147807

Modified: team/group/issue8824/CHANGES
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/CHANGES?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/CHANGES (original)
+++ team/group/issue8824/CHANGES Thu Oct  9 10:07:41 2008
@@ -7,6 +7,8 @@
  * Added support for SUBSCRIBE/NOTIFY with dialog-info based call pickups.
    Snom phones use this for call pickup of extensions that the phone is
    subscribed to.
+ * Added support for subscribing to a voice mailbox on a remote server and
+   making the new/old message count available to local devices.
 
 Dialplan Functions
 ------------------

Modified: team/group/issue8824/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/channels/chan_iax2.c?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/channels/chan_iax2.c (original)
+++ team/group/issue8824/channels/chan_iax2.c Thu Oct  9 10:07:41 2008
@@ -6601,7 +6601,7 @@
 	
 	memset(&ied, 0, sizeof(ied));
 	if (ies->apparent_addr)
-		bcopy(ies->apparent_addr, &new, sizeof(new));
+		memmove(&new, ies->apparent_addr, sizeof(new));
 	if (ies->callno)
 		newcall = ies->callno;
 	if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
@@ -6739,7 +6739,7 @@
 
 	memset(&us, 0, sizeof(us));
 	if (ies->apparent_addr)
-		bcopy(ies->apparent_addr, &us, sizeof(us));
+		memmove(&us, ies->apparent_addr, sizeof(us));
 	if (ies->username)
 		ast_copy_string(peer, ies->username, sizeof(peer));
 	if (ies->refresh)

Modified: team/group/issue8824/channels/chan_oss.c
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/channels/chan_oss.c?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/channels/chan_oss.c (original)
+++ team/group/issue8824/channels/chan_oss.c Thu Oct  9 10:07:41 2008
@@ -701,7 +701,7 @@
 
 	/* XXX can be simplified returning &ast_null_frame */
 	/* prepare a NULL frame in case we don't have enough data to return */
-	bzero(f, sizeof(struct ast_frame));
+	memset(f, '\0', sizeof(struct ast_frame));
 	f->frametype = AST_FRAME_NULL;
 	f->src = oss_tech.type;
 

Modified: team/group/issue8824/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/channels/chan_sip.c?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/channels/chan_sip.c (original)
+++ team/group/issue8824/channels/chan_sip.c Thu Oct  9 10:07:41 2008
@@ -216,6 +216,7 @@
 #define DEFAULT_DEFAULT_EXPIRY  120
 #define DEFAULT_MIN_EXPIRY      60
 #define DEFAULT_MAX_EXPIRY      3600
+#define DEFAULT_MWI_EXPIRY      3600
 #define DEFAULT_REGISTRATION_TIMEOUT 20
 #define DEFAULT_MAX_FORWARDS    "70"
 
@@ -235,6 +236,7 @@
 static int min_expiry = DEFAULT_MIN_EXPIRY;        /*!< Minimum accepted registration time */
 static int max_expiry = DEFAULT_MAX_EXPIRY;        /*!< Maximum accepted registration time */
 static int default_expiry = DEFAULT_DEFAULT_EXPIRY;
+static int mwi_expiry = DEFAULT_MWI_EXPIRY;
 
 #ifndef MAX
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
@@ -1426,6 +1428,8 @@
 	struct sip_st_dlg *stimer;		/*!< SIP Session-Timers */              
   
 	int red; 
+
+	struct sip_subscription_mwi *mwi;       /*!< If this is a subscription MWI dialog, to which subscription */
 };
 
 /*! Max entires in the history list for a sip_pvt */
@@ -1663,6 +1667,25 @@
 	AST_LIST_ENTRY(sip_threadinfo) list;
 };
 
+/*! \brief Definition of an MWI subscription to another server */
+struct sip_subscription_mwi {
+	ASTOBJ_COMPONENTS_FULL(struct sip_subscription_mwi,1,1);
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(username);     /*!< Who we are sending the subscription as */
+		AST_STRING_FIELD(authuser);     /*!< Who we *authenticate* as */
+		AST_STRING_FIELD(hostname);     /*!< Domain or host we subscribe to */
+		AST_STRING_FIELD(secret);       /*!< Password in clear text */
+		AST_STRING_FIELD(mailbox);      /*!< Mailbox store to put MWI into */
+		);
+	enum sip_transport transport;    /*!< Transport to use */
+	int portno;                      /*!< Optional port override */
+	int resub;                       /*!< Sched ID of resubscription */
+	unsigned int subscribed:1;       /*!< Whether we are currently subscribed or not */
+	struct sip_pvt *call;            /*!< Outbound subscription dialog */
+	struct ast_dnsmgr_entry *dnsmgr; /*!< DNS refresh manager for subscription */
+	struct sockaddr_in us;           /*!< Who the server thinks we are */
+};
+
 /* --- Hash tables of various objects --------*/
 
 #ifdef LOW_MEMORY
@@ -1687,6 +1710,11 @@
 	ASTOBJ_CONTAINER_COMPONENTS(struct sip_registry);
 	int recheck;
 } regl;
+
+/*! \brief  The MWI subscription list */
+static struct ast_subscription_mwi_list {
+	ASTOBJ_CONTAINER_COMPONENTS(struct sip_subscription_mwi);
+} submwil;
 
 /*! \brief
  * \note The only member of the peer used here is the name field
@@ -2071,6 +2099,7 @@
 static char *sip_show_registry(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 static char *sip_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+static char *sip_show_mwi(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 static const char *subscription_type2str(enum subscriptiontype subtype) attribute_pure;
 static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype);
 static char *complete_sip_peer(const char *word, int state, int flags2);
@@ -2231,6 +2260,7 @@
 static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
 static void handle_response_notify(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
 static void handle_response_refer(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
+static void handle_response_subscribe(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
 static int handle_response_register(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
 static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
 
@@ -2263,6 +2293,12 @@
 static enum st_mode st_get_mode(struct sip_pvt *);
 static struct sip_st_dlg* sip_st_alloc(struct sip_pvt *const p);
 
+/*!--- SIP MWI Subscription support */
+static int sip_subscribe_mwi(const char *value, int lineno);
+static void sip_subscribe_mwi_destroy(struct sip_subscription_mwi *mwi);
+static void sip_send_all_mwi_subscriptions(void);
+static int sip_subscribe_mwi_do(const void *data);
+static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi);
 
 /*! \brief Definition of this channel for PBX channel registration */
 static const struct ast_channel_tech sip_tech = {
@@ -4589,6 +4625,20 @@
 	ast_dnsmgr_release(reg->dnsmgr);
 	ast_free(reg);
 	
+}
+
+/*! \brief Destroy MWI subscription object */
+static void sip_subscribe_mwi_destroy(struct sip_subscription_mwi *mwi)
+{
+	if (mwi->call) {
+		mwi->call->mwi = NULL;
+		sip_destroy(mwi->call);
+	}
+	
+	AST_SCHED_DEL(sched, mwi->resub);
+	ast_string_field_free_memory(mwi);
+	ast_dnsmgr_release(mwi->dnsmgr);
+	ast_free(mwi);
 }
 
 /*! \brief Execute destruction of SIP dialog structure, release memory */
@@ -5746,9 +5796,9 @@
 }
 
 /*! \brief Reads one line of SIP message body */
-static char *get_body_by_line(const char *line, const char *name, int nameLen)
-{
-	if (!strncasecmp(line, name, nameLen) && line[nameLen] == '=')
+static char *get_body_by_line(const char *line, const char *name, int nameLen, char delimiter)
+{
+	if (!strncasecmp(line, name, nameLen) && line[nameLen] == delimiter)
 		return ast_skip_blanks(line + nameLen + 1);
 
 	return "";
@@ -5763,7 +5813,7 @@
 	int len = strlen(name);
 
 	while (*start < req->sdp_end) {
-		const char *r = get_body_by_line(req->line[(*start)++], name, len);
+		const char *r = get_body_by_line(req->line[(*start)++], name, len, '=');
 		if (r[0] != '\0')
 			return r;
 	}
@@ -5780,14 +5830,14 @@
 }
 
 /*! \brief Get a specific line from the message body */
-static char *get_body(struct sip_request *req, char *name) 
+static char *get_body(struct sip_request *req, char *name, char delimiter) 
 {
 	int x;
 	int len = strlen(name);
 	char *r;
 
 	for (x = 0; x < req->lines; x++) {
-		r = get_body_by_line(req->line[x], name, len);
+		r = get_body_by_line(req->line[x], name, len, delimiter);
 		if (r[0] != '\0')
 			return r;
 	}
@@ -6446,6 +6496,80 @@
 	reg->ocseq = INITIAL_CSEQ;
 	ASTOBJ_CONTAINER_LINK(&regl, reg); /* Add the new registry entry to the list */
 	registry_unref(reg, "unref the reg pointer");	/* release the reference given by ASTOBJ_INIT. The container has another reference */
+	return 0;
+}
+
+/*! \brief Parse mwi=> line in sip.conf and add to list */
+static int sip_subscribe_mwi(const char *value, int lineno)
+{
+	struct sip_subscription_mwi *mwi;
+	int portnum = 0;
+	enum sip_transport transport = SIP_TRANSPORT_UDP;
+	char buf[256] = "";
+	char *username = NULL, *hostname = NULL, *secret = NULL, *authuser = NULL, *porta = NULL, *mailbox = NULL;
+	
+	if (!value) {
+		return -1;
+	}
+	
+	ast_copy_string(buf, value, sizeof(buf));
+
+	sip_parse_host(buf, lineno, &username, &portnum, &transport);
+	
+	if ((hostname = strrchr(username, '@'))) {
+		*hostname++ = '\0';
+	}
+	
+	if ((secret = strchr(username, ':'))) {
+		*secret++ = '\0';
+		if ((authuser = strchr(secret, ':'))) {
+			*authuser++ = '\0';
+		}
+	}
+	
+	if ((mailbox = strchr(hostname, '/'))) {
+		*mailbox++ = '\0';
+	}
+
+	if (ast_strlen_zero(username) || ast_strlen_zero(hostname) || ast_strlen_zero(mailbox)) {
+		ast_log(LOG_WARNING, "Format for MWI subscription is user[:secret[:authuser]]@host[:port][/mailbox] at line %d\n", lineno);
+		return -1;
+	}
+	
+	if ((porta = strchr(hostname, ':'))) {
+		*porta++ = '\0';
+		if (!(portnum = atoi(porta))) {
+			ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
+			return -1;
+		}
+	}
+	
+	if (!(mwi = ast_calloc(1, sizeof(*mwi)))) {
+		return -1;
+	}
+	
+	if (ast_string_field_init(mwi, 256)) {
+		ast_free(mwi);
+		return -1;
+	}
+	
+	ASTOBJ_INIT(mwi);
+	ast_string_field_set(mwi, username, username);
+	if (secret) {
+		ast_string_field_set(mwi, secret, secret);
+	}
+	if (authuser) {
+		ast_string_field_set(mwi, authuser, authuser);
+	}
+	ast_string_field_set(mwi, hostname, hostname);
+	ast_string_field_set(mwi, mailbox, mailbox);
+	mwi->resub = -1;
+	mwi->portno = portnum;
+	mwi->transport = transport;
+	
+	ASTOBJ_CONTAINER_LINK(&submwil, mwi);
+	ASTOBJ_UNREF(mwi, sip_subscribe_mwi_destroy);
+	
 	return 0;
 }
 
@@ -9163,7 +9287,7 @@
 	add_header(req, "Diversion", header_text);
 }
 
-/*! \brief Build REFER/INVITE/OPTIONS message and transmit it 
+/*! \brief Build REFER/INVITE/OPTIONS/SUBSCRIBE message and transmit it 
 	\param init 0 = Prepare request within dialog, 1= prepare request, new branch, 2= prepare new request and new dialog. do_proxy_auth calls this with init!=2
  \param p sip_pvt structure
  \param sdp unknown 
@@ -9199,7 +9323,15 @@
 				add_header(&req, "Referred-By", buf);
 			}
 		}
-	}
+	} else if (sipmethod == SIP_SUBSCRIBE) { /* We only support sending MWI subscriptions right now */
+		char buf[SIPBUFSIZE];
+
+		add_header(&req, "Event", "message-summary");
+		add_header(&req, "Accept", "application/simple-message-summary");
+		snprintf(buf, sizeof(buf), "%d", mwi_expiry);
+		add_header(&req, "Expires", buf);
+	}
+
 	/* This new INVITE is part of an attended transfer. Make sure that the
 	other end knows and replace the current call with this new call */
 	if (p->options && !ast_strlen_zero(p->options->replaces)) {
@@ -9294,6 +9426,94 @@
 		initialize_initreq(p, &req);
 	p->lastinvite = p->ocseq;
 	return send_request(p, &req, init ? XMIT_CRITICAL : XMIT_RELIABLE, p->ocseq);
+}
+
+/*! \brief Send a subscription or resubscription for MWI */
+static int sip_subscribe_mwi_do(const void *data)
+{
+	struct sip_subscription_mwi *mwi = ASTOBJ_REF((struct sip_subscription_mwi *) data);
+	
+	if (!mwi) {
+		return -1;
+	}
+	
+	mwi->resub = -1;
+	__sip_subscribe_mwi_do(mwi);
+	ASTOBJ_UNREF(mwi, sip_subscribe_mwi_destroy);
+	
+	return 0;
+}
+
+/*! \brief Actually setup an MWI subscription or resubscribe */
+static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi)
+{
+	/* If we have no DNS manager let's do a lookup */
+	if (!mwi->dnsmgr) {
+		char transport[MAXHOSTNAMELEN];
+		snprintf(transport, sizeof(transport), "_sip._%s", get_transport(mwi->transport));
+		ast_dnsmgr_lookup(mwi->hostname, &mwi->us, &mwi->dnsmgr, global_srvlookup ? transport : NULL);
+	}
+
+	/* If we already have a subscription up simply send a resubscription */
+	if (mwi->call) {
+		transmit_invite(mwi->call, SIP_SUBSCRIBE, 0, 0);
+		return 0;
+	}
+	
+	/* Create a dialog that we will use for the subscription */
+	if (!(mwi->call = sip_alloc(NULL, NULL, 0, SIP_SUBSCRIBE))) {
+		return -1;
+	}
+
+	mwi->call->outboundproxy = obproxy_get(mwi->call, NULL);
+
+	if (!mwi->us.sin_port && mwi->portno) {
+		mwi->us.sin_port = htons(mwi->portno);
+	}
+	
+	/* Setup the destination of our subscription */
+	if (create_addr(mwi->call, mwi->hostname, &mwi->us, 0)) {
+		dialog_unlink_all(mwi->call, TRUE, TRUE);
+		mwi->call = dialog_unref(mwi->call, "unref dialog after unlink_all");
+		return 0;
+	}
+	
+	if (!mwi->dnsmgr && mwi->portno) {
+		mwi->call->sa.sin_port = htons(mwi->portno);
+		mwi->call->recv.sin_port = htons(mwi->portno);
+	} else {
+		mwi->portno = ntohs(mwi->call->sa.sin_port);
+	}
+	
+	/* Set various other information */
+	if (!ast_strlen_zero(mwi->authuser)) {
+		ast_string_field_set(mwi->call, peername, mwi->authuser);
+		ast_string_field_set(mwi->call, authname, mwi->authuser);
+		ast_string_field_set(mwi->call, fromuser, mwi->authuser);
+	} else {
+		ast_string_field_set(mwi->call, peername, mwi->username);
+		ast_string_field_set(mwi->call, authname, mwi->username);
+		ast_string_field_set(mwi->call, fromuser, mwi->username);
+	}
+	ast_string_field_set(mwi->call, username, mwi->username);
+	if (!ast_strlen_zero(mwi->secret)) {
+		ast_string_field_set(mwi->call, peersecret, mwi->secret);
+	}
+	mwi->call->socket.type = mwi->transport;
+	mwi->call->socket.port = htons(mwi->portno);
+	ast_sip_ouraddrfor(&mwi->call->sa.sin_addr, &mwi->call->ourip);
+	build_contact(mwi->call);
+	build_via(mwi->call);
+	build_callid_pvt(mwi->call);
+	ast_set_flag(&mwi->call->flags[0], SIP_OUTGOING);
+	
+	/* Associate the call with us */
+	mwi->call->mwi = ASTOBJ_REF(mwi);
+	
+	/* Actually send the packet */
+	transmit_invite(mwi->call, SIP_SUBSCRIBE, 0, 2);
+	
+	return 0;
 }
 
 /*! \brief Used in the SUBSCRIBE notification subsystem (RFC3265) */
@@ -14027,6 +14247,36 @@
 	return CLI_SUCCESS;
 }
 
+static char *sip_show_mwi(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+#define FORMAT  "%-30.30s  %-12.12s  %-10.10s  %-10.10s\n"
+	char host[80];
+	
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "sip show mwi";
+		e->usage =
+			"Usage: sip show mwi\n"
+			"       Provides a list of MWI subscriptions and status.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+	
+	ast_cli(a->fd, FORMAT, "Host", "Username", "Mailbox", "Subscribed");
+	
+	ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do {
+		ASTOBJ_RDLOCK(iterator);
+		snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT);
+		ast_cli(a->fd, FORMAT, host, iterator->username, iterator->mailbox, iterator->subscribed ? "Yes" : "No");
+		ASTOBJ_UNLOCK(iterator);
+	} while(0));
+
+	return CLI_SUCCESS;
+#undef FORMAT
+}
+
+
 /*! \brief Show subscription type in string format */
 static const char *subscription_type2str(enum subscriptiontype subtype)
 {
@@ -14507,7 +14757,7 @@
 		}
 
 		/* Try getting the "signal=" part */
-		if (ast_strlen_zero(c = get_body(req, "Signal")) && ast_strlen_zero(c = get_body(req, "d"))) {
+		if (ast_strlen_zero(c = get_body(req, "Signal", '=')) && ast_strlen_zero(c = get_body(req, "d", '='))) {
 			ast_log(LOG_WARNING, "Unable to retrieve DTMF signal from INFO message from %s\n", p->callid);
 			transmit_response(p, "200 OK", req); /* Should return error */
 			return;
@@ -14515,7 +14765,7 @@
 			ast_copy_string(buf, c, sizeof(buf));
 		}
 
-		if (!ast_strlen_zero((c = get_body(req, "Duration"))))
+		if (!ast_strlen_zero((c = get_body(req, "Duration", '='))))
 			duration = atoi(c);
 		if (!duration)
 			duration = 100; /* 100 ms */
@@ -16068,6 +16318,63 @@
 	}
 }
 
+/* \brief Handle SIP response in SUBSCRIBE transaction */
+static void handle_response_subscribe(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
+{
+	if (!p->mwi) {
+		return;
+	}
+
+	switch (resp) {
+	case 200: /* Subscription accepted */
+		ast_debug(3, "Got 200 OK on subscription for MWI\n");
+		if (p->options) {
+			ast_free(p->options);
+			p->options = NULL;
+		}
+		p->mwi->subscribed = 1;
+		p->mwi->resub = ast_sched_add(sched, mwi_expiry * 1000, sip_subscribe_mwi_do, p->mwi);
+		break;
+	case 401:
+	case 407:
+		ast_string_field_set(p, theirtag, NULL);
+		if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_SUBSCRIBE, 0)) {
+			ast_log(LOG_NOTICE, "Failed to authenticate on SUBSCRIBE to '%s'\n", get_header(&p->initreq, "From"));
+			p->mwi->call = NULL;
+			ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy);
+			p->needdestroy = 1;
+		}
+		break;
+	case 403:
+		transmit_response_with_date(p, "200 OK", req);
+		ast_log(LOG_WARNING, "Authentication failed while trying to subscribe for MWI.\n");
+		p->mwi->call = NULL;
+		ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy);
+		p->needdestroy = 1;
+		sip_alreadygone(p);
+		break;
+	case 404:
+		ast_log(LOG_WARNING, "Subscription failed for MWI. The remote side said that a mailbox may not have been configured.\n");
+		p->mwi->call = NULL;
+		ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy);
+		p->needdestroy = 1;
+		break;
+	case 481:
+		ast_log(LOG_WARNING, "Subscription failed for MWI. The remote side said that our dialog did not exist.\n");
+		p->mwi->call = NULL;
+		ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy);
+		p->needdestroy = 1;
+		break;
+	case 500:
+	case 501:
+		ast_log(LOG_WARNING, "Subscription failed for MWI. The remote side may have suffered a heart attack.\n");
+		p->mwi->call = NULL;
+		ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy);
+		p->needdestroy = 1;
+		break;
+	}
+}
+
 /* \brief Handle SIP response in REFER transaction
 	We've sent a REFER, now handle responses to it 
   */
@@ -16416,13 +16723,14 @@
 				handle_response_invite(p, resp, rest, req, seqno);
 			} else if (sipmethod == SIP_NOTIFY) {
 				handle_response_notify(p, resp, rest, req, seqno);
-			} else if (sipmethod == SIP_REGISTER) 
+			} else if (sipmethod == SIP_REGISTER) {
 				res = handle_response_register(p, resp, rest, req, seqno);
-			else if (sipmethod == SIP_BYE) {		/* Ok, we're ready to go */
+			} else if (sipmethod == SIP_SUBSCRIBE) {
+				ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
+				handle_response_subscribe(p, resp, rest, req, seqno);
+			} else if (sipmethod == SIP_BYE) {		/* Ok, we're ready to go */
 				p->needdestroy = 1;
 				ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
-			} else if (sipmethod == SIP_SUBSCRIBE) {
-				ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
 			}
 			break;
 		case 202:   /* Transfer accepted */
@@ -16437,6 +16745,8 @@
 				handle_response_notify(p, resp, rest, req, seqno);
 			else if (sipmethod == SIP_REFER)
 				handle_response_refer(p, resp, rest, req, seqno);
+			else if (sipmethod == SIP_SUBSCRIBE)
+				handle_response_subscribe(p, resp, rest, req, seqno);
 			else if (p->registry && sipmethod == SIP_REGISTER)
 				res = handle_response_register(p, resp, rest, req, seqno);
 			else if (sipmethod == SIP_BYE) {
@@ -16458,6 +16768,8 @@
 		case 403: /* Forbidden - we failed authentication */
 			if (sipmethod == SIP_INVITE)
 				handle_response_invite(p, resp, rest, req, seqno);
+			else if (sipmethod == SIP_SUBSCRIBE)
+				handle_response_subscribe(p, resp, rest, req, seqno);
 			else if (p->registry && sipmethod == SIP_REGISTER) 
 				res = handle_response_register(p, resp, rest, req, seqno);
 			else {
@@ -16470,6 +16782,8 @@
 				res = handle_response_register(p, resp, rest, req, seqno);
 			else if (sipmethod == SIP_INVITE)
 				handle_response_invite(p, resp, rest, req, seqno);
+			else if (sipmethod == SIP_SUBSCRIBE)
+				handle_response_subscribe(p, resp, rest, req, seqno);
 			else if (owner)
 				ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
 			break;
@@ -16503,6 +16817,8 @@
 				handle_response_invite(p, resp, rest, req, seqno);
 			} else if (sipmethod == SIP_REFER) {
 				handle_response_refer(p, resp, rest, req, seqno);
+			} else if (sipmethod == SIP_SUBSCRIBE) {
+				handle_response_subscribe(p, resp, rest, req, seqno);
 			} else if (sipmethod == SIP_BYE) {
 				/* The other side has no transaction to bye,
 				just assume it's all right then */
@@ -16586,6 +16902,9 @@
 				case 500: /* Server error */
 					if (sipmethod == SIP_REFER) {
 						handle_response_refer(p, resp, rest, req, seqno);
+						break;
+					} else if (sipmethod == SIP_SUBSCRIBE) {
+						handle_response_subscribe(p, resp, rest, req, seqno);
 						break;
 					}
 					/* Fall through */
@@ -17035,12 +17354,7 @@
 	if (sipdebug)
 		ast_debug(2, "Got NOTIFY Event: %s\n", event);
 
-	if (strcmp(event, "refer")) {
-		/* We don't understand this event. */
-		/* Here's room to implement incoming voicemail notifications :-) */
-		transmit_response(p, "489 Bad event", req);
-		res = -1;
-	} else {
+	if (!strcmp(event, "refer")) {
 		/* Save nesting depth for now, since there might be other events we will
 			support in the future */
 
@@ -17140,7 +17454,33 @@
 		
 		/* Confirm that we received this packet */
 		transmit_response(p, "200 OK", req);
-	};
+	} else if (p->mwi && !strcmp(event, "message-summary")) {
+		char *c = ast_strdupa(get_body(req, "Voice-Message", ':'));
+
+		if (!ast_strlen_zero(c)) {
+			char *old = strsep(&c, " ");
+			char *new = strsep(&old, "/");
+			struct ast_event *event;
+
+			if ((event = ast_event_new(AST_EVENT_MWI,
+						   AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, p->mwi->mailbox,
+						   AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, "SIP_Remote",
+						   AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, atoi(new),
+						   AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, atoi(old),
+						   AST_EVENT_IE_END))) {
+				ast_event_queue_and_cache(event,
+							  AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
+							  AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
+							  AST_EVENT_IE_END);
+			}
+		}
+
+		transmit_response(p, "200 OK", req);
+	} else {
+		/* We don't understand this event. */
+		transmit_response(p, "489 Bad event", req);
+		res = -1;
+	}
 
 	if (!p->lastinvite)
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
@@ -22232,6 +22572,10 @@
 			default_expiry = atoi(v->value);
 			if (default_expiry < 1)
 				default_expiry = DEFAULT_DEFAULT_EXPIRY;
+		} else if (!strcasecmp(v->name, "mwiexpiry") || !strcasecmp(v->name, "mwiexpirey")) {
+			mwi_expiry = atoi(v->value);
+			if (mwi_expiry < 1)
+				mwi_expiry = DEFAULT_MWI_EXPIRY;
 		} else if (!strcasecmp(v->name, "sipdebug")) {
 			if (ast_true(v->value))
 				sipdebug |= sip_debug_config;
@@ -22310,6 +22654,8 @@
 		} else if (!strcasecmp(v->name, "register")) {
 			if (sip_register(v->value, v->lineno) == 0)
 				registry_count++;
+		} else if (!strcasecmp(v->name, "mwi")) {
+			sip_subscribe_mwi(v->value, v->lineno);
 		} else if (!strcasecmp(v->name, "tos_sip")) {
 			if (ast_str2tos(v->value, &global_tos_sip))
 				ast_log(LOG_WARNING, "Invalid tos_sip value at line %d, refer to QoS documentation\n", v->lineno);
@@ -23138,6 +23484,17 @@
 	);
 }
 
+/*! \brief Send all MWI subscriptions */
+static void sip_send_all_mwi_subscriptions(void)
+{
+	ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do {
+		ASTOBJ_WRLOCK(iterator);
+		AST_SCHED_DEL(sched, iterator->resub);
+		iterator->resub = ast_sched_add(sched, 1, sip_subscribe_mwi_do, iterator);
+		ASTOBJ_UNLOCK(iterator);
+	} while (0));
+}
+
 /*! \brief Reload module */
 static int sip_do_reload(enum channelreloadreason reason)
 {
@@ -23157,6 +23514,9 @@
 
 	/* Register with all services */
 	sip_send_all_registers();
+
+	sip_send_all_mwi_subscriptions();
+
 	end_poke = time(0);
 	
 	ast_debug(4, "do_reload finished. peer poke/prune reg contact time = %d sec.\n", (int)(end_poke-start_poke));
@@ -23214,6 +23574,7 @@
 	AST_CLI_DEFINE(sip_show_registry, "List SIP registration status"),
 	AST_CLI_DEFINE(sip_unregister, "Unregister (force expiration) a SIP peer from the registry"),
 	AST_CLI_DEFINE(sip_show_settings, "Show SIP global settings"),
+	AST_CLI_DEFINE(sip_show_mwi, "Show MWI subscriptions"),
 	AST_CLI_DEFINE(sip_cli_notify, "Send a notify packet to a SIP peer"),
 	AST_CLI_DEFINE(sip_show_channel, "Show detailed SIP channel info"),
 	AST_CLI_DEFINE(sip_show_history, "Show SIP dialog history"),
@@ -23238,6 +23599,7 @@
 	dialogs = ao2_t_container_alloc(hash_dialog_size, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs");
 	
 	ASTOBJ_CONTAINER_INIT(&regl); /* Registry object list -- not searched for anything */
+	ASTOBJ_CONTAINER_INIT(&submwil); /* MWI subscription object list */
 
 	if (!(sched = sched_context_create())) {
 		ast_log(LOG_ERROR, "Unable to create scheduler context\n");
@@ -23302,7 +23664,8 @@
 			"Send a SIP notify", mandescr_sipnotify);
 	sip_poke_all_peers();	
 	sip_send_all_registers();
-	
+	sip_send_all_mwi_subscriptions();
+
 	/* And start the monitor for the first time */
 	restart_monitor();
 
@@ -23419,6 +23782,8 @@
 
 	ASTOBJ_CONTAINER_DESTROYALL(&regl, sip_registry_destroy);
 	ASTOBJ_CONTAINER_DESTROY(&regl);
+	ASTOBJ_CONTAINER_DESTROYALL(&submwil, sip_subscribe_mwi_destroy);
+	ASTOBJ_CONTAINER_DESTROY(&submwil);
 
 	ao2_t_ref(peers, -1, "unref the peers table");
 	ao2_t_ref(peers_by_ip, -1, "unref the peers_by_ip table");

Modified: team/group/issue8824/channels/chan_usbradio.c
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/channels/chan_usbradio.c?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/channels/chan_usbradio.c (original)
+++ team/group/issue8824/channels/chan_usbradio.c Thu Oct  9 10:07:41 2008
@@ -1411,7 +1411,7 @@
 				l = FRAME_SIZE - ofs;
 			if (l > s->datalen - start)	/* don't overflow the source */
 				l = s->datalen - start;
-			bcopy(s->data + start, myframe + ofs, l * 2);
+			memmove(myframe + ofs, s->data + start, l * 2);
 			if (0)
 				ast_log(LOG_WARNING, "send_sound sound %d/%d of %d into %d\n", l_sampsent, l, s->samplen, ofs);
 			l_sampsent += l;
@@ -1422,14 +1422,14 @@
 			if (l > 0) {
 				if (l > FRAME_SIZE - ofs)
 					l = FRAME_SIZE - ofs;
-				bcopy(silence, myframe + ofs, l * 2);
+				memmove(myframe + ofs, silence, l * 2);
 				l_sampsent += l;
 			} else {			/* silence is over, restart sound if loop */
 				if (s->repeat == 0) {	/* last block */
 					o->cursound = -1;
 					o->nosound = 0;	/* allow audio data */
 					if (ofs < FRAME_SIZE)	/* pad with silence */
-						bcopy(silence, myframe + ofs, (FRAME_SIZE - ofs) * 2);
+						memmove(myframe + ofs, silence, (FRAME_SIZE - ofs) * 2);
 				}
 				l_sampsent = 0;
 			}
@@ -1813,7 +1813,7 @@
 	}
 	/* XXX can be simplified returning &ast_null_frame */
 	/* prepare a NULL frame in case we don't have enough data to return */
-	bzero(f, sizeof(struct ast_frame));
+	memset(f, '\0', sizeof(struct ast_frame));
 	f->frametype = AST_FRAME_NULL;
 	f->src = usbradio_tech.type;
 

Modified: team/group/issue8824/channels/console_gui.c
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/channels/console_gui.c?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/channels/console_gui.c (original)
+++ team/group/issue8824/channels/console_gui.c Thu Oct  9 10:07:41 2008
@@ -204,7 +204,7 @@
 		if (gui->win[i].bmp)
 			SDL_FreeYUVOverlay(gui->win[i].bmp);
 	}
-	bzero(gui, sizeof(gui));
+	memset(gui, '\0', sizeof(gui));
 
 	/* deallocates the space allocated for the keypad message boards */
 	if (gui->bd_dialed)
@@ -290,7 +290,7 @@
 	bmp = gui->win[out].bmp;
 	SDL_LockYUVOverlay(bmp);
 	/* output picture info - this is sdl, YUV420P */
-	bzero(&p_out, sizeof(p_out));
+	memset(&p_out, '\0', sizeof(p_out));
 	p_out.data[0] = bmp->pixels[0];
 	p_out.data[1] = bmp->pixels[1];
 	p_out.data[2] = bmp->pixels[2];
@@ -1358,7 +1358,7 @@
                            FocusChangeMask | PropertyChangeMask |
                            ColormapChangeMask | OwnerGrabButtonMask;
 
-        bzero(&attr, sizeof(attr));
+        memset(&attr, '\0', sizeof(attr));
 	XGetWindowAttributes(SDL_Display, win, &attr);
 
 	/* the following events can be delivered only to one client.
@@ -1565,7 +1565,7 @@
 		return 0;
 
 	s1[0] = s2[0] = '\0';
-	bzero(&e, sizeof(e));
+	memset(&e, '\0', sizeof(e));
 	i = sscanf(val, "%14s %14s %d %d %d %d %d",
                 s1, s2, &e.x0, &e.y0, &e.x1, &e.y1, &e.h);
 

Modified: team/group/issue8824/channels/console_video.c
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/channels/console_video.c?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/channels/console_video.c (original)
+++ team/group/issue8824/channels/console_video.c Thu Oct  9 10:07:41 2008
@@ -272,7 +272,7 @@
 
 	if (b->data && b->size)
 		ast_free(b->data);
-	bzero(b, sizeof(*b));
+	memset(b, '\0', sizeof(*b));
 	/* restore some fields */
 	b->w = x.w;
 	b->h = x.h;
@@ -587,7 +587,7 @@
 	int luv = b->w/2;	/* U/V linesize, bytes */
 	int sample_size = 1;
 	
-	bzero(p, sizeof(*p));
+	memset(p, '\0', sizeof(*p));
 	switch (b->pix_fmt) {
 	case PIX_FMT_RGB555:
 	case PIX_FMT_RGB565:

Modified: team/group/issue8824/channels/vcodecs.c
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/channels/vcodecs.c?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/channels/vcodecs.c (original)
+++ team/group/issue8824/channels/vcodecs.c Thu Oct  9 10:07:41 2008
@@ -204,7 +204,7 @@
 		if ( x == 0) {	/* new line */
 			if (i != 0)
 				ast_log(LOG_WARNING, "%s\n", buf);
-			bzero(buf, sizeof(buf));
+			memset(buf, '\0', sizeof(buf));
 			sprintf(buf, "%04x: ", i);
 		}
 		sprintf(buf + 6 + x*3, "%02x ", b->data[i]);
@@ -504,7 +504,7 @@
 		}
 	}
 	if (srclen != 0)	/* update b with leftover data */
-		bcopy(src, b->data, srclen);
+		memmove(b->data, src, srclen);
 	b->used = srclen;
 	b->ebit = 0;
 	return full_frame;
@@ -582,7 +582,7 @@
 	if (len < H263_MIN_LEN)	/* unreasonably small */
 		return NULL;
 
-	bzero(h263_hdr, sizeof(h263_hdr));
+	memset(h263_hdr, '\0', sizeof(h263_hdr));
 	/* Now set the header bytes. Only type A by now,
 	 * and h[0] = h[2] = h[3] = 0 by default.
 	 * PTYPE starts 30 bits in the picture, so the first useful
@@ -647,7 +647,7 @@
 
 		if (!f)
 			break;
-		bcopy(h, f->data.ptr, 4);	/* copy the h263 header */
+		memmove(f->data.ptr, h, 4);	/* copy the h263 header */
 		/* XXX to do: if not aligned, fix sbit and ebit,
 		 * then move i back by 1 for the next frame
 		 */
@@ -737,7 +737,7 @@
 	if (len < H261_MIN_LEN)	/* unreasonably small */
 		return NULL;
 
-	bzero(h261_hdr, sizeof(h261_hdr));
+	memset(h261_hdr, '\0', sizeof(h261_hdr));
 
 	/* Similar to the code in h263_encap, but the marker there is longer.
 	 * Start a few bytes within the bitstream to avoid hitting the marker
@@ -801,7 +801,7 @@
 			break;
 		/* recompute header with I=0, V=1 */
 		h[0] = ( (sbit & 7) << 5 ) | ( (ebit & 7) << 2 ) | 1;
-		bcopy(h, f->data.ptr, 4);	/* copy the h261 header */
+		memmove(f->data.ptr, h, 4);	/* copy the h261 header */
 		if (ebit)	/* not aligned, restart from previous byte */
 			i--;
 		sbit = (8 - ebit) & 7;
@@ -902,7 +902,7 @@
 	}
 	datalen -= ret;
 	if (datalen > 0)	/* update b with leftover bytes */
-		bcopy(b->data + ret, b->data, datalen);
+		memmove(b->data, b->data + ret, datalen);
 	b->used = datalen;
 	b->ebit = 0;
 	return full_frame;

Modified: team/group/issue8824/configs/sip.conf.sample
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/configs/sip.conf.sample?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/configs/sip.conf.sample (original)
+++ team/group/issue8824/configs/sip.conf.sample Thu Oct  9 10:07:41 2008
@@ -145,6 +145,7 @@
                                 ; and subscriptions (seconds)
 ;minexpiry=60                   ; Minimum length of registrations/subscriptions (default 60)
 ;defaultexpiry=120              ; Default length of incoming/outgoing registration
+;mwiexpiry=3600                 ; Expiry time for outgoing MWI subscriptions
 ;qualifyfreq=60                 ; Qualification: How often to check for the 
                                 ; host to be up in seconds
                                 ; Set to low value if you use low timeout for
@@ -453,7 +454,17 @@
                                 ; 0 = continue forever, hammering the other server
                                 ; until it accepts the registration
                                 ; Default is 0 tries, continue forever
-
+;----------------------------------------- OUTBOUND MWI SUBSCRIPTIONS -------------------------
+; Asterisk can subscribe to receive the MWI from another SIP server and store it locally for retrieval
+; by other phones.
+; Format for the mwi register statement is:
+;       mwi => user[:secret[:authuser]]@host[:port][/mailbox]
+;
+; Examples:
+;mwi => 1234:password at mysipprovider.com/1234
+;
+; MWI received will be stored in the 1234 mailbox of the SIP_Remote context. It can be used by other phones by following the below:
+; mailbox=1234 at SIP_Remote
 ;----------------------------------------- NAT SUPPORT ------------------------
 ;
 ; WARNING: SIP operation behind a NAT is tricky and you really need

Modified: team/group/issue8824/configure.ac
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/configure.ac?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/configure.ac (original)
+++ team/group/issue8824/configure.ac Thu Oct  9 10:07:41 2008
@@ -327,7 +327,7 @@
 AC_FUNC_STRTOD
 AC_FUNC_UTIME_NULL
 AC_FUNC_VPRINTF
-AC_CHECK_FUNCS([asprintf atexit bzero dup2 endpwent ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap putenv re_comp regcomp select setenv socket strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtol strtoq unsetenv utime vasprintf])
+AC_CHECK_FUNCS([asprintf atexit dup2 endpwent ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap putenv re_comp regcomp select setenv socket strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtol strtoq unsetenv utime vasprintf])
 
 AC_CHECK_FUNCS([glob])
 

Modified: team/group/issue8824/doc/CODING-GUIDELINES
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/doc/CODING-GUIDELINES?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/doc/CODING-GUIDELINES (original)
+++ team/group/issue8824/doc/CODING-GUIDELINES Thu Oct  9 10:07:41 2008
@@ -382,6 +382,12 @@
 * Use of functions
 ------------------
 
+For the sake of uclibc, do not use index, bcopy or bzero; use 
+strchr(), memset(), and memmove() instead. uclibc can be configured
+to supply these functions, but we can save these users
+time and consternation if we abstain from using these
+functions.
+
 When making applications, always ast_strdupa(data) to a local pointer if
 you intend to parse the incoming data string.
 

Modified: team/group/issue8824/include/asterisk.h
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/include/asterisk.h?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/include/asterisk.h (original)
+++ team/group/issue8824/include/asterisk.h Thu Oct  9 10:07:41 2008
@@ -178,4 +178,7 @@
 struct ast_variable;
 struct ast_str;
 
+#define bzero  0x__dont_use_bzero__use_memset_instead""
+#define bcopy  0x__dont_use_bcopy__use_memmove_instead()
+
 #endif /* _ASTERISK_H */

Modified: team/group/issue8824/include/asterisk/autoconfig.h.in
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/include/asterisk/autoconfig.h.in?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/include/asterisk/autoconfig.h.in (original)
+++ team/group/issue8824/include/asterisk/autoconfig.h.in Thu Oct  9 10:07:41 2008
@@ -125,9 +125,6 @@
 
 /* Define to 1 if byteswap.h macros are available. */
 #undef HAVE_BYTESWAP_H
-
-/* Define to 1 if you have the `bzero' function. */
-#undef HAVE_BZERO
 
 /* Define this to indicate the ${CAP_DESCRIP} library */
 #undef HAVE_CAP

Modified: team/group/issue8824/main/astobj2.c
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/main/astobj2.c?view=diff&rev=147812&r1=147811&r2=147812
==============================================================================
--- team/group/issue8824/main/astobj2.c (original)
+++ team/group/issue8824/main/astobj2.c Thu Oct  9 10:07:41 2008
@@ -262,7 +262,7 @@
 		/* for safety, zero-out the astobj2 header and also the
 		 * first word of the user-data, which we make sure is always
 		 * allocated. */

[... 114 lines stripped ...]



More information about the svn-commits mailing list