summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/samples/pjsip.conf.sample28
-rw-r--r--contrib/ast-db-manage/config/versions/1c688d9a003c_pjsip_voicemail_extension.py31
-rw-r--r--include/asterisk/res_pjsip.h17
-rw-r--r--include/asterisk/res_pjsip_body_generator_types.h2
-rw-r--r--include/asterisk/res_pjsip_pubsub.h20
-rw-r--r--res/res_pjsip.c12
-rw-r--r--res/res_pjsip/config_global.c44
-rw-r--r--res/res_pjsip/location.c20
-rw-r--r--res/res_pjsip/pjsip_configuration.c20
-rw-r--r--res/res_pjsip_mwi.c130
-rw-r--r--res/res_pjsip_mwi_body_generator.c5
-rw-r--r--res/res_pjsip_pubsub.c11
-rw-r--r--res/res_pjsip_pubsub.exports.in40
13 files changed, 288 insertions, 92 deletions
diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index c7b33c025..0b321b43c 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -624,7 +624,14 @@
; "username")
;redirect_method=user ; How redirects received from an endpoint are handled
; (default: "user")
-;mailboxes= ; Mailbox es to be associated with (default: "")
+;mailboxes= ; NOTIFY the endpoint when state changes for any of the specified mailboxes.
+ ; Asterisk will send unsolicited MWI NOTIFY messages to the endpoint when state
+ ; changes happen for any of the specified mailboxes. (default: "")
+;voicemail_extension= ; The voicemail extension to send in the NOTIFY Message-Account header
+ ; (default: global/default_voicemail_extension)
+;mwi_subscribe_replaces_unsolicited=no
+ ; An MWI subscribe will replace unsoliticed NOTIFYs
+ ; (default: "no")
;moh_suggest=default ; Default Music On Hold class (default: "default")
;outbound_auth= ; Authentication object used for outbound requests (default:
; "")
@@ -824,7 +831,11 @@
;default_expiration=3600 ; Default expiration time in seconds for
; contacts that are dynamically bound to an AoR
; (default: "3600")
-;mailboxes= ; Mailbox es to be associated with (default: "")
+;mailboxes= ; Allow subscriptions for the specified mailbox(es)
+ ; This option applies when an external entity subscribes to an AoR
+ ; for Message Waiting Indications. (default: "")
+;voicemail_extension= ; The voicemail extension to send in the NOTIFY Message-Account header
+ ; (default: global/default_voicemail_extension)
;maximum_expiration=7200 ; Maximum time to keep an AoR (default: "7200")
;max_contacts=0 ; Maximum number of contacts that can bind to an AoR (default:
; "0")
@@ -896,10 +907,15 @@
; startup that qualifies should be attempted on all
; contacts. If greater than the qualify_frequency
; for an aor, qualify_frequency will be used instead.
-; If regcontext is specified, Asterisk will dynamically create and destroy a
-; NoOp priority 1 extension for a given endpoint who registers or unregisters
-; with us. The extension added is the name of the endpoint.
-;regcontext=sipregistrations
+;regcontext=sipregistrations ; If regcontext is specified, Asterisk will dynamically
+ ; create and destroy a NoOp priority 1 extension for a
+ ; given endpoint who registers or unregisters with us.
+ ; The extension added is the name of the endpoint.
+;default_voicemail_extension=asterisk
+ ; The voicemail extension to send in the NOTIFY Message-Account header
+ ; if not set on endpoint or aor.
+ ; (default: "")
+
; MODULE PROVIDING BELOW SECTION(S): res_pjsip_acl
;==========================ACL SECTION OPTIONS=========================
diff --git a/contrib/ast-db-manage/config/versions/1c688d9a003c_pjsip_voicemail_extension.py b/contrib/ast-db-manage/config/versions/1c688d9a003c_pjsip_voicemail_extension.py
new file mode 100644
index 000000000..781dca703
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/1c688d9a003c_pjsip_voicemail_extension.py
@@ -0,0 +1,31 @@
+"""pjsip voicemail extension
+
+Revision ID: 1c688d9a003c
+Revises: 5813202e92be
+Create Date: 2016-03-24 22:31:45.537895
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '1c688d9a003c'
+down_revision = '5813202e92be'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+ op.add_column('ps_globals', sa.Column('default_voicemail_extension', sa.String(40)))
+ op.add_column('ps_aors', sa.Column('voicemail_extension', sa.String(40)))
+ op.add_column('ps_endpoints', sa.Column('voicemail_extension', sa.String(40)))
+ op.add_column('ps_endpoints', sa.Column('mwi_subscribe_replaces_unsolicited', sa.Integer))
+
+
+def downgrade():
+ with op.batch_alter_table('ps_globals') as batch_op:
+ batch_op.drop_column('default_voicemail_extension')
+ with op.batch_alter_table('ps_aors') as batch_op:
+ batch_op.drop_column('voicemail_extension')
+ with op.batch_alter_table('ps_endpoints') as batch_op:
+ batch_op.drop_column('voicemail_extension')
+ batch_op.drop_column('mwi_subscribe_replaces_unsolicited')
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 50fbc5102..fbb9bdcbe 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -310,6 +310,8 @@ struct ast_sip_aor {
unsigned int support_path;
/*! Qualify timeout. 0 is diabled. */
double qualify_timeout;
+ /* Voicemail extension to set in Message-Account */
+ char *voicemail_extension;
};
/*!
@@ -464,6 +466,10 @@ struct ast_sip_mwi_configuration {
);
/* Should mailbox states be combined into a single notification? */
unsigned int aggregate;
+ /* Should a subscribe replace unsolicited notifies? */
+ unsigned int subscribe_replaces_unsolicited;
+ /* Voicemail extension to set in Message-Account */
+ char *voicemail_extension;
};
/*!
@@ -2164,6 +2170,16 @@ char *ast_sip_get_regcontext(void);
char *ast_sip_get_endpoint_identifier_order(void);
/*!
+ * \brief Retrieve the default voicemail extension.
+ * \since 13.9.0
+ *
+ * \note returned string needs to be de-allocated by caller.
+ *
+ * \retval the default voicemail extension
+ */
+char *ast_sip_get_default_voicemail_extension(void);
+
+/*!
* \brief Retrieve the global default from user.
*
* This is the value placed in outbound requests' From header if there
@@ -2302,4 +2318,5 @@ int ast_sip_set_tpselector_from_transport_name(const char *transport_name, pjsip
void ast_sip_modify_id_header(pj_pool_t *pool, pjsip_fromto_hdr *id_hdr,
const struct ast_party_id *id);
+
#endif /* _RES_PJSIP_H */
diff --git a/include/asterisk/res_pjsip_body_generator_types.h b/include/asterisk/res_pjsip_body_generator_types.h
index a2cc04313..aab147238 100644
--- a/include/asterisk/res_pjsip_body_generator_types.h
+++ b/include/asterisk/res_pjsip_body_generator_types.h
@@ -65,6 +65,8 @@ struct ast_sip_message_accumulator {
int old_msgs;
/*! Number of new messages */
int new_msgs;
+ /*! Message-Account */
+ char message_account[PJSIP_MAX_URL_SIZE];
};
#endif /* _RES_PJSIP_BODY_GENERATOR_TYPES_H */
diff --git a/include/asterisk/res_pjsip_pubsub.h b/include/asterisk/res_pjsip_pubsub.h
index c9b66dce3..84d86fb9e 100644
--- a/include/asterisk/res_pjsip_pubsub.h
+++ b/include/asterisk/res_pjsip_pubsub.h
@@ -339,6 +339,14 @@ struct ast_sip_subscription_handler {
struct ast_sip_subscription *ast_sip_create_subscription(const struct ast_sip_subscription_handler *handler,
struct ast_sip_endpoint *endpoint, const char *resource);
+/*!
+ * \brief Get the pjsip dialog that is associated with this subscription
+ * \since 13.9.0
+ *
+ * \retval NULL Could not get dialog
+ * \retval non-NULL The dialog
+ */
+pjsip_dialog *ast_sip_subscription_get_dialog(struct ast_sip_subscription *sub);
/*!
* \brief Get the endpoint that is associated with this subscription
@@ -379,6 +387,18 @@ struct ast_taskprocessor *ast_sip_subscription_get_serializer(struct ast_sip_sub
int ast_sip_subscription_notify(struct ast_sip_subscription *sub, struct ast_sip_body_data *notify_data, int terminate);
/*!
+ * \brief Retrieve the local sip uri for this subscription
+ * \since 13.9.0
+ *
+ * This is the local sip URI of the subscribed resource.
+ *
+ * \param sub The subscription
+ * \retval NULL Could not get uri
+ * \retval non-NULL The local pjsip_sip_uri
+ */
+pjsip_sip_uri *ast_sip_subscription_get_sip_uri(struct ast_sip_subscription *sub);
+
+/*!
* \brief Retrieve the local URI for this subscription
*
* This is the local URI of the subscribed resource.
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 0d5ded565..2b0e777fa 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -302,6 +302,12 @@
configuration.
</para></description>
</configOption>
+ <configOption name="mwi_subscribe_replaces_unsolicited">
+ <synopsis>An MWI subscribe will replace sending unsolicited NOTIFYs</synopsis>
+ </configOption>
+ <configOption name="voicemail_extension">
+ <synopsis>The voicemail extension to send in the NOTIFY Message-Account header</synopsis>
+ </configOption>
<configOption name="moh_suggest" default="default">
<synopsis>Default Music On Hold class</synopsis>
</configOption>
@@ -1135,6 +1141,9 @@
endpoint configuration section to enable unsolicited MWI NOTIFYs to the endpoint.
</para></description>
</configOption>
+ <configOption name="voicemail_extension">
+ <synopsis>The voicemail extension to send in the NOTIFY Message-Account header</synopsis>
+ </configOption>
<configOption name="maximum_expiration" default="7200">
<synopsis>Maximum time to keep an AoR</synopsis>
<description><para>
@@ -1299,6 +1308,9 @@
<configOption name="default_outbound_endpoint" default="default_outbound_endpoint">
<synopsis>Endpoint to use when sending an outbound request to a URI without a specified endpoint.</synopsis>
</configOption>
+ <configOption name="default_voicemail_extension">
+ <synopsis>The voicemail extension to send in the NOTIFY Message-Account header if not specified on endpoint or aor</synopsis>
+ </configOption>
<configOption name="debug" default="no">
<synopsis>Enable/Disable SIP debug logging. Valid options include yes|no or
a host address</synopsis>
diff --git a/res/res_pjsip/config_global.c b/res/res_pjsip/config_global.c
index c0fede64d..ad03379fd 100644
--- a/res/res_pjsip/config_global.c
+++ b/res/res_pjsip/config_global.c
@@ -37,6 +37,7 @@
#define DEFAULT_FROM_USER "asterisk"
#define DEFAULT_REGCONTEXT ""
#define DEFAULT_CONTACT_EXPIRATION_CHECK_INTERVAL 30
+#define DEFAULT_VOICEMAIL_EXTENSION ""
static char default_useragent[256];
@@ -52,6 +53,8 @@ struct global_config {
AST_STRING_FIELD(endpoint_identifier_order);
/*! User name to place in From header if there is no better option */
AST_STRING_FIELD(default_from_user);
+ /*! Default voicemail extension */
+ AST_STRING_FIELD(default_voicemail_extension);
);
/* Value to put in Max-Forwards header */
unsigned int max_forwards;
@@ -144,20 +147,35 @@ char *ast_sip_get_debug(void)
char *ast_sip_get_regcontext(void)
{
- char *res;
- struct global_config *cfg;
+ char *res;
+ struct global_config *cfg;
- cfg = get_global_cfg();
- if (!cfg) {
- return ast_strdup(DEFAULT_REGCONTEXT);
- }
+ cfg = get_global_cfg();
+ if (!cfg) {
+ return ast_strdup(DEFAULT_REGCONTEXT);
+ }
- res = ast_strdup(cfg->regcontext);
- ao2_ref(cfg, -1);
+ res = ast_strdup(cfg->regcontext);
+ ao2_ref(cfg, -1);
- return res;
+ return res;
}
+char *ast_sip_get_default_voicemail_extension(void)
+{
+ char *res;
+ struct global_config *cfg;
+
+ cfg = get_global_cfg();
+ if (!cfg) {
+ return ast_strdup(DEFAULT_VOICEMAIL_EXTENSION);
+ }
+
+ res = ast_strdup(cfg->default_voicemail_extension);
+ ao2_ref(cfg, -1);
+
+ return res;
+}
char *ast_sip_get_endpoint_identifier_order(void)
{
@@ -347,12 +365,14 @@ int ast_sip_initialize_sorcery_global(void)
OPT_UINT_T, 0, FLDSET(struct global_config, max_initial_qualify_time));
ast_sorcery_object_field_register(sorcery, "global", "default_from_user", DEFAULT_FROM_USER,
OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, default_from_user));
+ ast_sorcery_object_field_register(sorcery, "global", "default_voicemail_extension",
+ DEFAULT_VOICEMAIL_EXTENSION, OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config,
+ default_voicemail_extension));
ast_sorcery_object_field_register(sorcery, "global", "regcontext", DEFAULT_REGCONTEXT,
- OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, regcontext));
+ OPT_UINT_T, 0, FLDSET(struct global_config, contact_expiration_check_interval));
ast_sorcery_object_field_register(sorcery, "global", "contact_expiration_check_interval",
__stringify(DEFAULT_CONTACT_EXPIRATION_CHECK_INTERVAL),
- OPT_UINT_T, 0, FLDSET(struct global_config, contact_expiration_check_interval));
-
+ OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, regcontext));
if (ast_sorcery_instance_observer_add(sorcery, &observer_callbacks_global)) {
return -1;
diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c
index 4284f35f1..735b18f46 100644
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -35,6 +35,7 @@ static void aor_destroy(void *obj)
ao2_cleanup(aor->permanent_contacts);
ast_string_field_free_memory(aor);
+ ast_free(aor->voicemail_extension);
}
/*! \brief Allocator for AOR */
@@ -442,6 +443,24 @@ static int contacts_to_var_list(const void *obj, struct ast_variable **fields)
return 0;
}
+static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+ struct ast_sip_aor *aor = obj;
+
+ aor->voicemail_extension = ast_strdup(var->value);
+
+ return aor->voicemail_extension ? 0 : -1;
+}
+
+static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_aor *aor = obj;
+
+ *buf = ast_strdup(aor->voicemail_extension);
+
+ return 0;
+}
+
int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
{
char *copy, *name;
@@ -992,6 +1011,7 @@ int ast_sip_initialize_sorcery_location(void)
ast_sorcery_object_field_register(sorcery, "aor", "remove_existing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_existing));
ast_sorcery_object_field_register_custom(sorcery, "aor", "contact", "", permanent_uri_handler, contacts_to_str, contacts_to_var_list, 0, 0);
ast_sorcery_object_field_register(sorcery, "aor", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, mailboxes));
+ ast_sorcery_object_field_register_custom(sorcery, "aor", "voicemail_extension", "", voicemail_extension_handler, voicemail_extension_to_str, NULL, 0, 0);
ast_sorcery_object_field_register(sorcery, "aor", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, outbound_proxy));
ast_sorcery_object_field_register(sorcery, "aor", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, support_path));
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index ea808ce4d..06588337c 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1055,6 +1055,23 @@ static int set_var_to_vl(const void *obj, struct ast_variable **fields)
return 0;
}
+static int voicemail_extension_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+ struct ast_sip_endpoint *endpoint = obj;
+
+ endpoint->subscription.mwi.voicemail_extension = ast_strdup(var->value);
+
+ return endpoint->subscription.mwi.voicemail_extension ? 0 : -1;
+}
+
+static int voicemail_extension_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+
+ *buf = ast_strdup(endpoint->subscription.mwi.voicemail_extension);
+
+ return 0;
+}
static void *sip_nat_hook_alloc(const char *name)
{
@@ -1650,7 +1667,9 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rpid_immediate", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, rpid_immediate));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_diversion", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, id.send_diversion));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, subscription.mwi.mailboxes));
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "voicemail_extension", "", voicemail_extension_handler, voicemail_extension_to_str, NULL, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aggregate_mwi", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.mwi.aggregate));
+ ast_sorcery_object_field_register(sip_sorcery, "endpoint", "mwi_subscribe_replaces_unsolicited", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.mwi.subscribe_replaces_unsolicited));
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "media_encryption", "no", media_encryption_handler, media_encryption_to_str, NULL, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_avpf", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_avpf));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "force_avp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.force_avp));
@@ -1801,6 +1820,7 @@ int ast_res_pjsip_reload_configuration(void)
static void subscription_configuration_destroy(struct ast_sip_endpoint_subscription_configuration *subscription)
{
ast_string_field_free_memory(&subscription->mwi);
+ ast_free(subscription->mwi.voicemail_extension);
}
static void info_configuration_destroy(struct ast_sip_endpoint_info_configuration *info)
diff --git a/res/res_pjsip_mwi.c b/res/res_pjsip_mwi.c
index b77981cfe..f18c3f9cd 100644
--- a/res/res_pjsip_mwi.c
+++ b/res/res_pjsip_mwi.c
@@ -42,6 +42,8 @@
struct mwi_subscription;
static struct ao2_container *unsolicited_mwi;
+static char *default_voicemail_extension;
+
#define STASIS_BUCKETS 13
#define MWI_BUCKETS 53
@@ -326,11 +328,30 @@ static int get_message_count(void *obj, void *arg, int flags)
return 0;
}
+static void set_voicemail_extension(pj_pool_t *pool, pjsip_sip_uri *local_uri,
+ struct ast_sip_message_accumulator *counter, const char *voicemail_extension)
+{
+ pjsip_sip_uri *account_uri;
+ const char *vm_exten;
+
+ if (ast_strlen_zero(voicemail_extension)) {
+ vm_exten = default_voicemail_extension;
+ } else {
+ vm_exten = voicemail_extension;
+ }
+
+ if (!ast_strlen_zero(vm_exten)) {
+ account_uri = pjsip_uri_clone(pool, local_uri);
+ pj_strdup2(pool, &account_uri->user, vm_exten);
+ pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, account_uri, counter->message_account, sizeof(counter->message_account));
+ }
+}
+
struct unsolicited_mwi_data {
struct mwi_subscription *sub;
struct ast_sip_endpoint *endpoint;
pjsip_evsub_state state;
- const struct ast_sip_body *body;
+ struct ast_sip_message_accumulator *counter;
};
static int send_unsolicited_mwi_notify_to_contact(void *obj, void *arg, int flags)
@@ -339,27 +360,50 @@ static int send_unsolicited_mwi_notify_to_contact(void *obj, void *arg, int flag
struct mwi_subscription *sub = mwi_data->sub;
struct ast_sip_endpoint *endpoint = mwi_data->endpoint;
pjsip_evsub_state state = mwi_data->state;
- const struct ast_sip_body *body = mwi_data->body;
struct ast_sip_contact *contact = obj;
const char *state_name;
pjsip_tx_data *tdata;
pjsip_sub_state_hdr *sub_state;
pjsip_event_hdr *event;
+ pjsip_from_hdr *from;
+ pjsip_sip_uri *from_uri;
const pjsip_hdr *allow_events = pjsip_evsub_get_allow_events_hdr(NULL);
+ struct ast_sip_body body;
+ struct ast_str *body_text;
+ struct ast_sip_body_data body_data = {
+ .body_type = AST_SIP_MESSAGE_ACCUMULATOR,
+ .body_data = mwi_data->counter,
+ };
if (ast_sip_create_request("NOTIFY", NULL, endpoint, NULL, contact, &tdata)) {
ast_log(LOG_WARNING, "Unable to create unsolicited NOTIFY request to endpoint %s URI %s\n", sub->id, contact->uri);
return 0;
}
- if (!ast_strlen_zero(endpoint->subscription.mwi.fromuser)) {
- pjsip_fromto_hdr *from = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_FROM, NULL);
- pjsip_name_addr *from_name_addr = (pjsip_name_addr *) from->uri;
- pjsip_sip_uri *from_uri = pjsip_uri_get_uri(from_name_addr->uri);
+ body.type = MWI_TYPE;
+ body.subtype = MWI_SUBTYPE;
+ body_text = ast_str_create(64);
+ if (!body_text) {
+ return 0;
+ }
+ from = PJSIP_MSG_FROM_HDR(tdata->msg);
+ from_uri = pjsip_uri_get_uri(from->uri);
+
+ if (!ast_strlen_zero(endpoint->subscription.mwi.fromuser)) {
pj_strdup2(tdata->pool, &from_uri->user, endpoint->subscription.mwi.fromuser);
}
+ set_voicemail_extension(tdata->pool, from_uri, mwi_data->counter, endpoint->subscription.mwi.voicemail_extension);
+
+ if (ast_sip_pubsub_generate_body_content(body.type, body.subtype, &body_data, &body_text)) {
+ ast_log(LOG_WARNING, "Unable to generate SIP MWI NOTIFY body.\n");
+ ast_free(body_text);
+ return 0;
+ }
+
+ body.body_text = ast_str_buffer(body_text);
+
switch (state) {
case PJSIP_EVSUB_STATE_ACTIVE:
state_name = "active";
@@ -379,9 +423,11 @@ static int send_unsolicited_mwi_notify_to_contact(void *obj, void *arg, int flag
pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) event);
pjsip_msg_add_hdr(tdata->msg, pjsip_hdr_shallow_clone(tdata->pool, allow_events));
- ast_sip_add_body(tdata, body);
+ ast_sip_add_body(tdata, &body);
ast_sip_send_request(tdata, NULL, endpoint, NULL, NULL);
+ ast_free(body_text);
+
return 0;
}
@@ -392,12 +438,6 @@ static void send_unsolicited_mwi_notify(struct mwi_subscription *sub,
"endpoint", sub->id), ao2_cleanup);
char *endpoint_aors;
char *aor_name;
- struct ast_sip_body body;
- struct ast_str *body_text;
- struct ast_sip_body_data body_data = {
- .body_type = AST_SIP_MESSAGE_ACCUMULATOR,
- .body_data = counter,
- };
if (!endpoint) {
ast_log(LOG_WARNING, "Unable to send unsolicited MWI to %s because endpoint does not exist\n",
@@ -410,23 +450,6 @@ static void send_unsolicited_mwi_notify(struct mwi_subscription *sub,
return;
}
- body.type = MWI_TYPE;
- body.subtype = MWI_SUBTYPE;
-
- body_text = ast_str_create(64);
-
- if (!body_text) {
- return;
- }
-
- if (ast_sip_pubsub_generate_body_content(body.type, body.subtype, &body_data, &body_text)) {
- ast_log(LOG_WARNING, "Unable to generate SIP MWI NOTIFY body.\n");
- ast_free(body_text);
- return;
- }
-
- body.body_text = ast_str_buffer(body_text);
-
endpoint_aors = ast_strdupa(endpoint->aors);
ast_debug(5, "Sending unsolicited MWI NOTIFY to endpoint %s, new messages: %d, old messages: %d\n",
@@ -438,7 +461,7 @@ static void send_unsolicited_mwi_notify(struct mwi_subscription *sub,
struct unsolicited_mwi_data mwi_data = {
.sub = sub,
.endpoint = endpoint,
- .body = &body,
+ .counter = counter,
};
if (!aor) {
@@ -454,8 +477,6 @@ static void send_unsolicited_mwi_notify(struct mwi_subscription *sub,
ao2_callback(contacts, OBJ_NODATA, send_unsolicited_mwi_notify_to_contact, &mwi_data);
}
-
- ast_free(body_text);
}
static void send_mwi_notify(struct mwi_subscription *sub)
@@ -463,6 +484,7 @@ static void send_mwi_notify(struct mwi_subscription *sub)
struct ast_sip_message_accumulator counter = {
.old_msgs = 0,
.new_msgs = 0,
+ .message_account[0] = '\0',
};
struct ast_sip_body_data data = {
.body_type = AST_SIP_MESSAGE_ACCUMULATOR,
@@ -472,7 +494,17 @@ static void send_mwi_notify(struct mwi_subscription *sub)
ao2_callback(sub->stasis_subs, OBJ_NODATA, get_message_count, &counter);
if (sub->is_solicited) {
+ struct ast_sip_aor *aor = ast_sip_location_retrieve_aor(ast_sip_subscription_get_resource_name(sub->sip_sub));
+ pjsip_dialog *dlg = ast_sip_subscription_get_dialog(sub->sip_sub);
+ pjsip_sip_uri *sip_uri = ast_sip_subscription_get_sip_uri(sub->sip_sub);
+
+ if (aor && dlg && sip_uri) {
+ set_voicemail_extension(dlg->pool, sip_uri, &counter, aor->voicemail_extension);
+ }
+
+ ao2_cleanup(aor);
ast_sip_subscription_notify(sub->sip_sub, &data, 0);
+
return;
}
@@ -565,7 +597,12 @@ static int endpoint_receives_unsolicited_mwi_for_mailbox(struct ast_sip_endpoint
mwi_stasis = ao2_find(mwi_sub->stasis_subs, mailbox, OBJ_SEARCH_KEY);
if (mwi_stasis) {
- ret = 1;
+ if (endpoint->subscription.mwi.subscribe_replaces_unsolicited) {
+ unsubscribe_stasis(mwi_stasis, NULL, 0);
+ ao2_unlink(mwi_sub->stasis_subs, mwi_stasis);
+ } else {
+ ret = 1;
+ }
ao2_cleanup(mwi_stasis);
}
}
@@ -771,6 +808,7 @@ static void *mwi_get_notify_data(struct ast_sip_subscription *sub)
struct ast_sip_message_accumulator *counter;
struct mwi_subscription *mwi_sub;
struct ast_datastore *mwi_datastore;
+ struct ast_sip_aor *aor;
mwi_datastore = ast_sip_subscription_get_datastore(sub, MWI_DATASTORE);
if (!mwi_datastore) {
@@ -784,6 +822,16 @@ static void *mwi_get_notify_data(struct ast_sip_subscription *sub)
return NULL;
}
+ if ((aor = ast_sip_location_retrieve_aor(ast_sip_subscription_get_resource_name(sub)))) {
+ pjsip_dialog *dlg = ast_sip_subscription_get_dialog(sub);
+ pjsip_sip_uri *sip_uri = ast_sip_subscription_get_sip_uri(sub);
+
+ if (dlg && sip_uri) {
+ set_voicemail_extension(dlg->pool, sip_uri, counter, aor->voicemail_extension);
+ }
+ ao2_ref(aor, -1);
+ }
+
ao2_callback(mwi_sub->stasis_subs, OBJ_NODATA, get_message_count, counter);
ao2_cleanup(mwi_datastore);
return counter;
@@ -1084,6 +1132,16 @@ static void mwi_startup_event_cb(void *data, struct stasis_subscription *sub, st
stasis_unsubscribe(sub);
}
+static void global_loaded(const char *object_type)
+{
+ ast_free(default_voicemail_extension);
+ default_voicemail_extension = ast_sip_get_default_voicemail_extension();
+}
+
+static struct ast_sorcery_observer global_observer = {
+ .loaded = global_loaded,
+};
+
static int reload(void)
{
create_mwi_subscriptions();
@@ -1106,6 +1164,8 @@ static int load_module(void)
create_mwi_subscriptions();
ast_sorcery_observer_add(ast_sip_get_sorcery(), "contact", &mwi_contact_observer);
+ ast_sorcery_observer_add(ast_sip_get_sorcery(), "global", &global_observer);
+ ast_sorcery_reload_object(ast_sip_get_sorcery(), "global");
if (ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
ast_sip_push_task(NULL, send_initial_notify_all, NULL);
@@ -1120,8 +1180,10 @@ static int unload_module(void)
{
ao2_callback(unsolicited_mwi, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe, NULL);
ao2_ref(unsolicited_mwi, -1);
+ ast_sorcery_observer_remove(ast_sip_get_sorcery(), "global", &global_observer);
ast_sorcery_observer_remove(ast_sip_get_sorcery(), "contact", &mwi_contact_observer);
ast_sip_unregister_subscription_handler(&mwi_handler);
+ ast_free(default_voicemail_extension);
return 0;
}
diff --git a/res/res_pjsip_mwi_body_generator.c b/res/res_pjsip_mwi_body_generator.c
index cc558ac82..f6aca2df1 100644
--- a/res/res_pjsip_mwi_body_generator.c
+++ b/res/res_pjsip_mwi_body_generator.c
@@ -46,7 +46,7 @@ static void *mwi_allocate_body(void *data)
if (!mwi_str) {
return NULL;
}
- *mwi_str = ast_str_create(64);
+ *mwi_str = ast_str_create(128);
if (!*mwi_str) {
ast_free(mwi_str);
return NULL;
@@ -63,6 +63,9 @@ static int mwi_generate_body_content(void *body, void *data)
counter->new_msgs ? "yes" : "no");
ast_str_append(mwi, 0, "Voice-Message: %d/%d (0/0)\r\n",
counter->new_msgs, counter->old_msgs);
+ if (!ast_strlen_zero(counter->message_account)) {
+ ast_str_append(mwi, 0, "Message-Account: %s\r\n", counter->message_account);
+ }
return 0;
}
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index d859b760a..670047567 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -1644,6 +1644,12 @@ struct ast_sip_subscription *ast_sip_create_subscription(const struct ast_sip_su
return sub;
}
+pjsip_dialog *ast_sip_subscription_get_dialog(struct ast_sip_subscription *sub)
+{
+ ast_assert(sub->tree->dlg != NULL);
+ return sub->tree->dlg;
+}
+
struct ast_sip_endpoint *ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub)
{
ast_assert(sub->tree->endpoint != NULL);
@@ -2271,6 +2277,11 @@ int ast_sip_subscription_notify(struct ast_sip_subscription *sub, struct ast_sip
return res;
}
+pjsip_sip_uri *ast_sip_subscription_get_sip_uri(struct ast_sip_subscription *sub)
+{
+ return sub->uri;
+}
+
void ast_sip_subscription_get_local_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
{
pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, sub->uri, buf, size);
diff --git a/res/res_pjsip_pubsub.exports.in b/res/res_pjsip_pubsub.exports.in
index 661652489..a75103bb6 100644
--- a/res/res_pjsip_pubsub.exports.in
+++ b/res/res_pjsip_pubsub.exports.in
@@ -1,44 +1,6 @@
{
global:
- LINKER_SYMBOL_PREFIXast_sip_create_subscription;
- LINKER_SYMBOL_PREFIXast_sip_subscription_get_endpoint;
- LINKER_SYMBOL_PREFIXast_sip_subscription_get_serializer;
- LINKER_SYMBOL_PREFIXast_sip_subscription_get_evsub;
- LINKER_SYMBOL_PREFIXast_sip_subscription_get_dlg;
- LINKER_SYMBOL_PREFIXast_sip_subscription_accept;
- LINKER_SYMBOL_PREFIXast_sip_subscription_send_request;
- LINKER_SYMBOL_PREFIXast_sip_subscription_alloc_datastore;
- LINKER_SYMBOL_PREFIXast_sip_subscription_add_datastore;
- LINKER_SYMBOL_PREFIXast_sip_subscription_get_datastore;
- LINKER_SYMBOL_PREFIXast_sip_subscription_remove_datastore;
- LINKER_SYMBOL_PREFIXast_sip_register_subscription_handler;
- LINKER_SYMBOL_PREFIXast_sip_unregister_subscription_handler;
- LINKER_SYMBOL_PREFIXast_sip_create_publication;
- LINKER_SYMBOL_PREFIXast_sip_publication_get_endpoint;
- LINKER_SYMBOL_PREFIXast_sip_publication_get_resource;
- LINKER_SYMBOL_PREFIXast_sip_publication_get_event_configuration;
- LINKER_SYMBOL_PREFIXast_sip_publication_create_response;
- LINKER_SYMBOL_PREFIXast_sip_publication_send_response;
- LINKER_SYMBOL_PREFIXast_sip_register_publish_handler;
- LINKER_SYMBOL_PREFIXast_sip_unregister_publish_handler;
- LINKER_SYMBOL_PREFIXast_sip_publication_add_datastore;
- LINKER_SYMBOL_PREFIXast_sip_publication_get_datastore;
- LINKER_SYMBOL_PREFIXast_sip_publication_remove_datastore;
- LINKER_SYMBOL_PREFIXast_sip_publication_remove_datastore;
- LINKER_SYMBOL_PREFIXast_sip_pubsub_register_body_generator;
- LINKER_SYMBOL_PREFIXast_sip_pubsub_unregister_body_generator;
- LINKER_SYMBOL_PREFIXast_sip_pubsub_register_body_supplement;
- LINKER_SYMBOL_PREFIXast_sip_pubsub_unregister_body_supplement;
- LINKER_SYMBOL_PREFIXast_sip_pubsub_generate_body_content;
- LINKER_SYMBOL_PREFIXast_sip_subscription_get_body_type;
- LINKER_SYMBOL_PREFIXast_sip_subscription_get_body_subtype;
- LINKER_SYMBOL_PREFIXast_sip_subscription_get_resource_name;
- LINKER_SYMBOL_PREFIXast_sip_subscription_notify;
- LINKER_SYMBOL_PREFIXast_sip_subscription_get_local_uri;
- LINKER_SYMBOL_PREFIXast_sip_subscription_get_remote_uri;
- LINKER_SYMBOL_PREFIXast_sip_subscription_get_header;
- LINKER_SYMBOL_PREFIXast_sip_subscription_is_terminated;
- LINKER_SYMBOL_PREFIXast_sip_subscription_destroy;
+ LINKER_SYMBOL_PREFIXast_sip_*;
local:
*;
};