<p>Kevin Harwell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/11250">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">app.[ch], mwi core: Move core MWI functionality into its own files<br><br>There is enough MWI functionality to warrant it having its own 'c' and header<br>files. This patch moves all current core MWI data structures, and functions<br>into the following files:<br><br>main/mwi.h<br>main/mwi.c<br><br>Note, code was simply moved, and not modified. However, this patch is also in<br>preparation for core MWI changes, and additions to come.<br><br>Change-Id: I9dde8bfae1e7ec254fa63166e090f77e4d3097e0<br>---<br>M apps/app_minivm.c<br>M apps/app_voicemail.c<br>M channels/chan_dahdi.c<br>M channels/chan_iax2.c<br>M channels/chan_mgcp.c<br>M channels/chan_sip.c<br>M channels/chan_skinny.c<br>M channels/chan_unistim.c<br>M include/asterisk/app.h<br>A include/asterisk/mwi.h<br>M main/app.c<br>M main/asterisk.c<br>M main/manager.c<br>M main/manager_mwi.c<br>A main/mwi.c<br>M res/res_mwi_devstate.c<br>M res/res_mwi_external.c<br>M res/res_pjsip_mwi.c<br>M res/res_pjsip_publish_asterisk.c<br>M res/res_pjsip_pubsub.c<br>M res/res_smdi.c<br>M res/res_xmpp.c<br>22 files changed, 630 insertions(+), 531 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/50/11250/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_minivm.c b/apps/app_minivm.c</span><br><span>index ef73cab..dae033f 100644</span><br><span>--- a/apps/app_minivm.c</span><br><span>+++ b/apps/app_minivm.c</span><br><span>@@ -166,6 +166,7 @@</span><br><span> #include "asterisk/say.h"</span><br><span> #include "asterisk/module.h"</span><br><span> #include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/dsp.h"</span><br><span> #include "asterisk/localtime.h"</span><br><span> #include "asterisk/cli.h"</span><br><span>diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c</span><br><span>index 64167d1..d83587f 100644</span><br><span>--- a/apps/app_voicemail.c</span><br><span>+++ b/apps/app_voicemail.c</span><br><span>@@ -122,6 +122,7 @@</span><br><span> #include "asterisk/module.h"</span><br><span> #include "asterisk/adsi.h"</span><br><span> #include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/manager.h"</span><br><span> #include "asterisk/dsp.h"</span><br><span> #include "asterisk/localtime.h"</span><br><span>diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c</span><br><span>index 1f769c9..d425b32 100644</span><br><span>--- a/channels/chan_dahdi.c</span><br><span>+++ b/channels/chan_dahdi.c</span><br><span>@@ -110,7 +110,7 @@</span><br><span> #include "asterisk/musiconhold.h"</span><br><span> #include "asterisk/say.h"</span><br><span> #include "asterisk/tdd.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/dsp.h"</span><br><span> #include "asterisk/astdb.h"</span><br><span> #include "asterisk/manager.h"</span><br><span>diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c</span><br><span>index b485fd1..83d9711 100644</span><br><span>--- a/channels/chan_iax2.c</span><br><span>+++ b/channels/chan_iax2.c</span><br><span>@@ -95,6 +95,7 @@</span><br><span> #include "asterisk/manager.h"</span><br><span> #include "asterisk/callerid.h"</span><br><span> #include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/astdb.h"</span><br><span> #include "asterisk/musiconhold.h"</span><br><span> #include "asterisk/features.h"</span><br><span>diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c</span><br><span>index 5b3089b..c0f522d 100644</span><br><span>--- a/channels/chan_mgcp.c</span><br><span>+++ b/channels/chan_mgcp.c</span><br><span>@@ -71,6 +71,7 @@</span><br><span> #include "asterisk/astdb.h"</span><br><span> #include "asterisk/features.h"</span><br><span> #include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/musiconhold.h"</span><br><span> #include "asterisk/utils.h"</span><br><span> #include "asterisk/netsock2.h"</span><br><span>diff --git a/channels/chan_sip.c b/channels/chan_sip.c</span><br><span>index 6836db3..7c8928d 100644</span><br><span>--- a/channels/chan_sip.c</span><br><span>+++ b/channels/chan_sip.c</span><br><span>@@ -276,7 +276,7 @@</span><br><span> #include "sip/include/security_events.h"</span><br><span> #include "sip/include/route.h"</span><br><span> #include "asterisk/sip_api.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/bridge.h"</span><br><span> #include "asterisk/stasis.h"</span><br><span> #include "asterisk/stasis_endpoints.h"</span><br><span>diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c</span><br><span>index 9c63da9..c3044c2 100644</span><br><span>--- a/channels/chan_skinny.c</span><br><span>+++ b/channels/chan_skinny.c</span><br><span>@@ -71,6 +71,7 @@</span><br><span> #include "asterisk/causes.h"</span><br><span> #include "asterisk/pickup.h"</span><br><span> #include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/musiconhold.h"</span><br><span> #include "asterisk/utils.h"</span><br><span> #include "asterisk/dsp.h"</span><br><span>diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c</span><br><span>index 1809c8a..b846585 100644</span><br><span>--- a/channels/chan_unistim.c</span><br><span>+++ b/channels/chan_unistim.c</span><br><span>@@ -69,6 +69,7 @@</span><br><span> #include "asterisk/callerid.h"</span><br><span> #include "asterisk/cli.h"</span><br><span> #include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/musiconhold.h"</span><br><span> #include "asterisk/causes.h"</span><br><span> #include "asterisk/indications.h"</span><br><span>diff --git a/include/asterisk/app.h b/include/asterisk/app.h</span><br><span>index 0865121..df3990f 100644</span><br><span>--- a/include/asterisk/app.h</span><br><span>+++ b/include/asterisk/app.h</span><br><span>@@ -1470,200 +1470,6 @@</span><br><span> int ast_app_parse_timelen(const char *timestr, int *result, enum ast_timelen defunit);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Publish a MWI state update via stasis</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] new_msgs The number of new messages in this mailbox</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] old_msgs The number of old messages in this mailbox</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 Success</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval -1 Failure</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs) \</span><br><span style="color: hsl(0, 100%, 40%);">-   ast_publish_mwi_state_full(mailbox, context, new_msgs, old_msgs, NULL, NULL)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Publish a MWI state update associated with some channel</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] new_msgs The number of new messages in this mailbox</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] old_msgs The number of old messages in this mailbox</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] channel_id A unique identifier for a channel associated with this</span><br><span style="color: hsl(0, 100%, 40%);">- * change in mailbox state</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 Success</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval -1 Failure</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-#define ast_publish_mwi_state_channel(mailbox, context, new_msgs, old_msgs, channel_id) \</span><br><span style="color: hsl(0, 100%, 40%);">-      ast_publish_mwi_state_full(mailbox, context, new_msgs, old_msgs, channel_id, NULL)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Publish a MWI state update via stasis with all parameters</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] new_msgs The number of new messages in this mailbox</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] old_msgs The number of old messages in this mailbox</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] channel_id A unique identifier for a channel associated with this</span><br><span style="color: hsl(0, 100%, 40%);">- * change in mailbox state</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] eid The EID of the server that originally published the message</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 Success</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval -1 Failure</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-int ast_publish_mwi_state_full(</span><br><span style="color: hsl(0, 100%, 40%);">-   const char *mailbox,</span><br><span style="color: hsl(0, 100%, 40%);">-    const char *context,</span><br><span style="color: hsl(0, 100%, 40%);">-    int new_msgs,</span><br><span style="color: hsl(0, 100%, 40%);">-   int old_msgs,</span><br><span style="color: hsl(0, 100%, 40%);">-   const char *channel_id,</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_eid *eid);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12.2.0</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Delete MWI state cached by stasis</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 Success</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval -1 Failure</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-#define ast_delete_mwi_state(mailbox, context) \</span><br><span style="color: hsl(0, 100%, 40%);">-   ast_delete_mwi_state_full(mailbox, context, NULL)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12.2.0</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Delete MWI state cached by stasis with all parameters</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] eid The EID of the server that originally published the message</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 Success</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval -1 Failure</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-int ast_delete_mwi_state_full(const char *mailbox, const char *context, struct ast_eid *eid);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \addtogroup StasisTopicsAndMessages</span><br><span style="color: hsl(0, 100%, 40%);">- * @{</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief The structure that contains MWI state</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_mwi_state {</span><br><span style="color: hsl(0, 100%, 40%);">-   AST_DECLARE_STRING_FIELDS(</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_STRING_FIELD(uniqueid);  /*!< Unique identifier for this mailbox */</span><br><span style="color: hsl(0, 100%, 40%);">-      );</span><br><span style="color: hsl(0, 100%, 40%);">-      int new_msgs;                    /*!< The current number of new messages for this mailbox */</span><br><span style="color: hsl(0, 100%, 40%);">- int old_msgs;                    /*!< The current number of old messages for this mailbox */</span><br><span style="color: hsl(0, 100%, 40%);">- /*! If applicable, a snapshot of the channel that caused this MWI change */</span><br><span style="color: hsl(0, 100%, 40%);">-     struct ast_channel_snapshot *snapshot;</span><br><span style="color: hsl(0, 100%, 40%);">-  struct ast_eid eid;              /*!< The EID of the server where this message originated */</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Object that represents an MWI update with some additional application</span><br><span style="color: hsl(0, 100%, 40%);">- * defined data</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_mwi_blob {</span><br><span style="color: hsl(0, 100%, 40%);">-      struct ast_mwi_state *mwi_state;    /*!< MWI state */</span><br><span style="color: hsl(0, 100%, 40%);">-        struct ast_json *blob;              /*!< JSON blob of data */</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Create a \ref ast_mwi_state object</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval \ref ast_mwi_state object on success</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval NULL on error</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_mwi_state *ast_mwi_create(const char *mailbox, const char *context);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Creates a \ref ast_mwi_blob message.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * The \a blob JSON object requires a \c "type" field describing the blob. It</span><br><span style="color: hsl(0, 100%, 40%);">- * should also be treated as immutable and not modified after it is put into the</span><br><span style="color: hsl(0, 100%, 40%);">- * message.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param mwi_state MWI state associated with the update</span><br><span style="color: hsl(0, 100%, 40%);">- * \param message_type The type of message to create</span><br><span style="color: hsl(0, 100%, 40%);">- * \param blob JSON object representing the data.</span><br><span style="color: hsl(0, 100%, 40%);">- * \return \ref ast_mwi_blob message.</span><br><span style="color: hsl(0, 100%, 40%);">- * \return \c NULL on error</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_message *ast_mwi_blob_create(struct ast_mwi_state *mwi_state,</span><br><span style="color: hsl(0, 100%, 40%);">-                                         struct stasis_message_type *message_type,</span><br><span style="color: hsl(0, 100%, 40%);">-                                       struct ast_json *blob);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Get the \ref stasis topic for MWI messages</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval The topic structure for MWI messages</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval NULL if it has not been allocated</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_topic *ast_mwi_topic_all(void);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Get the \ref stasis topic for MWI messages on a unique ID</span><br><span style="color: hsl(0, 100%, 40%);">- * \param uniqueid The unique id for which to get the topic</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval The topic structure for MWI messages for a given uniqueid</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval NULL if it failed to be found or allocated</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_topic *ast_mwi_topic(const char *uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Get the \ref stasis caching topic for MWI messages</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval The caching topic structure for MWI messages</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval NULL if it has not been allocated</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_topic *ast_mwi_topic_cached(void);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Backend cache for ast_mwi_topic_cached().</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval Cache of \ref ast_mwi_state.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_cache *ast_mwi_state_cache(void);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Get the \ref stasis message type for MWI messages</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval The message type structure for MWI messages</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval NULL on error</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_message_type *ast_mwi_state_type(void);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Get the \ref stasis message type for voicemail application specific messages</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This message type exists for those messages a voicemail application may wish to send</span><br><span style="color: hsl(0, 100%, 40%);">- * that have no logical relationship with other voicemail applications. Voicemail apps</span><br><span style="color: hsl(0, 100%, 40%);">- * that use this message type must pass a \ref ast_mwi_blob. Any extraneous information</span><br><span style="color: hsl(0, 100%, 40%);">- * in the JSON blob must be packed as key/value pair tuples of strings.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * At least one key/value tuple must have a key value of "Event".</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval The \ref stasis_message_type for voicemail application specific messages</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval NULL on error</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_message_type *ast_mwi_vm_app_type(void);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span>  * \brief Get the \ref stasis topic for queue messages</span><br><span>  * \retval The topic structure for queue messages</span><br><span>  * \retval NULL if it has not been allocated</span><br><span>@@ -1689,7 +1495,6 @@</span><br><span>  */</span><br><span> int app_init(void);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define AST_MAX_MAILBOX_UNIQUEID (AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2)</span><br><span> #if defined(__cplusplus) || defined(c_plusplus)</span><br><span> }</span><br><span> #endif</span><br><span>diff --git a/include/asterisk/mwi.h b/include/asterisk/mwi.h</span><br><span>new file mode 100644</span><br><span>index 0000000..9e463d2</span><br><span>--- /dev/null</span><br><span>+++ b/include/asterisk/mwi.h</span><br><span>@@ -0,0 +1,242 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2019, Digium, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Kevin Harwell <kharwell@digium.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(120, 100%, 40%);">+ * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(120, 100%, 40%);">+ * channels for your use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software, distributed under the terms of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(120, 100%, 40%);">+ * at the top of the source tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef _ASTERISK_MWI_H</span><br><span style="color: hsl(120, 100%, 40%);">+#define _ASTERISK_MWI_H</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/utils.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__cplusplus) || defined(c_plusplus)</span><br><span style="color: hsl(120, 100%, 40%);">+extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_json;</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_message_type;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Publish a MWI state update via stasis</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] new_msgs The number of new messages in this mailbox</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] old_msgs The number of old messages in this mailbox</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 Failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs) \</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_publish_mwi_state_full(mailbox, context, new_msgs, old_msgs, NULL, NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Publish a MWI state update associated with some channel</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] new_msgs The number of new messages in this mailbox</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] old_msgs The number of old messages in this mailbox</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] channel_id A unique identifier for a channel associated with this</span><br><span style="color: hsl(120, 100%, 40%);">+ * change in mailbox state</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 Failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define ast_publish_mwi_state_channel(mailbox, context, new_msgs, old_msgs, channel_id) \</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_publish_mwi_state_full(mailbox, context, new_msgs, old_msgs, channel_id, NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Publish a MWI state update via stasis with all parameters</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] new_msgs The number of new messages in this mailbox</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] old_msgs The number of old messages in this mailbox</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] channel_id A unique identifier for a channel associated with this</span><br><span style="color: hsl(120, 100%, 40%);">+ * change in mailbox state</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] eid The EID of the server that originally published the message</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 Failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_publish_mwi_state_full(</span><br><span style="color: hsl(120, 100%, 40%);">+       const char *mailbox,</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *context,</span><br><span style="color: hsl(120, 100%, 40%);">+  int new_msgs,</span><br><span style="color: hsl(120, 100%, 40%);">+ int old_msgs,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *channel_id,</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_eid *eid);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12.2.0</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Delete MWI state cached by stasis</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 Failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define ast_delete_mwi_state(mailbox, context) \</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_delete_mwi_state_full(mailbox, context, NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12.2.0</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Delete MWI state cached by stasis with all parameters</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] eid The EID of the server that originally published the message</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 Failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_delete_mwi_state_full(const char *mailbox, const char *context, struct ast_eid *eid);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \addtogroup StasisTopicsAndMessages</span><br><span style="color: hsl(120, 100%, 40%);">+ * @{</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief The structure that contains MWI state</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_mwi_state {</span><br><span style="color: hsl(120, 100%, 40%);">+   AST_DECLARE_STRING_FIELDS(</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_STRING_FIELD(uniqueid);  /*!< Unique identifier for this mailbox */</span><br><span style="color: hsl(120, 100%, 40%);">+    );</span><br><span style="color: hsl(120, 100%, 40%);">+    int new_msgs;                    /*!< The current number of new messages for this mailbox */</span><br><span style="color: hsl(120, 100%, 40%);">+       int old_msgs;                    /*!< The current number of old messages for this mailbox */</span><br><span style="color: hsl(120, 100%, 40%);">+       /*! If applicable, a snapshot of the channel that caused this MWI change */</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_channel_snapshot *snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_eid eid;              /*!< The EID of the server where this message originated */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Object that represents an MWI update with some additional application</span><br><span style="color: hsl(120, 100%, 40%);">+ * defined data</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_mwi_blob {</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_mwi_state *mwi_state;    /*!< MWI state */</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_json *blob;              /*!< JSON blob of data */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Create a \ref ast_mwi_state object</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval \ref ast_mwi_state object on success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL on error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_mwi_state *ast_mwi_create(const char *mailbox, const char *context);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Creates a \ref ast_mwi_blob message.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The \a blob JSON object requires a \c "type" field describing the blob. It</span><br><span style="color: hsl(120, 100%, 40%);">+ * should also be treated as immutable and not modified after it is put into the</span><br><span style="color: hsl(120, 100%, 40%);">+ * message.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param mwi_state MWI state associated with the update</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param message_type The type of message to create</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param blob JSON object representing the data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return \ref ast_mwi_blob message.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return \c NULL on error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_message *ast_mwi_blob_create(struct ast_mwi_state *mwi_state,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     struct stasis_message_type *message_type,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     struct ast_json *blob);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the \ref stasis topic for MWI messages</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval The topic structure for MWI messages</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL if it has not been allocated</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_topic *ast_mwi_topic_all(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the \ref stasis topic for MWI messages on a unique ID</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param uniqueid The unique id for which to get the topic</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval The topic structure for MWI messages for a given uniqueid</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL if it failed to be found or allocated</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_topic *ast_mwi_topic(const char *uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the \ref stasis caching topic for MWI messages</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval The caching topic structure for MWI messages</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL if it has not been allocated</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_topic *ast_mwi_topic_cached(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Backend cache for ast_mwi_topic_cached().</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval Cache of \ref ast_mwi_state.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_cache *ast_mwi_state_cache(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the \ref stasis message type for MWI messages</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval The message type structure for MWI messages</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL on error</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_message_type *ast_mwi_state_type(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the \ref stasis message type for voicemail application specific messages</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This message type exists for those messages a voicemail application may wish to send</span><br><span style="color: hsl(120, 100%, 40%);">+ * that have no logical relationship with other voicemail applications. Voicemail apps</span><br><span style="color: hsl(120, 100%, 40%);">+ * that use this message type must pass a \ref ast_mwi_blob. Any extraneous information</span><br><span style="color: hsl(120, 100%, 40%);">+ * in the JSON blob must be packed as key/value pair tuples of strings.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * At least one key/value tuple must have a key value of "Event".</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval The \ref stasis_message_type for voicemail application specific messages</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL on error</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_message_type *ast_mwi_vm_app_type(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Initialize the mwi core</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 Failure</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 13.26.0</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 16.4.0</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int mwi_init(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define AST_MAX_MAILBOX_UNIQUEID (AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#if defined(__cplusplus) || defined(c_plusplus)</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* _ASTERISK_MWI_H */</span><br><span>diff --git a/main/app.c b/main/app.c</span><br><span>index 623843a..5fb81ba 100644</span><br><span>--- a/main/app.c</span><br><span>+++ b/main/app.c</span><br><span>@@ -72,8 +72,6 @@</span><br><span> #include "asterisk/json.h"</span><br><span> #include "asterisk/format_cache.h"</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define MWI_TOPIC_BUCKETS 57</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> AST_THREADSTORAGE_PUBLIC(ast_str_thread_global_buf);</span><br><span> </span><br><span> static pthread_t shaun_of_the_dead_thread = AST_PTHREADT_NULL;</span><br><span>@@ -88,57 +86,10 @@</span><br><span> /*</span><br><span>  * @{ \brief Define \ref stasis topic objects</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct stasis_topic *mwi_topic_all;</span><br><span style="color: hsl(0, 100%, 40%);">-static struct stasis_cache *mwi_state_cache;</span><br><span style="color: hsl(0, 100%, 40%);">-static struct stasis_caching_topic *mwi_topic_cached;</span><br><span style="color: hsl(0, 100%, 40%);">-static struct stasis_topic_pool *mwi_topic_pool;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static struct stasis_topic *queue_topic_all;</span><br><span> static struct stasis_topic_pool *queue_topic_pool;</span><br><span> /* @} */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Convert a MWI \ref stasis_message to a \ref ast_event */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_event *mwi_to_event(struct stasis_message *message)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    struct ast_event *event;</span><br><span style="color: hsl(0, 100%, 40%);">-        struct ast_mwi_state *mwi_state;</span><br><span style="color: hsl(0, 100%, 40%);">-        char *mailbox;</span><br><span style="color: hsl(0, 100%, 40%);">-  char *context;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!message) {</span><br><span style="color: hsl(0, 100%, 40%);">-         return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       mwi_state = stasis_message_data(message);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* Strip off @context */</span><br><span style="color: hsl(0, 100%, 40%);">-        context = mailbox = ast_strdupa(mwi_state->uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">-        strsep(&context, "@");</span><br><span style="color: hsl(0, 100%, 40%);">-    if (ast_strlen_zero(context)) {</span><br><span style="color: hsl(0, 100%, 40%);">-         context = "default";</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       event = ast_event_new(AST_EVENT_MWI,</span><br><span style="color: hsl(0, 100%, 40%);">-                            AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,</span><br><span style="color: hsl(0, 100%, 40%);">-                         AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,</span><br><span style="color: hsl(0, 100%, 40%);">-                         AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, mwi_state->new_msgs,</span><br><span style="color: hsl(0, 100%, 40%);">-                         AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, mwi_state->old_msgs,</span><br><span style="color: hsl(0, 100%, 40%);">-                         AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, &mwi_state->eid, sizeof(mwi_state->eid),</span><br><span style="color: hsl(0, 100%, 40%);">-                           AST_EVENT_IE_END);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      return event;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*</span><br><span style="color: hsl(0, 100%, 40%);">- * @{ \brief Define \ref stasis message types for MWI</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-STASIS_MESSAGE_TYPE_DEFN(ast_mwi_state_type,</span><br><span style="color: hsl(0, 100%, 40%);">-    .to_event = mwi_to_event, );</span><br><span style="color: hsl(0, 100%, 40%);">-STASIS_MESSAGE_TYPE_DEFN(ast_mwi_vm_app_type);</span><br><span style="color: hsl(0, 100%, 40%);">-/* @} */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static void *shaun_of_the_dead(void *data)</span><br><span> {</span><br><span>        struct zombie *cur;</span><br><span>@@ -3161,255 +3112,6 @@</span><br><span>        return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void mwi_state_dtor(void *obj)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        struct ast_mwi_state *mwi_state = obj;</span><br><span style="color: hsl(0, 100%, 40%);">-  ast_string_field_free_memory(mwi_state);</span><br><span style="color: hsl(0, 100%, 40%);">-        ao2_cleanup(mwi_state->snapshot);</span><br><span style="color: hsl(0, 100%, 40%);">-    mwi_state->snapshot = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_topic *ast_mwi_topic_all(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    return mwi_topic_all;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_cache *ast_mwi_state_cache(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   return mwi_state_cache;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_topic *ast_mwi_topic_cached(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        return stasis_caching_get_topic(mwi_topic_cached);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_topic *ast_mwi_topic(const char *uniqueid)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    return stasis_topic_pool_get_topic(mwi_topic_pool, uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_mwi_state *ast_mwi_create(const char *mailbox, const char *context)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   struct ast_mwi_state *mwi_state;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        ast_assert(!ast_strlen_zero(mailbox));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  mwi_state = ao2_alloc(sizeof(*mwi_state), mwi_state_dtor);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!mwi_state) {</span><br><span style="color: hsl(0, 100%, 40%);">-               return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (ast_string_field_init(mwi_state, 256)) {</span><br><span style="color: hsl(0, 100%, 40%);">-            ao2_ref(mwi_state, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-         return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!ast_strlen_zero(context)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_string_field_build(mwi_state, uniqueid, "%s@%s", mailbox, context);</span><br><span style="color: hsl(0, 100%, 40%);">-       } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_string_field_set(mwi_state, uniqueid, mailbox);</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return mwi_state;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \internal</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Create a MWI state snapshot message.</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12.2.0</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] new_msgs The number of new messages in this mailbox</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] old_msgs The number of old messages in this mailbox</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] channel_id A unique identifier for a channel associated with this</span><br><span style="color: hsl(0, 100%, 40%);">- * change in mailbox state</span><br><span style="color: hsl(0, 100%, 40%);">- * \param[in] eid The EID of the server that originally published the message</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval message on success.  Use ao2_cleanup() when done with it.</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval NULL on error.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct stasis_message *mwi_state_create_message(</span><br><span style="color: hsl(0, 100%, 40%);">-    const char *mailbox,</span><br><span style="color: hsl(0, 100%, 40%);">-    const char *context,</span><br><span style="color: hsl(0, 100%, 40%);">-    int new_msgs,</span><br><span style="color: hsl(0, 100%, 40%);">-   int old_msgs,</span><br><span style="color: hsl(0, 100%, 40%);">-   const char *channel_id,</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_eid *eid)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   struct ast_mwi_state *mwi_state;</span><br><span style="color: hsl(0, 100%, 40%);">-        struct stasis_message *message;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_mwi_state_type()) {</span><br><span style="color: hsl(0, 100%, 40%);">-            return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       mwi_state = ast_mwi_create(mailbox, context);</span><br><span style="color: hsl(0, 100%, 40%);">-   if (!mwi_state) {</span><br><span style="color: hsl(0, 100%, 40%);">-               return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       mwi_state->new_msgs = new_msgs;</span><br><span style="color: hsl(0, 100%, 40%);">-      mwi_state->old_msgs = old_msgs;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!ast_strlen_zero(channel_id)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             struct stasis_message *chan_message;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-            chan_message = stasis_cache_get(ast_channel_cache(), ast_channel_snapshot_type(),</span><br><span style="color: hsl(0, 100%, 40%);">-                       channel_id);</span><br><span style="color: hsl(0, 100%, 40%);">-            if (chan_message) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     mwi_state->snapshot = stasis_message_data(chan_message);</span><br><span style="color: hsl(0, 100%, 40%);">-                     ao2_ref(mwi_state->snapshot, +1);</span><br><span style="color: hsl(0, 100%, 40%);">-            }</span><br><span style="color: hsl(0, 100%, 40%);">-               ao2_cleanup(chan_message);</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (eid) {</span><br><span style="color: hsl(0, 100%, 40%);">-              mwi_state->eid = *eid;</span><br><span style="color: hsl(0, 100%, 40%);">-       } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                mwi_state->eid = ast_eid_default;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /*</span><br><span style="color: hsl(0, 100%, 40%);">-       * XXX As far as stasis is concerned, all MWI events are local.</span><br><span style="color: hsl(0, 100%, 40%);">-  *</span><br><span style="color: hsl(0, 100%, 40%);">-       * We may in the future want to make MWI aggregate local/remote</span><br><span style="color: hsl(0, 100%, 40%);">-  * message counts similar to how device state aggregates state.</span><br><span style="color: hsl(0, 100%, 40%);">-  */</span><br><span style="color: hsl(0, 100%, 40%);">-     message = stasis_message_create_full(ast_mwi_state_type(), mwi_state, &ast_eid_default);</span><br><span style="color: hsl(0, 100%, 40%);">-    ao2_cleanup(mwi_state);</span><br><span style="color: hsl(0, 100%, 40%);">- return message;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-int ast_publish_mwi_state_full(</span><br><span style="color: hsl(0, 100%, 40%);">- const char *mailbox,</span><br><span style="color: hsl(0, 100%, 40%);">-    const char *context,</span><br><span style="color: hsl(0, 100%, 40%);">-    int new_msgs,</span><br><span style="color: hsl(0, 100%, 40%);">-   int old_msgs,</span><br><span style="color: hsl(0, 100%, 40%);">-   const char *channel_id,</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_eid *eid)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   struct ast_mwi_state *mwi_state;</span><br><span style="color: hsl(0, 100%, 40%);">-        RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-  struct stasis_topic *mailbox_specific_topic;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    message = mwi_state_create_message(mailbox, context, new_msgs, old_msgs, channel_id, eid);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!message) {</span><br><span style="color: hsl(0, 100%, 40%);">-         return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       mwi_state = stasis_message_data(message);</span><br><span style="color: hsl(0, 100%, 40%);">-       mailbox_specific_topic = ast_mwi_topic(mwi_state->uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mailbox_specific_topic) {</span><br><span style="color: hsl(0, 100%, 40%);">-          return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       stasis_publish(mailbox_specific_topic, message);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-int ast_delete_mwi_state_full(const char *mailbox, const char *context, struct ast_eid *eid)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-      struct stasis_message *cached_msg;</span><br><span style="color: hsl(0, 100%, 40%);">-      struct stasis_message *clear_msg;</span><br><span style="color: hsl(0, 100%, 40%);">-       struct ast_mwi_state *mwi_state;</span><br><span style="color: hsl(0, 100%, 40%);">-        struct stasis_topic *mailbox_specific_topic;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    msg = mwi_state_create_message(mailbox, context, 0, 0, NULL, eid);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!msg) {</span><br><span style="color: hsl(0, 100%, 40%);">-             return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       mwi_state = stasis_message_data(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   /*</span><br><span style="color: hsl(0, 100%, 40%);">-       * XXX As far as stasis is concerned, all MWI events are local.</span><br><span style="color: hsl(0, 100%, 40%);">-  *</span><br><span style="color: hsl(0, 100%, 40%);">-       * For now, it is assumed that there is only one entity</span><br><span style="color: hsl(0, 100%, 40%);">-  * maintaining the state of a particular mailbox.</span><br><span style="color: hsl(0, 100%, 40%);">-        *</span><br><span style="color: hsl(0, 100%, 40%);">-       * If we ever have multiple MWI event entities maintaining</span><br><span style="color: hsl(0, 100%, 40%);">-       * the same mailbox that wish to delete their cached entry</span><br><span style="color: hsl(0, 100%, 40%);">-       * we will need to do something about the race condition</span><br><span style="color: hsl(0, 100%, 40%);">-         * potential between checking the cache and removing the</span><br><span style="color: hsl(0, 100%, 40%);">-         * cache entry.</span><br><span style="color: hsl(0, 100%, 40%);">-  */</span><br><span style="color: hsl(0, 100%, 40%);">-     cached_msg = stasis_cache_get_by_eid(ast_mwi_state_cache(),</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_mwi_state_type(), mwi_state->uniqueid, &ast_eid_default);</span><br><span style="color: hsl(0, 100%, 40%);">-    if (!cached_msg) {</span><br><span style="color: hsl(0, 100%, 40%);">-              /* Nothing to clear */</span><br><span style="color: hsl(0, 100%, 40%);">-          return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-       ao2_cleanup(cached_msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        mailbox_specific_topic = ast_mwi_topic(mwi_state->uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mailbox_specific_topic) {</span><br><span style="color: hsl(0, 100%, 40%);">-          return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       clear_msg = stasis_cache_clear_create(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (clear_msg) {</span><br><span style="color: hsl(0, 100%, 40%);">-                stasis_publish(mailbox_specific_topic, clear_msg);</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       ao2_cleanup(clear_msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static const char *mwi_state_get_id(struct stasis_message *message)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  if (ast_mwi_state_type() == stasis_message_type(message)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             struct ast_mwi_state *mwi_state = stasis_message_data(message);</span><br><span style="color: hsl(0, 100%, 40%);">-         return mwi_state->uniqueid;</span><br><span style="color: hsl(0, 100%, 40%);">-  } else if (stasis_subscription_change_type() == stasis_message_type(message)) {</span><br><span style="color: hsl(0, 100%, 40%);">-         struct stasis_subscription_change *change = stasis_message_data(message);</span><br><span style="color: hsl(0, 100%, 40%);">-               return change->uniqueid;</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void mwi_blob_dtor(void *obj)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      struct ast_mwi_blob *mwi_blob = obj;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    ao2_cleanup(mwi_blob->mwi_state);</span><br><span style="color: hsl(0, 100%, 40%);">-    ast_json_unref(mwi_blob->blob);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_message *ast_mwi_blob_create(struct ast_mwi_state *mwi_state,</span><br><span style="color: hsl(0, 100%, 40%);">-                                         struct stasis_message_type *message_type,</span><br><span style="color: hsl(0, 100%, 40%);">-                                               struct ast_json *blob)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  struct ast_mwi_blob *obj;</span><br><span style="color: hsl(0, 100%, 40%);">-       struct stasis_message *msg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     ast_assert(blob != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!message_type) {</span><br><span style="color: hsl(0, 100%, 40%);">-            return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       obj = ao2_alloc(sizeof(*obj), mwi_blob_dtor);</span><br><span style="color: hsl(0, 100%, 40%);">-   if (!obj) {</span><br><span style="color: hsl(0, 100%, 40%);">-             return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       obj->mwi_state = mwi_state;</span><br><span style="color: hsl(0, 100%, 40%);">-  ao2_ref(obj->mwi_state, +1);</span><br><span style="color: hsl(0, 100%, 40%);">- obj->blob = ast_json_ref(blob);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      /* This is not a normal MWI event.  Only used by the MinivmNotify app. */</span><br><span style="color: hsl(0, 100%, 40%);">-       msg = stasis_message_create(message_type, obj);</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(obj, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return msg;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> struct stasis_topic *ast_queue_topic_all(void)</span><br><span> {</span><br><span>  return queue_topic_all;</span><br><span>@@ -3426,43 +3128,12 @@</span><br><span>    queue_topic_pool = NULL;</span><br><span>     ao2_cleanup(queue_topic_all);</span><br><span>        queue_topic_all = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_cleanup(mwi_topic_pool);</span><br><span style="color: hsl(0, 100%, 40%);">-    mwi_topic_pool = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-  ao2_cleanup(mwi_topic_all);</span><br><span style="color: hsl(0, 100%, 40%);">-     mwi_topic_all = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-   ao2_cleanup(mwi_state_cache);</span><br><span style="color: hsl(0, 100%, 40%);">-   mwi_state_cache = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- mwi_topic_cached = stasis_caching_unsubscribe_and_join(mwi_topic_cached);</span><br><span style="color: hsl(0, 100%, 40%);">-       STASIS_MESSAGE_TYPE_CLEANUP(ast_mwi_state_type);</span><br><span style="color: hsl(0, 100%, 40%);">-        STASIS_MESSAGE_TYPE_CLEANUP(ast_mwi_vm_app_type);</span><br><span> }</span><br><span> </span><br><span> int app_init(void)</span><br><span> {</span><br><span>        ast_register_cleanup(app_cleanup);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  if (STASIS_MESSAGE_TYPE_INIT(ast_mwi_state_type) != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (STASIS_MESSAGE_TYPE_INIT(ast_mwi_vm_app_type) != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-               return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-       mwi_topic_all = stasis_topic_create("mwi:all");</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!mwi_topic_all) {</span><br><span style="color: hsl(0, 100%, 40%);">-           return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-       mwi_state_cache = stasis_cache_create(mwi_state_get_id);</span><br><span style="color: hsl(0, 100%, 40%);">-        if (!mwi_state_cache) {</span><br><span style="color: hsl(0, 100%, 40%);">-         return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-       mwi_topic_cached = stasis_caching_topic_create(mwi_topic_all, mwi_state_cache);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!mwi_topic_cached) {</span><br><span style="color: hsl(0, 100%, 40%);">-                return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-       mwi_topic_pool = stasis_topic_pool_create(mwi_topic_all);</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!mwi_topic_pool) {</span><br><span style="color: hsl(0, 100%, 40%);">-          return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span>    queue_topic_all = stasis_topic_create("queue:all");</span><br><span>        if (!queue_topic_all) {</span><br><span>              return -1;</span><br><span>diff --git a/main/asterisk.c b/main/asterisk.c</span><br><span>index ac5b1d6..30b84e6 100644</span><br><span>--- a/main/asterisk.c</span><br><span>+++ b/main/asterisk.c</span><br><span>@@ -217,6 +217,7 @@</span><br><span> #include "asterisk/http.h"</span><br><span> #include "asterisk/udptl.h"</span><br><span> #include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/lock.h"</span><br><span> #include "asterisk/utils.h"</span><br><span> #include "asterisk/file.h"</span><br><span>@@ -4245,6 +4246,7 @@</span><br><span>      read_pjproject_startup_options();</span><br><span>    check_init(ast_pj_init(), "Embedded PJProject");</span><br><span>   check_init(app_init(), "App Core");</span><br><span style="color: hsl(120, 100%, 40%);">+ check_init(mwi_init(), "MWI Core");</span><br><span>        check_init(devstate_init(), "Device State Core");</span><br><span>  check_init(ast_msg_init(), "Messaging API");</span><br><span>       check_init(ast_data_init(), "Data Retrieval API");</span><br><span>diff --git a/main/manager.c b/main/manager.c</span><br><span>index cb9a713..0cd9ed5 100644</span><br><span>--- a/main/manager.c</span><br><span>+++ b/main/manager.c</span><br><span>@@ -73,6 +73,7 @@</span><br><span> #include "asterisk/lock.h"</span><br><span> #include "asterisk/cli.h"</span><br><span> #include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/pbx.h"</span><br><span> #include "asterisk/md5.h"</span><br><span> #include "asterisk/acl.h"</span><br><span>diff --git a/main/manager_mwi.c b/main/manager_mwi.c</span><br><span>index 8facc90..b8bc594 100644</span><br><span>--- a/main/manager_mwi.c</span><br><span>+++ b/main/manager_mwi.c</span><br><span>@@ -29,6 +29,7 @@</span><br><span> </span><br><span> #include "asterisk/manager.h"</span><br><span> #include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/channel.h"</span><br><span> #include "asterisk/stasis_message_router.h"</span><br><span> #include "asterisk/stasis.h"</span><br><span>diff --git a/main/mwi.c b/main/mwi.c</span><br><span>new file mode 100644</span><br><span>index 0000000..28a493d</span><br><span>--- /dev/null</span><br><span>+++ b/main/mwi.c</span><br><span>@@ -0,0 +1,369 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2019, Digium, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Kevin Harwell <kharwell@digium.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(120, 100%, 40%);">+ * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(120, 100%, 40%);">+ * channels for your use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software, distributed under the terms of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(120, 100%, 40%);">+ * at the top of the source tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*** MODULEINFO</span><br><span style="color: hsl(120, 100%, 40%);">+   <support_level>core</support_level></span><br><span style="color: hsl(120, 100%, 40%);">+ ***/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/stasis_channels.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * @{ \brief Define \ref stasis topic objects</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct stasis_topic *mwi_topic_all;</span><br><span style="color: hsl(120, 100%, 40%);">+static struct stasis_cache *mwi_state_cache;</span><br><span style="color: hsl(120, 100%, 40%);">+static struct stasis_caching_topic *mwi_topic_cached;</span><br><span style="color: hsl(120, 100%, 40%);">+static struct stasis_topic_pool *mwi_topic_pool;</span><br><span style="color: hsl(120, 100%, 40%);">+/* @} */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Convert a MWI \ref stasis_message to a \ref ast_event */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_event *mwi_to_event(struct stasis_message *message)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_event *event;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_mwi_state *mwi_state;</span><br><span style="color: hsl(120, 100%, 40%);">+      char *mailbox;</span><br><span style="color: hsl(120, 100%, 40%);">+        char *context;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!message) {</span><br><span style="color: hsl(120, 100%, 40%);">+               return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mwi_state = stasis_message_data(message);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Strip off @context */</span><br><span style="color: hsl(120, 100%, 40%);">+      context = mailbox = ast_strdupa(mwi_state->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+      strsep(&context, "@");</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ast_strlen_zero(context)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               context = "default";</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   event = ast_event_new(AST_EVENT_MWI,</span><br><span style="color: hsl(120, 100%, 40%);">+                          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,</span><br><span style="color: hsl(120, 100%, 40%);">+                               AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,</span><br><span style="color: hsl(120, 100%, 40%);">+                               AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, mwi_state->new_msgs,</span><br><span style="color: hsl(120, 100%, 40%);">+                               AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, mwi_state->old_msgs,</span><br><span style="color: hsl(120, 100%, 40%);">+                               AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, &mwi_state->eid, sizeof(mwi_state->eid),</span><br><span style="color: hsl(120, 100%, 40%);">+                         AST_EVENT_IE_END);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return event;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * @{ \brief Define \ref stasis message types for MWI</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+STASIS_MESSAGE_TYPE_DEFN(ast_mwi_state_type,</span><br><span style="color: hsl(120, 100%, 40%);">+      .to_event = mwi_to_event, );</span><br><span style="color: hsl(120, 100%, 40%);">+STASIS_MESSAGE_TYPE_DEFN(ast_mwi_vm_app_type);</span><br><span style="color: hsl(120, 100%, 40%);">+/* @} */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void mwi_state_dtor(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_mwi_state *mwi_state = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_string_field_free_memory(mwi_state);</span><br><span style="color: hsl(120, 100%, 40%);">+      ao2_cleanup(mwi_state->snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+  mwi_state->snapshot = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_topic *ast_mwi_topic_all(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  return mwi_topic_all;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_cache *ast_mwi_state_cache(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return mwi_state_cache;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_topic *ast_mwi_topic_cached(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return stasis_caching_get_topic(mwi_topic_cached);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_topic *ast_mwi_topic(const char *uniqueid)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  return stasis_topic_pool_get_topic(mwi_topic_pool, uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_mwi_state *ast_mwi_create(const char *mailbox, const char *context)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_mwi_state *mwi_state;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_assert(!ast_strlen_zero(mailbox));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      mwi_state = ao2_alloc(sizeof(*mwi_state), mwi_state_dtor);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!mwi_state) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_string_field_init(mwi_state, 256)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ao2_ref(mwi_state, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+               return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!ast_strlen_zero(context)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_string_field_build(mwi_state, uniqueid, "%s@%s", mailbox, context);</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_string_field_set(mwi_state, uniqueid, mailbox);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return mwi_state;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Create a MWI state snapshot message.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12.2.0</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mailbox The mailbox identifier string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] new_msgs The number of new messages in this mailbox</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] old_msgs The number of old messages in this mailbox</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] channel_id A unique identifier for a channel associated with this</span><br><span style="color: hsl(120, 100%, 40%);">+ * change in mailbox state</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] eid The EID of the server that originally published the message</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval message on success.  Use ao2_cleanup() when done with it.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct stasis_message *mwi_state_create_message(</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *mailbox,</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *context,</span><br><span style="color: hsl(120, 100%, 40%);">+  int new_msgs,</span><br><span style="color: hsl(120, 100%, 40%);">+ int old_msgs,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *channel_id,</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_eid *eid)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_mwi_state *mwi_state;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct stasis_message *message;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!ast_mwi_state_type()) {</span><br><span style="color: hsl(120, 100%, 40%);">+          return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mwi_state = ast_mwi_create(mailbox, context);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mwi_state) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mwi_state->new_msgs = new_msgs;</span><br><span style="color: hsl(120, 100%, 40%);">+    mwi_state->old_msgs = old_msgs;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!ast_strlen_zero(channel_id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           struct stasis_message *chan_message;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                chan_message = stasis_cache_get(ast_channel_cache(), ast_channel_snapshot_type(),</span><br><span style="color: hsl(120, 100%, 40%);">+                     channel_id);</span><br><span style="color: hsl(120, 100%, 40%);">+          if (chan_message) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   mwi_state->snapshot = stasis_message_data(chan_message);</span><br><span style="color: hsl(120, 100%, 40%);">+                   ao2_ref(mwi_state->snapshot, +1);</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+             ao2_cleanup(chan_message);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (eid) {</span><br><span style="color: hsl(120, 100%, 40%);">+            mwi_state->eid = *eid;</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              mwi_state->eid = ast_eid_default;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * XXX As far as stasis is concerned, all MWI events are local.</span><br><span style="color: hsl(120, 100%, 40%);">+        *</span><br><span style="color: hsl(120, 100%, 40%);">+     * We may in the future want to make MWI aggregate local/remote</span><br><span style="color: hsl(120, 100%, 40%);">+        * message counts similar to how device state aggregates state.</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span style="color: hsl(120, 100%, 40%);">+   message = stasis_message_create_full(ast_mwi_state_type(), mwi_state, &ast_eid_default);</span><br><span style="color: hsl(120, 100%, 40%);">+  ao2_cleanup(mwi_state);</span><br><span style="color: hsl(120, 100%, 40%);">+       return message;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_publish_mwi_state_full(</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *mailbox,</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *context,</span><br><span style="color: hsl(120, 100%, 40%);">+  int new_msgs,</span><br><span style="color: hsl(120, 100%, 40%);">+ int old_msgs,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *channel_id,</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_eid *eid)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_mwi_state *mwi_state;</span><br><span style="color: hsl(120, 100%, 40%);">+      RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+        struct stasis_topic *mailbox_specific_topic;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        message = mwi_state_create_message(mailbox, context, new_msgs, old_msgs, channel_id, eid);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!message) {</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mwi_state = stasis_message_data(message);</span><br><span style="color: hsl(120, 100%, 40%);">+     mailbox_specific_topic = ast_mwi_topic(mwi_state->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!mailbox_specific_topic) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   stasis_publish(mailbox_specific_topic, message);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_delete_mwi_state_full(const char *mailbox, const char *context, struct ast_eid *eid)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+    struct stasis_message *cached_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct stasis_message *clear_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_mwi_state *mwi_state;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct stasis_topic *mailbox_specific_topic;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        msg = mwi_state_create_message(mailbox, context, 0, 0, NULL, eid);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+           return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mwi_state = stasis_message_data(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * XXX As far as stasis is concerned, all MWI events are local.</span><br><span style="color: hsl(120, 100%, 40%);">+        *</span><br><span style="color: hsl(120, 100%, 40%);">+     * For now, it is assumed that there is only one entity</span><br><span style="color: hsl(120, 100%, 40%);">+        * maintaining the state of a particular mailbox.</span><br><span style="color: hsl(120, 100%, 40%);">+      *</span><br><span style="color: hsl(120, 100%, 40%);">+     * If we ever have multiple MWI event entities maintaining</span><br><span style="color: hsl(120, 100%, 40%);">+     * the same mailbox that wish to delete their cached entry</span><br><span style="color: hsl(120, 100%, 40%);">+     * we will need to do something about the race condition</span><br><span style="color: hsl(120, 100%, 40%);">+       * potential between checking the cache and removing the</span><br><span style="color: hsl(120, 100%, 40%);">+       * cache entry.</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span style="color: hsl(120, 100%, 40%);">+   cached_msg = stasis_cache_get_by_eid(ast_mwi_state_cache(),</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_mwi_state_type(), mwi_state->uniqueid, &ast_eid_default);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!cached_msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Nothing to clear */</span><br><span style="color: hsl(120, 100%, 40%);">+                return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_cleanup(cached_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    mailbox_specific_topic = ast_mwi_topic(mwi_state->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!mailbox_specific_topic) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   clear_msg = stasis_cache_clear_create(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (clear_msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+              stasis_publish(mailbox_specific_topic, clear_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ao2_cleanup(clear_msg);</span><br><span style="color: hsl(120, 100%, 40%);">+       return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const char *mwi_state_get_id(struct stasis_message *message)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        if (ast_mwi_state_type() == stasis_message_type(message)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           struct ast_mwi_state *mwi_state = stasis_message_data(message);</span><br><span style="color: hsl(120, 100%, 40%);">+               return mwi_state->uniqueid;</span><br><span style="color: hsl(120, 100%, 40%);">+        } else if (stasis_subscription_change_type() == stasis_message_type(message)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct stasis_subscription_change *change = stasis_message_data(message);</span><br><span style="color: hsl(120, 100%, 40%);">+             return change->uniqueid;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void mwi_blob_dtor(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_mwi_blob *mwi_blob = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ao2_cleanup(mwi_blob->mwi_state);</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_json_unref(mwi_blob->blob);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct stasis_message *ast_mwi_blob_create(struct ast_mwi_state *mwi_state,</span><br><span style="color: hsl(120, 100%, 40%);">+  struct stasis_message_type *message_type, struct ast_json *blob)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_mwi_blob *obj;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct stasis_message *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_assert(blob != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!message_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+          return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   obj = ao2_alloc(sizeof(*obj), mwi_blob_dtor);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!obj) {</span><br><span style="color: hsl(120, 100%, 40%);">+           return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   obj->mwi_state = mwi_state;</span><br><span style="color: hsl(120, 100%, 40%);">+        ao2_ref(obj->mwi_state, +1);</span><br><span style="color: hsl(120, 100%, 40%);">+       obj->blob = ast_json_ref(blob);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* This is not a normal MWI event.  Only used by the MinivmNotify app. */</span><br><span style="color: hsl(120, 100%, 40%);">+     msg = stasis_message_create(message_type, obj);</span><br><span style="color: hsl(120, 100%, 40%);">+       ao2_ref(obj, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return msg;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void mwi_cleanup(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    ao2_cleanup(mwi_topic_pool);</span><br><span style="color: hsl(120, 100%, 40%);">+  mwi_topic_pool = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        ao2_cleanup(mwi_topic_all);</span><br><span style="color: hsl(120, 100%, 40%);">+   mwi_topic_all = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(mwi_state_cache);</span><br><span style="color: hsl(120, 100%, 40%);">+ mwi_state_cache = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       mwi_topic_cached = stasis_caching_unsubscribe_and_join(mwi_topic_cached);</span><br><span style="color: hsl(120, 100%, 40%);">+     STASIS_MESSAGE_TYPE_CLEANUP(ast_mwi_state_type);</span><br><span style="color: hsl(120, 100%, 40%);">+      STASIS_MESSAGE_TYPE_CLEANUP(ast_mwi_vm_app_type);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int mwi_init(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_register_cleanup(mwi_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (STASIS_MESSAGE_TYPE_INIT(ast_mwi_state_type) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (STASIS_MESSAGE_TYPE_INIT(ast_mwi_vm_app_type) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mwi_topic_all = stasis_topic_create("mwi:all");</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!mwi_topic_all) {</span><br><span style="color: hsl(120, 100%, 40%);">+         return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mwi_state_cache = stasis_cache_create(mwi_state_get_id);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!mwi_state_cache) {</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mwi_topic_cached = stasis_caching_topic_create(mwi_topic_all, mwi_state_cache);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!mwi_topic_cached) {</span><br><span style="color: hsl(120, 100%, 40%);">+              return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mwi_topic_pool = stasis_topic_pool_create(mwi_topic_all);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!mwi_topic_pool) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/res/res_mwi_devstate.c b/res/res_mwi_devstate.c</span><br><span>index ff23a8d..deef55d 100644</span><br><span>--- a/res/res_mwi_devstate.c</span><br><span>+++ b/res/res_mwi_devstate.c</span><br><span>@@ -22,7 +22,7 @@</span><br><span> </span><br><span> #include "asterisk.h"</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/devicestate.h"</span><br><span> #include "asterisk/module.h"</span><br><span> #include "asterisk/stasis_message_router.h"</span><br><span>diff --git a/res/res_mwi_external.c b/res/res_mwi_external.c</span><br><span>index 9ded0d9..d01838e 100644</span><br><span>--- a/res/res_mwi_external.c</span><br><span>+++ b/res/res_mwi_external.c</span><br><span>@@ -56,7 +56,7 @@</span><br><span> </span><br><span> ASTERISK_FILE_VERSION(__FILE__, "$Revision$")</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/module.h"</span><br><span> #include "asterisk/res_mwi_external.h"</span><br><span> #include "asterisk/sorcery.h"</span><br><span>diff --git a/res/res_pjsip_mwi.c b/res/res_pjsip_mwi.c</span><br><span>index 7f86d98..e157d72 100644</span><br><span>--- a/res/res_pjsip_mwi.c</span><br><span>+++ b/res/res_pjsip_mwi.c</span><br><span>@@ -38,7 +38,7 @@</span><br><span> #include "asterisk/taskprocessor.h"</span><br><span> #include "asterisk/sorcery.h"</span><br><span> #include "asterisk/stasis.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> </span><br><span> struct mwi_subscription;</span><br><span> static struct ao2_container *unsolicited_mwi;</span><br><span>diff --git a/res/res_pjsip_publish_asterisk.c b/res/res_pjsip_publish_asterisk.c</span><br><span>index 2271d8b..292d68e 100644</span><br><span>--- a/res/res_pjsip_publish_asterisk.c</span><br><span>+++ b/res/res_pjsip_publish_asterisk.c</span><br><span>@@ -36,7 +36,7 @@</span><br><span> #include "asterisk/res_pjsip_pubsub.h"</span><br><span> #include "asterisk/module.h"</span><br><span> #include "asterisk/logger.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> </span><br><span> /*** DOCUMENTATION</span><br><span>       <configInfo name="res_pjsip_publish_asterisk" language="en_US"></span><br><span>diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c</span><br><span>index ab3e4b2..16c9a73 100644</span><br><span>--- a/res/res_pjsip_pubsub.c</span><br><span>+++ b/res/res_pjsip_pubsub.c</span><br><span>@@ -31,7 +31,7 @@</span><br><span> #include <pjsip_simple.h></span><br><span> #include <pjlib.h></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/res_pjsip_pubsub.h"</span><br><span> #include "asterisk/module.h"</span><br><span> #include "asterisk/linkedlists.h"</span><br><span>diff --git a/res/res_smdi.c b/res/res_smdi.c</span><br><span>index 1232839..2401807 100644</span><br><span>--- a/res/res_smdi.c</span><br><span>+++ b/res/res_smdi.c</span><br><span>@@ -63,6 +63,7 @@</span><br><span> #include "asterisk/stringfields.h"</span><br><span> #include "asterisk/linkedlists.h"</span><br><span> #include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/pbx.h"</span><br><span> #include "asterisk/channel.h"</span><br><span> </span><br><span>diff --git a/res/res_xmpp.c b/res/res_xmpp.c</span><br><span>index 2c2a0a9..a5f2851 100644</span><br><span>--- a/res/res_xmpp.c</span><br><span>+++ b/res/res_xmpp.c</span><br><span>@@ -57,6 +57,7 @@</span><br><span> #include "asterisk/module.h"</span><br><span> #include "asterisk/manager.h"</span><br><span> #include "asterisk/app.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/mwi.h"</span><br><span> #include "asterisk/message.h"</span><br><span> #include "asterisk/manager.h"</span><br><span> #include "asterisk/cli.h"</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/11250">change 11250</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/11250"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-Change-Id: I9dde8bfae1e7ec254fa63166e090f77e4d3097e0 </div>
<div style="display:none"> Gerrit-Change-Number: 11250 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>