[Asterisk-code-review] res pjsip: Add handling for incoming unsolicited MWI NOTIFY (asterisk[13])

George Joseph asteriskteam at digium.com
Tue Sep 12 09:51:30 CDT 2017


George Joseph has uploaded this change for review. ( https://gerrit.asterisk.org/6480


Change subject: res_pjsip:  Add handling for incoming unsolicited MWI NOTIFY
......................................................................

res_pjsip:  Add handling for incoming unsolicited MWI NOTIFY

A new endpoint parameter "incoming_mwi_mailbox" allows Asterisk to
receive unsolicited MWI NOTIFY requests and make them available to
other modules via the stasis message bus.

res_pjsip_pubsub has a new handler "pubsub_on_rx_mwi_notify_request"
that parses a simple-message-summary body and, if
endpoint->incoming_mwi_account is set, calls ast_publish_mwi_state
with the voice-message counts from the message.

Change-Id: I08bae3d16e77af48fcccc2c936acce8fc0ef0f3c
---
M CHANGES
M configs/samples/pjsip.conf.sample
A contrib/ast-db-manage/config/versions/a1698e8bb9c5_add_incoming_mwi_mailbox.py
M include/asterisk/res_pjsip.h
M include/asterisk/strings.h
M main/strings.c
M res/res_pjsip.c
M res/res_pjsip/pjsip_configuration.c
M res/res_pjsip_pubsub.c
9 files changed, 198 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/80/6480/1

diff --git a/CHANGES b/CHANGES
index a8623e0..9b6c2b1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -30,6 +30,10 @@
    when dnsmgr refreshes are enabled will be automatically updated with the new
    IP address of a given hostname.
 
+ * A new endpoint parameter "incoming_mwi_mailbox" allows Asterisk to receive
+   unsolicited MWI NOTIFY requests and make them available to other modules via
+   the stasis message bus.
+
 res_musiconhold
 ------------------
  * By default, when res_musiconhold reloads or unloads, it sends a HUP signal
diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index f983a87..bc068de 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -780,6 +780,12 @@
                               ; The value "yes" is useful for some SIP phones
                               ; (Cisco SPA) to be able to indicate and pick up
                               ; ringing devices.
+;incoming_mwi_mailbox = ; Mailbox name to use when incoming MWI NOTIFYs are
+                        ; received.
+                        ; If an MWI NOTIFY is received FROM this endpoint,
+                        ; this mailbox will be used when notifying other modules
+                        ; of MWI status changes.  If not set, incoming MWI
+                        ; NOTIFYs are ignored.
 
 ;==========================AUTH SECTION OPTIONS=========================
 ;[auth]
diff --git a/contrib/ast-db-manage/config/versions/a1698e8bb9c5_add_incoming_mwi_mailbox.py b/contrib/ast-db-manage/config/versions/a1698e8bb9c5_add_incoming_mwi_mailbox.py
new file mode 100644
index 0000000..86c307e
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/a1698e8bb9c5_add_incoming_mwi_mailbox.py
@@ -0,0 +1,21 @@
+"""add_incoming_mwi_mailbox
+
+Revision ID: a1698e8bb9c5
+Revises: b83645976fdd
+Create Date: 2017-09-08 13:45:18.937571
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'a1698e8bb9c5'
+down_revision = 'b83645976fdd'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    op.add_column('ps_endpoints', sa.Column('incoming_mwi_mailbox', sa.String(40)))
+
+def downgrade():
+    op.drop_column('ps_endpoints', 'incoming_mwi_mailbox')
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 70b56ae..ac1267d 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -788,6 +788,8 @@
 	unsigned int refer_blind_progress;
 	/*! Whether to notifies dialog-info 'early' on INUSE && RINGING state */
 	unsigned int notify_early_inuse_ringing;
+	/*! If set, we'll push incoming MWI NOTIFYs to stasis using this mailbox */
+	AST_STRING_FIELD_EXTENDED(incoming_mwi_mailbox);
 };
 
 /*! URI parameter for symmetric transport */
diff --git a/include/asterisk/strings.h b/include/asterisk/strings.h
index 1200eb9..963519d 100644
--- a/include/asterisk/strings.h
+++ b/include/asterisk/strings.h
@@ -1383,4 +1383,24 @@
  */
 int ast_strings_match(const char *left, const char *op, const char *right);
 
+/*!
+ * \brief Read lines from a string buffer
+ * \since 13.18.0
+ *
+ * \param buffer [IN/OUT] A pointer to a char * string with either Unix or Windows line endings
+ *
+ * \return The "next" line
+ *
+ * \warning The original string and *buffer will be modified.
+ *
+ * \details
+ * Both '\n' and '\r\n' are treated as single delimiters but consecutive occurrances of
+ * the delimiters are NOT considered to be a single delimiter.  This preserves blank
+ * lines in the input.
+ *
+ * MacOS line endings ('\r') are not supported at this time.
+ *
+ */
+char *ast_read_line_from_buffer(char **buffer);
+
 #endif /* _ASTERISK_STRINGS_H */
diff --git a/main/strings.c b/main/strings.c
index 7f2025a..38b4c94 100644
--- a/main/strings.c
+++ b/main/strings.c
@@ -371,4 +371,23 @@
 	return 0;
 }
 
+char *ast_read_line_from_buffer(char **buffer)
+{
+	char *start = *buffer;
 
+	if (!buffer || !*buffer || *(*buffer) == '\0') {
+		return NULL;
+	}
+
+	while (*(*buffer) && *(*buffer) != '\n' ) {
+		(*buffer)++;
+	}
+
+	*(*buffer) = '\0';
+	if (*(*buffer - 1) == '\r') {
+		*(*buffer - 1) = '\0';
+	}
+	(*buffer)++;
+
+	return start;
+}
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 2db0668..310603e 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -985,6 +985,14 @@
 						on Ringing when already INUSE.
 					</para></description>
 				</configOption>
+				<configOption name="incoming_mwi_mailbox">
+					<synopsis>Mailbox name to use when incoming MWI NOTIFYs are received</synopsis>
+					<description><para>
+						If an MWI NOTIFY is received <emphasis>from</emphasis> this endpoint,
+						this mailbox will be used when notifying other modules of MWI status
+						changes.  If not set, incoming MWI NOTIFYs are ignored.
+					</para></description>
+				</configOption>
 			</configObject>
 			<configObject name="auth">
 				<synopsis>Authentication type</synopsis>
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 27dadb1..88ffadb 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1960,6 +1960,7 @@
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_overlap", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allow_overlap));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "refer_blind_progress", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, refer_blind_progress));
 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "notify_early_inuse_ringing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, notify_early_inuse_ringing));
+	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "incoming_mwi_mailbox", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, incoming_mwi_mailbox));
 
 	if (ast_sip_initialize_sorcery_transport()) {
 		ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
@@ -2123,6 +2124,9 @@
 		ao2_cleanup(endpoint);
 		return NULL;
 	}
+
+	ast_string_field_init_extended(endpoint, incoming_mwi_mailbox);
+
 	if (!(endpoint->media.codecs = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
 		ao2_cleanup(endpoint);
 		return NULL;
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index c62bddd..8dc780a 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -31,6 +31,7 @@
 #include <pjsip_simple.h>
 #include <pjlib.h>
 
+#include "asterisk/app.h"
 #include "asterisk/res_pjsip_pubsub.h"
 #include "asterisk/module.h"
 #include "asterisk/linkedlists.h"
@@ -3462,12 +3463,125 @@
 	return res;
 }
 
+struct simple_message_summary {
+	int messages_waiting;
+	int voice_messages_new;
+	int voice_messages_old;
+	int voice_messages_urgent_new;
+	int voice_messages_urgent_old;
+	char message_account[PJSIP_MAX_URL_SIZE];
+};
+
+static struct simple_message_summary *parse_simple_message_summary(char *body)
+{
+	char *line;
+	char *buffer;
+	struct simple_message_summary *summary;
+
+	if (ast_strlen_zero(body)) {
+		return NULL;
+	}
+
+	summary = ast_calloc(1, sizeof(*summary));
+	if (!summary) {
+		return NULL;
+	}
+	buffer = ast_strdupa(body);
+
+	while ((line = ast_read_line_from_buffer(&buffer))) {
+		line = ast_str_to_lower(line);
+
+		if (!sscanf(line, "voice-message: %d/%d (%d/%d)",
+			&summary->voice_messages_new, &summary->voice_messages_old,
+			&summary->voice_messages_urgent_new, &summary->voice_messages_urgent_old)) {
+			sscanf(line, "message-account: %s", summary->message_account);
+		}
+	}
+
+	return summary;
+}
+
+static pj_bool_t pubsub_on_rx_mwi_notify_request(pjsip_rx_data *rdata)
+{
+	RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
+	struct simple_message_summary *summary = NULL;
+	const char *endpoint_name;
+	char *atsign;
+	char *context;
+	char *body;
+	char *mailbox;
+	int rc;
+
+	endpoint = ast_pjsip_rdata_get_endpoint(rdata);
+	if (!endpoint) {
+		ast_debug(1, "Endpoint not found in rdata (%p)\n", rdata);
+		rc = 404;
+		goto error;
+	}
+
+	endpoint_name = ast_sorcery_object_get_id(endpoint);
+	ast_debug(1, "Found endpoint: %s\n", endpoint_name);
+	if (ast_strlen_zero(endpoint->incoming_mwi_mailbox)) {
+		ast_debug(1, "No incoming mailbox specified for endpoint '%s'\n", endpoint_name);
+		rc = 404;
+		goto error;
+	}
+
+	mailbox = ast_strdupa(endpoint->incoming_mwi_mailbox);
+	atsign = strchr(mailbox, '@');
+	if (!atsign) {
+		ast_debug(1, "No '@' found in endpoint %s's incoming mailbox '%s'.  Can't parse context\n",
+			endpoint_name, endpoint->incoming_mwi_mailbox);
+		rc = 404;
+		goto error;
+	}
+
+	*atsign = '\0';
+	context = atsign + 1;
+
+	body = ast_alloca(rdata->msg_info.msg->body->len + 1);
+	rdata->msg_info.msg->body->print_body(rdata->msg_info.msg->body, body,
+		rdata->msg_info.msg->body->len + 1);
+	summary = parse_simple_message_summary(body);
+	if (!summary) {
+		ast_debug(1, "Endpoint: '%s' There was an issue getting message info from body '%s'\n",
+			ast_sorcery_object_get_id(endpoint), body);
+		rc = 404;
+		goto error;
+	}
+
+	ast_debug(1, "Endpoint: '%s' Mailbox: %s Message-Account: %s Voice-Messages: %d/%d (%d/%d)\n",
+		endpoint_name, endpoint->incoming_mwi_mailbox, summary->message_account,
+		summary->voice_messages_new, summary->voice_messages_old,
+		summary->voice_messages_urgent_new, summary->voice_messages_urgent_old);
+
+	ast_publish_mwi_state(mailbox, context,
+		summary->voice_messages_new, summary->voice_messages_old);
+	rc = 200;
+
+error:
+	ast_free(summary);
+	pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, rc, NULL, NULL, NULL);
+	return PJ_TRUE;
+}
+
+static pj_bool_t pubsub_on_rx_notify_request(pjsip_rx_data *rdata)
+{
+	if (pj_stricmp2(&rdata->msg_info.msg->body->content_type.type, "application") == 0 &&
+		pj_stricmp2(&rdata->msg_info.msg->body->content_type.subtype, "simple-message-summary") == 0) {
+		return pubsub_on_rx_mwi_notify_request(rdata);
+	}
+	return PJ_FALSE;
+}
+
 static pj_bool_t pubsub_on_rx_request(pjsip_rx_data *rdata)
 {
 	if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, pjsip_get_subscribe_method())) {
 		return pubsub_on_rx_subscribe_request(rdata);
 	} else if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_publish_method)) {
 		return pubsub_on_rx_publish_request(rdata);
+	} else if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_notify_method)) {
+		return pubsub_on_rx_notify_request(rdata);
 	}
 
 	return PJ_FALSE;

-- 
To view, visit https://gerrit.asterisk.org/6480
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 13
Gerrit-MessageType: newchange
Gerrit-Change-Id: I08bae3d16e77af48fcccc2c936acce8fc0ef0f3c
Gerrit-Change-Number: 6480
Gerrit-PatchSet: 1
Gerrit-Owner: George Joseph <gjoseph at digium.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20170912/4e733770/attachment-0001.html>


More information about the asterisk-code-review mailing list