579 lines
19 KiB
C
579 lines
19 KiB
C
/*
|
|
* Asterisk -- An open source telephony toolkit.
|
|
*
|
|
* Copyright (C) 2019, Sangoma Technologies Corporation
|
|
*
|
|
* Kevin Harwell <kharwell@digium.com>
|
|
*
|
|
* See http://www.asterisk.org for more information about
|
|
* the Asterisk project. Please do not directly contact
|
|
* any of the maintainers of this project for assistance;
|
|
* the project provides a web site, mailing lists and IRC
|
|
* channels for your use.
|
|
*
|
|
* This program is free software, distributed under the terms of
|
|
* the GNU General Public License Version 2. See the LICENSE file
|
|
* at the top of the source tree.
|
|
*/
|
|
|
|
#ifndef _ASTERISK_MWI_H
|
|
#define _ASTERISK_MWI_H
|
|
|
|
/*! \file
|
|
*
|
|
* \brief Asterisk MWI API.
|
|
*
|
|
* \par Intro
|
|
*
|
|
* This module manages, and processes all things MWI. Defined are mechanisms for subscribing
|
|
* and publishing to MWI topics. User modules wishing to receive MWI updates for a particular
|
|
* mailbox should do so by adding an MWI subscriber to that mailbox, followed by subscribing
|
|
* to the mailbox's topic. Likewise, user modules that want to publish MWI updates about a
|
|
* particular mailbox should first add a publisher for that mailbox prior to publishing.
|
|
*
|
|
* MWI state is managed via an underlying \ref stasis_state_manager (if interested see the
|
|
* stasis_state.c module for the gory details). As such all last known mailbox state can be
|
|
* retrieve and iterated over by using the \ref ast_mwi_subscribe_pool function.
|
|
*
|
|
* \par ast_mwi_subscriber
|
|
*
|
|
* Created via \ref ast_mwi_add_subscriber, a subscriber subscribes to a given mailbox in
|
|
* order to receive updates about the given mailbox. Adding a subscriber will create the
|
|
* underlying topic, and associated state data if those do not already exist for it. The
|
|
* topic, and last known state data is guaranteed to exist for the lifetime of the subscriber.
|
|
* State data can be NULL if nothing has been published to the mailbox's topic yet.
|
|
*
|
|
* NOTE, currently adding a subscriber here will either create, or add a reference to the
|
|
* underlying stasis state (and associated topic). However, it does not actually subscribe to
|
|
* the stasis topic itself. You still need to explicitly call \ref stasis_subscribe, or
|
|
* similar on the topic if you wish to receive published event updates.
|
|
*
|
|
* So given that when subscribing to an MWI topic the following order should be adhered to:
|
|
*
|
|
* 1. Add an MWI state subscriber using \ref ast_mwi_add_subscriber
|
|
* 2. Retrieve the topic from the subscriber using \ref ast_mwi_subscriber_topic
|
|
* 3. Subscribe to the topic itself using \ref stasis_subscribe or \ref stasis_subscribe_pool
|
|
*
|
|
* Or simply call \ref ast_mwi_subscribe_pool, which combines those steps into a single call and
|
|
* returns the subscriber that is now subscribed to both the stasis topic and state.
|
|
*
|
|
* Similarly, releasing the subscriber's reference removes a reference to the underlying state,
|
|
* but does not unsubscribe from the MWI topic. This should be done separately and prior to
|
|
* removing the subscriber's state reference:
|
|
*
|
|
* 1. Unsubscribe from the stasis topic subscription using \ref stasis_unsubscribe or
|
|
* \ref stasis_unsubscribe_and_join
|
|
* 2. Remove the MWI subscriber reference
|
|
*
|
|
* Or call \ref ast_mwi_unsubscribe (or _and_join), which combines those two steps into a
|
|
* single call.
|
|
*
|
|
* \par ast_mwi_publisher
|
|
*
|
|
* Before publishing to a particular topic a publisher should be created. This can be achieved
|
|
* by using \ref ast_mwi_add_publisher. Publishing to a mailbox should then be done using the
|
|
* \ref ast_mwi_publish function. This ensures the message is published to the appropriate
|
|
* topic, and the last known state is maintained.
|
|
*
|
|
* Publishing by mailbox id alone is also allowed. However, it is not recommended to do so,
|
|
* and exists mainly for backwards compatibility, and legacy subsystems. If, and when this
|
|
* method of publishing is employed a call to one of the \ref ast_delete_mwi_state functions
|
|
* should also be called for a given mailbox id after no more publishing will be done for
|
|
* that id. Otherwise a memory leak on the underlying stasis_state object will occur.
|
|
*
|
|
* \par ast_mwi_observer
|
|
*
|
|
* Add an observer in order to watch for particular MWI module related events. For instance if
|
|
* a submodule needs to know when a subscription is added to any mailbox an observer can be
|
|
* added to watch for that.
|
|
*/
|
|
|
|
#include "asterisk/utils.h"
|
|
#include "asterisk/stasis_state.h"
|
|
|
|
#if defined(__cplusplus) || defined(c_plusplus)
|
|
extern "C" {
|
|
#endif
|
|
|
|
struct ast_json;
|
|
struct stasis_message_type;
|
|
struct ast_mwi_state;
|
|
|
|
/*!
|
|
* \brief An MWI state subscriber
|
|
*
|
|
* An ao2 managed object. Holds a reference to the latest MWI state for its lifetime.
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
struct ast_mwi_subscriber;
|
|
|
|
/*!
|
|
* \brief Add an MWI state subscriber to the mailbox
|
|
*
|
|
* Adding a subscriber to a mailbox will create a stasis topic for the mailbox if one
|
|
* does not already exist. It does not however subscribe to the topic itself. This is
|
|
* done separately using a call to \ref stasis_subscribe or \ref stasis_subscribe_pool.
|
|
*
|
|
* A subscriber can be removed by releasing its reference. Doing so releases its underlying
|
|
* reference to the MWI state. It does not unsubscribe from the topic. Unsubscribing from
|
|
* a topic should be done prior to unsubscribing the state.
|
|
*
|
|
* \param mailbox The subscription state mailbox id
|
|
*
|
|
* \return An MWI subscriber object
|
|
* \retval NULL on error
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
struct ast_mwi_subscriber *ast_mwi_add_subscriber(const char *mailbox);
|
|
|
|
/*!
|
|
* \brief Add an MWI state subscriber, and stasis subscription to the mailbox
|
|
*
|
|
* Adding a subscriber to a mailbox will create a stasis topic for the mailbox if one
|
|
* does not already exist. Once successfully create the underlying stasis topic is then
|
|
* subscribed to as well.
|
|
*
|
|
* A subscriber can be removed by releasing its reference. Doing so releases its underlying
|
|
* reference to the MWI state. It does not unsubscribe from the topic. Unsubscribing from
|
|
* a topic should be done prior to unsubscribing the state.
|
|
*
|
|
* \param mailbox The subscription state mailbox id
|
|
* \param callback The stasis subscription callback
|
|
* \param data A user data object passed to the stasis subscription
|
|
*
|
|
* \return An MWI subscriber object
|
|
* \retval NULL on error
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
struct ast_mwi_subscriber *ast_mwi_subscribe_pool(const char *mailbox,
|
|
stasis_subscription_cb callback, void *data);
|
|
|
|
/*!
|
|
* \brief Unsubscribe from the stasis topic and MWI.
|
|
*
|
|
* \param sub An MWI subscriber
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
void *ast_mwi_unsubscribe(struct ast_mwi_subscriber *sub);
|
|
|
|
/*!
|
|
* \brief Unsubscribe from the stasis topic, block until the final message
|
|
* is received, and then unsubscribe from MWI.
|
|
*
|
|
* \param sub An MWI subscriber
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
void *ast_mwi_unsubscribe_and_join(struct ast_mwi_subscriber *sub);
|
|
|
|
/*!
|
|
* \brief Retrieves the MWI subscriber's topic
|
|
*
|
|
* \note Returned topic's reference count is NOT incremented. However, the topic is
|
|
* guaranteed to live for the lifetime of the subscriber.
|
|
*
|
|
* \param sub An MWI subscriber
|
|
*
|
|
* \return A stasis topic subscribed to by the subscriber
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
struct stasis_topic *ast_mwi_subscriber_topic(struct ast_mwi_subscriber *sub);
|
|
|
|
/*!
|
|
* \brief Retrieves the state data object associated with the MWI subscriber
|
|
*
|
|
* \note Returned data's reference count is incremented
|
|
*
|
|
* \param sub An MWI subscriber
|
|
*
|
|
* \return The state data object
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
struct ast_mwi_state *ast_mwi_subscriber_data(struct ast_mwi_subscriber *sub);
|
|
|
|
/*!
|
|
* \brief Retrieve the stasis MWI topic subscription if available.
|
|
*
|
|
* \param sub An MWI subscriber
|
|
*
|
|
* \return The subscriber's stasis subscription
|
|
* \retval NULL if no subscription available
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
struct stasis_subscription *ast_mwi_subscriber_subscription(struct ast_mwi_subscriber *sub);
|
|
|
|
/*!
|
|
* \brief An MWI state publisher
|
|
*
|
|
* An ao2 managed object. Holds a reference to the latest MWI state for its lifetime.
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
struct ast_mwi_publisher;
|
|
|
|
/*!
|
|
* \brief Add an MWI state publisher to the mailbox
|
|
*
|
|
* Adding a publisher to a mailbox will create a stasis topic for the mailbox if one
|
|
* does not already exist. A publisher can be removed by releasing its reference. Doing
|
|
* so releases its underlying reference to the MWI state.
|
|
*
|
|
* \param mailbox The mailbox id to publish to
|
|
*
|
|
* \return An MWI publisher object
|
|
* \retval NULl on error
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
struct ast_mwi_publisher *ast_mwi_add_publisher(const char *mailbox);
|
|
|
|
/*! \brief MWI state event interface */
|
|
struct ast_mwi_observer {
|
|
/*!
|
|
* \brief Raised when MWI is being subscribed
|
|
*
|
|
* \param mailbox The mailbox id subscribed
|
|
* \param sub The subscriber subscribed
|
|
*/
|
|
void (*on_subscribe)(const char *mailbox, struct ast_mwi_subscriber *sub);
|
|
|
|
/*!
|
|
* \brief Raised when MWI is being unsubscribed
|
|
*
|
|
* \param mailbox The mailbox id being unsubscribed
|
|
* \param sub The subscriber to unsubscribe
|
|
*/
|
|
void (*on_unsubscribe)(const char *mailbox, struct ast_mwi_subscriber *sub);
|
|
};
|
|
|
|
/*!
|
|
* \brief Add an observer to receive MWI state related events.
|
|
*
|
|
* \param observer The observer handling events
|
|
*
|
|
* \retval 0 if successfully registered
|
|
* \retval -1 otherwise
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
int ast_mwi_add_observer(struct ast_mwi_observer *observer);
|
|
|
|
/*!
|
|
* \brief Remove an MWI state observer.
|
|
*
|
|
* \param observer The observer being removed
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
void ast_mwi_remove_observer(struct ast_mwi_observer *observer);
|
|
|
|
/*!
|
|
* \brief The delegate called for each managed mailbox state.
|
|
*
|
|
* \param mwi_state The mwi state object
|
|
* \param data User data passed in by the initiator
|
|
*
|
|
* \retval 0 to continue traversing
|
|
* \retval CMP_STOP (2) to stop traversing
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
typedef int (*on_mwi_state)(struct ast_mwi_state *mwi_state, void *data);
|
|
|
|
/*!
|
|
* \brief For each managed mailbox call the given handler.
|
|
*
|
|
* \param handler The mwi state handler to call for each managed mailbox
|
|
* \param data User to data to pass on to the handler
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
void ast_mwi_state_callback_all(on_mwi_state handler, void *data);
|
|
|
|
/*!
|
|
* \brief For each managed mailbox that has a subscriber call the given handler.
|
|
*
|
|
* \param handler The mwi state handler to call for each managed mailbox
|
|
* \param data User to data to pass on to the handler
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
void ast_mwi_state_callback_subscribed(on_mwi_state handler, void *data);
|
|
|
|
/*!
|
|
* \brief Publish MWI for the given mailbox.
|
|
*
|
|
* \param publisher The publisher to publish a mailbox update on
|
|
* \param urgent_msgs The number of urgent messages in this mailbox
|
|
* \param new_msgs The number of new messages in this mailbox
|
|
* \param old_msgs The number of old messages in this mailbox
|
|
* \param channel_id A unique identifier for a channel associated with this
|
|
* change in mailbox state
|
|
* \param eid The EID of the server that originally published the message
|
|
*
|
|
* \retval 0 on success
|
|
* \retval -1 on failure
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
int ast_mwi_publish(struct ast_mwi_publisher *publisher, int urgent_msgs,
|
|
int new_msgs, int old_msgs, const char *channel_id, struct ast_eid *eid);
|
|
|
|
/*!
|
|
* \brief Publish MWI for the given mailbox.
|
|
*
|
|
* \param mailbox The mailbox identifier string.
|
|
* \param context The context this mailbox resides in (NULL or "" if only using mailbox)
|
|
* \param urgent_msgs The number of urgent messages in this mailbox
|
|
* \param new_msgs The number of new messages in this mailbox
|
|
* \param old_msgs The number of old messages in this mailbox
|
|
* \param channel_id A unique identifier for a channel associated with this
|
|
* change in mailbox state
|
|
* \param eid The EID of the server that originally published the message
|
|
*
|
|
* \retval 0 on success
|
|
* \retval -1 on failure
|
|
*
|
|
* \since 13.28.0
|
|
* \since 16.5.0
|
|
*/
|
|
int ast_mwi_publish_by_mailbox(const char *mailbox, const char *context, int urgent_msgs,
|
|
int new_msgs, int old_msgs, const char *channel_id, struct ast_eid *eid);
|
|
|
|
/*!
|
|
* \since 12
|
|
* \brief Publish a MWI state update via stasis
|
|
*
|
|
* \param[in] mailbox The mailbox identifier string.
|
|
* \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
|
|
* \param[in] new_msgs The number of new messages in this mailbox
|
|
* \param[in] old_msgs The number of old messages in this mailbox
|
|
*
|
|
* \retval 0 Success
|
|
* \retval -1 Failure
|
|
*/
|
|
#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs) \
|
|
ast_publish_mwi_state_full(mailbox, context, new_msgs, old_msgs, NULL, NULL)
|
|
|
|
/*!
|
|
* \since 12
|
|
* \brief Publish a MWI state update associated with some channel
|
|
*
|
|
* \param[in] mailbox The mailbox identifier string.
|
|
* \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
|
|
* \param[in] new_msgs The number of new messages in this mailbox
|
|
* \param[in] old_msgs The number of old messages in this mailbox
|
|
* \param[in] channel_id A unique identifier for a channel associated with this
|
|
* change in mailbox state
|
|
*
|
|
* \retval 0 Success
|
|
* \retval -1 Failure
|
|
*/
|
|
#define ast_publish_mwi_state_channel(mailbox, context, new_msgs, old_msgs, channel_id) \
|
|
ast_publish_mwi_state_full(mailbox, context, new_msgs, old_msgs, channel_id, NULL)
|
|
|
|
/*!
|
|
* \since 12
|
|
* \brief Publish a MWI state update via stasis with all parameters
|
|
*
|
|
* \param[in] mailbox The mailbox identifier string.
|
|
* \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
|
|
* \param[in] new_msgs The number of new messages in this mailbox
|
|
* \param[in] old_msgs The number of old messages in this mailbox
|
|
* \param[in] channel_id A unique identifier for a channel associated with this
|
|
* change in mailbox state
|
|
* \param[in] eid The EID of the server that originally published the message
|
|
*
|
|
* \retval 0 Success
|
|
* \retval -1 Failure
|
|
*/
|
|
int ast_publish_mwi_state_full(
|
|
const char *mailbox,
|
|
const char *context,
|
|
int new_msgs,
|
|
int old_msgs,
|
|
const char *channel_id,
|
|
struct ast_eid *eid);
|
|
|
|
/*!
|
|
* \since 12.2.0
|
|
* \brief Delete MWI state cached by stasis
|
|
*
|
|
* \param[in] mailbox The mailbox identifier string.
|
|
* \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
|
|
*
|
|
* \retval 0 Success
|
|
* \retval -1 Failure
|
|
*/
|
|
#define ast_delete_mwi_state(mailbox, context) \
|
|
ast_delete_mwi_state_full(mailbox, context, NULL)
|
|
|
|
/*!
|
|
* \since 12.2.0
|
|
* \brief Delete MWI state cached by stasis with all parameters
|
|
*
|
|
* \param[in] mailbox The mailbox identifier string.
|
|
* \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
|
|
* \param[in] eid The EID of the server that originally published the message
|
|
*
|
|
* \retval 0 Success
|
|
* \retval -1 Failure
|
|
*/
|
|
int ast_delete_mwi_state_full(const char *mailbox, const char *context, struct ast_eid *eid);
|
|
|
|
/*!
|
|
* \addtogroup StasisTopicsAndMessages
|
|
*/
|
|
|
|
/*!
|
|
* \brief The structure that contains MWI state
|
|
* \since 12
|
|
*/
|
|
struct ast_mwi_state {
|
|
AST_DECLARE_STRING_FIELDS(
|
|
AST_STRING_FIELD(uniqueid); /*!< Unique identifier for this mailbox */
|
|
);
|
|
int new_msgs; /*!< The current number of new messages for this mailbox */
|
|
int old_msgs; /*!< The current number of old messages for this mailbox */
|
|
/*! If applicable, a snapshot of the channel that caused this MWI change */
|
|
struct ast_channel_snapshot *snapshot;
|
|
struct ast_eid eid; /*!< The EID of the server where this message originated */
|
|
int urgent_msgs; /*!< The current number of urgent messages for this mailbox */
|
|
};
|
|
|
|
/*!
|
|
* \brief Object that represents an MWI update with some additional application
|
|
* defined data
|
|
*/
|
|
struct ast_mwi_blob {
|
|
struct ast_mwi_state *mwi_state; /*!< MWI state */
|
|
struct ast_json *blob; /*!< JSON blob of data */
|
|
};
|
|
|
|
/*!
|
|
* \since 12
|
|
* \brief Create a \ref ast_mwi_state object
|
|
*
|
|
* \param[in] mailbox The mailbox identifier string.
|
|
* \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
|
|
*
|
|
* \return \ref ast_mwi_state object on success
|
|
* \retval NULL on error
|
|
*/
|
|
struct ast_mwi_state *ast_mwi_create(const char *mailbox, const char *context);
|
|
|
|
/*!
|
|
* \since 12
|
|
* \brief Creates a \ref ast_mwi_blob message.
|
|
*
|
|
* The \a blob JSON object requires a \c "type" field describing the blob. It
|
|
* should also be treated as immutable and not modified after it is put into the
|
|
* message.
|
|
*
|
|
* \param mwi_state MWI state associated with the update
|
|
* \param message_type The type of message to create
|
|
* \param blob JSON object representing the data.
|
|
* \return \ref ast_mwi_blob message.
|
|
* \retval NULL on error
|
|
*/
|
|
struct stasis_message *ast_mwi_blob_create(struct ast_mwi_state *mwi_state,
|
|
struct stasis_message_type *message_type,
|
|
struct ast_json *blob);
|
|
|
|
/*!
|
|
* \brief Get the \ref stasis topic for MWI messages
|
|
* \return The topic structure for MWI messages
|
|
* \retval NULL if it has not been allocated
|
|
* \since 12
|
|
*/
|
|
struct stasis_topic *ast_mwi_topic_all(void);
|
|
|
|
/*!
|
|
* \brief Get the \ref stasis topic for MWI messages on a unique ID
|
|
* \param uniqueid The unique id for which to get the topic
|
|
* \return The topic structure for MWI messages for a given uniqueid
|
|
* \retval NULL if it failed to be found or allocated
|
|
* \since 12
|
|
*/
|
|
struct stasis_topic *ast_mwi_topic(const char *uniqueid);
|
|
|
|
/*!
|
|
* \brief Get the \ref stasis caching topic for MWI messages
|
|
* \return The caching topic structure for MWI messages
|
|
* \retval NULL if it has not been allocated
|
|
* \since 12
|
|
*/
|
|
struct stasis_topic *ast_mwi_topic_cached(void);
|
|
|
|
/*!
|
|
* \brief Backend cache for ast_mwi_topic_cached().
|
|
* \return Cache of \ref ast_mwi_state.
|
|
*/
|
|
struct stasis_cache *ast_mwi_state_cache(void);
|
|
|
|
/*!
|
|
* \brief Get the \ref stasis message type for MWI messages
|
|
* \return The message type structure for MWI messages
|
|
* \retval NULL on error
|
|
* \since 12
|
|
*/
|
|
struct stasis_message_type *ast_mwi_state_type(void);
|
|
|
|
/*!
|
|
* \brief Get the \ref stasis message type for voicemail application specific messages
|
|
*
|
|
* This message type exists for those messages a voicemail application may wish to send
|
|
* that have no logical relationship with other voicemail applications. Voicemail apps
|
|
* that use this message type must pass a \ref ast_mwi_blob. Any extraneous information
|
|
* in the JSON blob must be packed as key/value pair tuples of strings.
|
|
*
|
|
* At least one key/value tuple must have a key value of "Event".
|
|
*
|
|
* \return The \ref stasis_message_type for voicemail application specific messages
|
|
* \retval NULL on error
|
|
* \since 12
|
|
*/
|
|
struct stasis_message_type *ast_mwi_vm_app_type(void);
|
|
|
|
/*!
|
|
* \brief Initialize the mwi core
|
|
*
|
|
* \retval 0 Success
|
|
* \retval -1 Failure
|
|
*
|
|
* \since 13.27.0
|
|
* \since 16.4.0
|
|
*/
|
|
int mwi_init(void);
|
|
|
|
#define AST_MAX_MAILBOX_UNIQUEID (AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2)
|
|
|
|
#if defined(__cplusplus) || defined(c_plusplus)
|
|
}
|
|
#endif
|
|
|
|
#endif /* _ASTERISK_MWI_H */
|