29 #include <pjsip_simple.h> 51 #define STASIS_BUCKETS 13 52 #define MWI_BUCKETS 53 54 #define MWI_TYPE "application" 55 #define MWI_SUBTYPE "simple-message-summary" 57 #define MWI_DATASTORE "MWI datastore" 60 #define MWI_SERIALIZER_POOL_SIZE 8 63 #define MAX_UNLOAD_TIMEOUT_TIME 10 71 const char *resource);
148 mwi_stasis_sub =
ao2_alloc(
sizeof(*mwi_stasis_sub) + strlen(mailbox),
NULL);
149 if (!mwi_stasis_sub) {
154 strcpy(mwi_stasis_sub->
mailbox, mailbox);
169 return mwi_stasis_sub;
183 key =
object->mailbox;
196 const char *right_key = arg;
201 right_key = sub_right->
mailbox;
204 cmp = strcmp(sub_left->
mailbox, right_key);
207 cmp = strncmp(sub_left->
mailbox, right_key, strlen(right_key));
223 ast_debug(3,
"Destroying MWI subscription for endpoint %s\n", sub->
id);
237 sub =
ao2_alloc(
sizeof(*sub) + strlen(endpoint_id),
245 strcpy(sub->
id, endpoint_id);
274 ast_debug(3,
"Created %s MWI subscription for endpoint %s\n", is_solicited ?
"solicited" :
"unsolicited", sub->
id);
303 const char *right_key = arg;
308 right_key = sub_right->
id;
311 cmp = strcmp(sub_left->
id, right_key);
314 cmp = strncmp(sub_left->
id, right_key, strlen(right_key));
348 pjsip_sip_uri *account_uri;
349 const char *vm_exten;
354 vm_exten = voicemail_extension;
358 account_uri = pjsip_uri_clone(pool, local_uri);
359 pj_strdup2(pool, &account_uri->user, vm_exten);
378 const char *state_name;
379 pjsip_tx_data *tdata;
380 pjsip_sub_state_hdr *sub_state;
381 pjsip_event_hdr *
event;
382 pjsip_from_hdr *from;
383 pjsip_sip_uri *from_uri;
384 const pjsip_hdr *allow_events = pjsip_evsub_get_allow_events_hdr(
NULL);
389 .body_data = mwi_data->
counter,
393 ast_log(
LOG_WARNING,
"Unable to create unsolicited NOTIFY request to endpoint %s URI %s\n", sub->
id, contact->
uri);
401 pjsip_tx_data_dec_ref(tdata);
405 from = PJSIP_MSG_FROM_HDR(tdata->msg);
406 from_uri = pjsip_uri_get_uri(from->uri);
417 pjsip_tx_data_dec_ref(tdata);
424 case PJSIP_EVSUB_STATE_ACTIVE:
425 state_name =
"active";
427 case PJSIP_EVSUB_STATE_TERMINATED:
429 state_name =
"terminated";
433 sub_state = pjsip_sub_state_hdr_create(tdata->pool);
434 pj_cstr(&sub_state->sub_state, state_name);
435 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) sub_state);
437 event = pjsip_event_hdr_create(tdata->pool);
438 pj_cstr(&event->event_type,
"message-summary");
439 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) event);
441 pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_shallow_clone(tdata->pool, allow_events));
480 ast_debug(1,
"Found an aor (%s) that matches voicemail_extension %s\n", aor_name, resource);
499 ast_log(
LOG_WARNING,
"Unable to send unsolicited MWI to %s because endpoint does not exist\n",
504 ast_log(
LOG_WARNING,
"Unable to send unsolicited MWI to %s because the endpoint has no" 505 " configured AORs\n", sub->
id);
511 ast_debug(5,
"Sending unsolicited MWI NOTIFY to endpoint %s, new messages: %d, old messages: %d\n",
530 ast_debug(1,
"No contacts bound to AOR %s. Cannot send unsolicited MWI until a contact registers.\n", aor_name);
543 .message_account[0] =
'\0',
547 .body_data = &counter,
559 if (aor && dlg && sip_uri) {
578 ast_debug(3,
"Removing stasis subscription to mailbox %s\n", mwi_stasis->
mailbox);
596 if (!mwi_datastore) {
600 mwi_sub = mwi_datastore->
data;
618 if (unsolicited_mwi && endpoint) {
646 if (!mwi_datastore) {
711 return *mwi_stasis ? 1 : 0;
752 ast_debug(1,
"Unsolicited subscription being replaced by solicited for " 769 static int send_notify(
void *obj,
void *arg,
int flags);
858 if (unsolicited_mwi) {
869 ast_debug(1,
"Endpoint '%s' already configured for unsolicited MWI for mailbox '%s'. " 873 if (unsolicited_mwi) {
881 if (unsolicited_mwi) {
909 if (!mwi_stasis_sub) {
975 const char *resource)
988 ast_debug(1,
"Unable to locate aor %s. MWI subscription failed.\n", resource);
993 ast_debug(1,
"AOR %s has no configured mailboxes. MWI subscription failed.\n",
1032 if (solicited_mwi) {
1051 if (!mwi_datastore) {
1054 mwi_sub = mwi_datastore->
data;
1066 if (dlg && sip_uri) {
1104 if (!mwi_datastore) {
1108 mwi_sub = mwi_datastore->
data;
1211 if (aggregate_sub && !recreate) {
1215 if (!aggregate_sub) {
1217 if (!aggregate_sub) {
1231 if (solicited_mwi) {
1250 if (mwi_stasis_sub) {
1254 if (!aggregate_sub) {
1262 if (aggregate_sub && !sub_added) {
1268 if (aggregate_sub) {
1274 if (send_now && sub_added) {
1280 if (solicited_mwi) {
1309 if (!unsolicited_mwi) {
1346 const char *aor = arg;
1348 if (!mwi_sub->
aors || !strstr(mwi_sub->
aors, aor)) {
1383 if (!unsolicited_mwi) {
1439 if (found_contact) {
1445 if (!unsolicited_mwi) {
1474 if (unsolicited_mwi) {
1495 if (strcmp(type,
"FullyBooted")) {
1533 if (unsolicited_mwi) {
1544 mwi_serializer_pool =
NULL;
1563 if (!mwi_serializer_pool) {
1564 ast_log(
AST_LOG_WARNING,
"Failed to create MWI serializer pool. The default SIP pool will be used for MWI\n");
1569 if (!mwi_container) {
1578 if (!mwi_container) {
1603 if (!mwi_serializer_pool) {
1621 .requires =
"res_pjsip,res_pjsip_pubsub",
static struct ast_sorcery_observer global_observer
struct ast_mwi_subscriber * mwi_subscriber
#define AST_SIP_MESSAGE_ACCUMULATOR
static void mwi_contact_added(const void *object)
Function called when a contact is added.
struct ast_sip_mwi_configuration mwi
const ast_string_field mailboxes
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
For every aor in the comma separated aors string call the given 'on_aor' handler. ...
struct ast_sip_message_accumulator * counter
static void mwi_contact_updated(const void *object)
Function called when a contact is updated.
struct ast_taskprocessor * ast_sip_subscription_get_serializer(struct ast_sip_subscription *sub)
Get the serializer for the subscription.
struct mwi_subscription * sub
static void mwi_startup_event_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Event callback which fires initial unsolicited MWI NOTIFY messages when we're fully booted...
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
static void global_loaded(const char *object_type)
static void mwi_subscription_mailboxes_str(struct ao2_container *stasis_subs, struct ast_str **str)
unsigned int is_solicited
static int create_unsolicited_mwi_subscriptions(struct ast_sip_endpoint *endpoint, int recreate, int send_now, struct ao2_container *unsolicited_mwi, struct ao2_container *solicited_mwi)
The arg parameter is a search key, but is not an object.
#define ast_test_flag(p, flag)
Data used to create bodies for NOTIFY/PUBLISH requests.
static struct ast_sip_notifier mwi_notifier
char * voicemail_extension
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
int ast_serializer_pool_destroy(struct ast_serializer_pool *pool)
Destroy the serializer pool.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define ao2_callback(c, flags, cb_fn, arg)
static int add_mwi_datastore(struct mwi_subscription *sub)
static int unsubscribe_stasis(void *obj, void *arg, int flags)
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
Structure for variables, used for configurations and for channel variables.
static pj_pool_t * pool
Global memory pool for configuration and timers.
struct stasis_subscription * ast_mwi_subscriber_subscription(struct ast_mwi_subscriber *sub)
Retrieve the stasis MWI topic subscription if available.
void(* created)(const void *object)
Callback for when an object is created.
struct ast_sip_endpoint_subscription_configuration subscription
int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler)
Register a subscription handler.
Assume that the ao2_container is already locked.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Structure for a data store type.
static int unload_module(void)
Message counter used for message-summary XML bodies.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
static struct ast_sip_subscription_handler mwi_handler
#define ao2_global_obj_ref(holder)
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
Return all matching objects.
static void mwi_ds_destroy(void *data)
const char * ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub)
Get the name of the subscribed resource.
struct ao2_container * ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor)
Retrieve all contacts currently available for an AOR.
#define ao2_link_flags(container, obj, flags)
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
static int mwi_validate_for_aor(void *obj, void *arg, int flags)
Determine if an endpoint is a candidate to be able to subscribe for MWI.
static int send_unsolicited_mwi_notify_to_contact(void *obj, void *arg, int flags)
struct ast_mwi_state * ast_mwi_subscriber_data(struct ast_mwi_subscriber *sub)
Retrieves the state data object associated with the MWI subscriber.
const ast_string_field mailboxes
struct ast_threadpool * ast_sip_threadpool(void)
Retrieve the SIP threadpool object.
static void send_mwi_notify(struct mwi_subscription *sub)
static void mwi_contact_deleted(const void *object)
Function called when a contact is deleted.
static void mwi_subscription_destructor(void *obj)
static int mwi_on_aor(void *obj, void *arg, int flags)
static struct mwi_stasis_subscription * mwi_stasis_subscription_alloc(const char *mailbox, struct mwi_subscription *mwi_sub)
struct ao2_container * stasis_subs
int ast_sip_send_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, void *token, void(*callback)(void *token, pjsip_event *e))
General purpose method for sending a SIP request.
static struct ast_sip_aor * find_aor_for_resource(struct ast_sip_endpoint *endpoint, const char *resource)
AO2_GLOBAL_OBJ_STATIC(mwi_unsolicited)
char * voicemail_extension
#define ast_strlen_zero(foo)
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
unsigned int ast_sip_get_mwi_tps_queue_high(void)
Retrieve the global MWI taskprocessor high water alert trigger level.
int ast_sip_get_mwi_tps_queue_low(void)
Retrieve the global MWI taskprocessor low water clear alert level.
pjsip_sip_uri * ast_sip_subscription_get_sip_uri(struct ast_sip_subscription *sub)
Retrieve the local sip uri for this subscription.
#define ast_debug(level,...)
Log a DEBUG message.
struct stasis_message_type * ast_manager_get_generic_type(void)
Get the stasis_message_type for generic messages.
static int stasis_sub_hash(const void *obj, const int flags)
static int stasis_sub_cmp(void *obj, void *arg, int flags)
static int mwi_sub_cmp(void *obj, void *arg, int flags)
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
int ast_sip_pubsub_generate_body_content(const char *content_type, const char *content_subtype, struct ast_sip_body_data *data, struct ast_str **str)
Generate body content for a PUBLISH or NOTIFY.
int ast_sip_add_body(pjsip_tx_data *tdata, const struct ast_sip_body *body)
Add a body to an outbound SIP message.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define MAX_UNLOAD_TIMEOUT_TIME
static int has_mwi_subscription(struct ao2_container *container, struct ast_sip_endpoint *endpoint, const char *mailbox, struct mwi_subscription **mwi_sub, struct mwi_stasis_subscription **mwi_stasis)
unsigned int subscribe_replaces_unsolicited
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
struct ast_sip_subscription * sip_sub
static struct ao2_container * endpoints
#define ao2_ref(o, delta)
static struct ast_datastore_info mwi_ds_info
void(* destroy)(void *data)
#define ast_strdupa(s)
duplicate a string in memory from the stack
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
char * ast_sip_get_default_voicemail_extension(void)
Retrieve the default voicemail extension.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
unsigned int ast_sip_get_mwi_disable_initial_unsolicited(void)
Retrieve the global setting 'disable sending unsolicited mwi on startup'.
struct ao2_container * container
static struct mwi_subscription * mwi_create_subscription(struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
#define ast_variable_new(name, value, filename)
An entity with which Asterisk communicates.
struct ast_sip_contact * ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list)
Retrieve the first bound contact from a list of AORs.
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
void ast_sip_subscription_destroy(struct ast_sip_subscription *sub)
Alert the pubsub core that the subscription is ready for destruction.
Structure representing a "virtual" SIP subscription.
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
static int load_module(void)
static int allow_and_or_replace_unsolicited(struct ast_sip_endpoint *endpoint, const char *mailbox, struct ao2_container *unsolicited_mwi)
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
static int mwi_sub_hash(const void *obj, const int flags)
#define ao2_unlink(container, obj)
static int serialized_notify(void *userdata)
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
static int send_notify(void *obj, void *arg, int flags)
Interface for a sorcery object type observer.
#define ao2_global_obj_release(holder)
static char * default_voicemail_extension
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
struct ast_datastore * ast_sip_subscription_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
#define ao2_callback_data(container, flags, cb_fn, arg, data)
static void send_unsolicited_mwi_notify(struct mwi_subscription *sub, struct ast_sip_message_accumulator *counter)
#define stasis_subscribe_pool(topic, callback, data)
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
#define ao2_iterator_next(iter)
#define ao2_alloc(data_size, destructor_fn)
static void set_voicemail_extension(pj_pool_t *pool, pjsip_sip_uri *local_uri, struct ast_sip_message_accumulator *counter, const char *voicemail_extension)
int stasis_subscription_final_message(struct stasis_subscription *sub, struct stasis_message *msg)
Determine whether a message is the final message to be received on a subscription.
static void * mwi_get_notify_data(struct ast_sip_subscription *sub)
static void mwi_to_ami(struct ast_sip_subscription *sub, struct ast_str **buf)
static const struct ast_sorcery_observer mwi_contact_observer
Observer for contacts so unsolicited MWI is sent when a contact changes.
static struct mwi_subscription * mwi_subscribe_single(struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub, const char *name)
void * ast_mwi_unsubscribe_and_join(struct ast_mwi_subscriber *sub)
Unsubscribe from the stasis topic, block until the final message is received, and then unsubscribe fr...
void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler *handler)
Unregister a subscription handler.
#define MWI_SERIALIZER_POOL_SIZE
static int mwi_subscription_established(struct ast_sip_subscription *sub)
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
static struct mwi_subscription * mwi_subscription_alloc(struct ast_sip_endpoint *endpoint, unsigned int is_solicited, struct ast_sip_subscription *sip_sub)
Module has failed to load, may be in an inconsistent state.
#define ao2_find(container, arg, flags)
An API for managing task processing threads that can be shared across modules.
static int unsubscribe(void *obj, void *arg, int flags)
struct ast_datastore * ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name)
Retrieve a subscription datastore.
static void mwi_subscription_shutdown(struct ast_sip_subscription *sub)
void(* loaded)(const char *object_type)
Callback for when an object type is loaded/reloaded.
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Support for logging to various files, console and syslog Configuration in file logger.conf.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
int ast_serializer_pool_set_alerts(struct ast_serializer_pool *pool, long high, long low)
Set taskprocessor alert levels for the serializers in the pool.
struct ast_serializer_pool * ast_serializer_pool_create(const char *name, unsigned int size, struct ast_threadpool *threadpool, int timeout)
Create a serializer pool.
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
struct ast_sip_endpoint * ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub)
Get the endpoint that is associated with this subscription.
pjsip_dialog * ast_sip_subscription_get_dialog(struct ast_sip_subscription *sub)
Get the pjsip dialog that is associated with this subscription.
#define ao2_global_obj_replace_unref(holder, obj)
The arg parameter is an object of the same type.
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
struct ast_flags ast_options
char * strsep(char **str, const char *delims)
A ast_taskprocessor structure is a singleton by name.
int ast_sip_subscription_add_datastore(struct ast_sip_subscription *subscription, struct ast_datastore *datastore)
Add a datastore to a SIP subscription.
const ast_string_field fromuser
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
int ast_sip_subscription_notify(struct ast_sip_subscription *sub, struct ast_sip_body_data *notify_data, int terminate)
Notify a SIP subscription of a state change.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name)
Remove a subscription datastore from the subscription.
static int get_message_count(void *obj, void *arg, int flags)
static void create_mwi_subscriptions(void)
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, void *data, int flags)
struct stasis_forward * sub
static int send_contact_notify(void *obj, void *arg, int flags)
Function called to send MWI NOTIFY on any unsolicited mailboxes relating to this AOR.
static int send_initial_notify_all(void *obj)
Task invoked to send initial MWI NOTIFY for unsolicited.
struct stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.
static struct mwi_subscription * mwi_subscribe_all(struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
Search option field mask.
const ast_string_field aors
The structure that contains MWI state.
static int mwi_new_subscribe(struct ast_sip_endpoint *endpoint, const char *resource)
#define ASTERISK_GPL_KEY
The text the key() function should return.
const char * default_accept
Default body type defined for the event package this notifier handles.
Wrapper for stasis subscription.
Asterisk module definitions.
struct ast_mwi_subscriber * ast_mwi_subscribe_pool(const char *mailbox, stasis_subscription_cb callback, void *data)
Add an MWI state subscriber, and stasis subscription to the mailbox.
struct ast_sip_endpoint * endpoint
#define ao2_global_obj_replace(holder, obj)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
struct ast_taskprocessor * ast_serializer_pool_get(struct ast_serializer_pool *pool)
Retrieve a serializer from the pool.
void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects.
static struct stasis_subscription * mwi_sub
static void mwi_stasis_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
static struct ast_serializer_pool * mwi_serializer_pool
static void mwi_contact_changed(const struct ast_sip_contact *contact)
Create mwi subscriptions and notify.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, const char *uri, struct ast_sip_contact *contact, pjsip_tx_data **tdata)
General purpose method for creating a SIP request.
Sorcery Data Access Layer API.
static int is_unsolicited_allowed(struct ast_sip_endpoint *endpoint, const char *mailbox, struct ao2_container *unsolicited_mwi, struct ao2_container *solicited_mwi)
char message_account[PJSIP_MAX_URL_SIZE]
static int serialized_cleanup(void *userdata)
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
#define ao2_link(container, obj)