summaryrefslogtreecommitdiff
path: root/res/res_pjsip_mwi.c
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2014-06-25 20:57:28 +0000
committerMark Michelson <mmichelson@digium.com>2014-06-25 20:57:28 +0000
commitbc8c08c6090da176afd48712477f4d66fc71ab2b (patch)
tree7de55cfa4d0ab5e595acb181172b38f4557280fe /res/res_pjsip_mwi.c
parent4a7a36a0a1533304844feac6901a724633bc71cc (diff)
Abstract PJSIP-specific elements from the pubsub API.
This helps to pave the way for RLS work that is to come. Since this is a self-contained change and subscription tests still pass, this work is being committed directly to trunk instead of a working branch. ASTERISK-23865 #close Review: https://reviewboard.asterisk.org/r/3628 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@417233 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/res_pjsip_mwi.c')
-rw-r--r--res/res_pjsip_mwi.c293
1 files changed, 115 insertions, 178 deletions
diff --git a/res/res_pjsip_mwi.c b/res/res_pjsip_mwi.c
index f25a7c48f..a8e2d1429 100644
--- a/res/res_pjsip_mwi.c
+++ b/res/res_pjsip_mwi.c
@@ -49,31 +49,24 @@ AO2_GLOBAL_OBJ_STATIC(unsolicited_mwi);
#define MWI_SUBTYPE "simple-message-summary"
static void mwi_subscription_shutdown(struct ast_sip_subscription *sub);
-static struct ast_sip_subscription *mwi_new_subscribe(struct ast_sip_endpoint *endpoint,
- pjsip_rx_data *rdata);
-static void mwi_resubscribe(struct ast_sip_subscription *sub, pjsip_rx_data *rdata,
- struct ast_sip_subscription_response_data *response_data);
-static void mwi_subscription_timeout(struct ast_sip_subscription *sub);
-static void mwi_subscription_terminated(struct ast_sip_subscription *sub, pjsip_rx_data *rdata);
-static void mwi_notify_response(struct ast_sip_subscription *sub, pjsip_rx_data *rdata);
-static void mwi_notify_request(struct ast_sip_subscription *sub, pjsip_rx_data *rdata,
- struct ast_sip_subscription_response_data *response_data);
-static int mwi_refresh_subscription(struct ast_sip_subscription *sub);
static void mwi_to_ami(struct ast_sip_subscription *sub, struct ast_str **buf);
+static int mwi_new_subscribe(struct ast_sip_endpoint *endpoint,
+ const char *resource);
+static int mwi_notify_required(struct ast_sip_subscription *sip_sub,
+ enum ast_sip_subscription_notify_reason reason);
+
+static struct ast_sip_notifier mwi_notifier = {
+ .default_accept = MWI_TYPE"/"MWI_SUBTYPE,
+ .new_subscribe = mwi_new_subscribe,
+ .notify_required = mwi_notify_required,
+};
static struct ast_sip_subscription_handler mwi_handler = {
.event_name = "message-summary",
.accept = { MWI_TYPE"/"MWI_SUBTYPE, },
- .default_accept = MWI_TYPE"/"MWI_SUBTYPE,
.subscription_shutdown = mwi_subscription_shutdown,
- .new_subscribe = mwi_new_subscribe,
- .resubscribe = mwi_resubscribe,
- .subscription_timeout = mwi_subscription_timeout,
- .subscription_terminated = mwi_subscription_terminated,
- .notify_response = mwi_notify_response,
- .notify_request = mwi_notify_request,
- .refresh_subscription = mwi_refresh_subscription,
.to_ami = mwi_to_ami,
+ .notifier = &mwi_notifier,
};
/*!
@@ -202,7 +195,7 @@ static void mwi_subscription_destructor(void *obj)
}
static struct mwi_subscription *mwi_subscription_alloc(struct ast_sip_endpoint *endpoint,
- enum ast_sip_subscription_role role, unsigned int is_solicited, pjsip_rx_data *rdata)
+ unsigned int is_solicited, struct ast_sip_subscription *sip_sub)
{
struct mwi_subscription *sub;
const char *endpoint_id = ast_sorcery_object_get_id(endpoint);
@@ -216,6 +209,7 @@ static struct mwi_subscription *mwi_subscription_alloc(struct ast_sip_endpoint *
/* Safe strcpy */
strcpy(sub->id, endpoint_id);
+
/* Unsolicited MWI doesn't actually result in a SIP subscription being
* created. This is because a SIP subscription associates with a dialog.
* Most devices expect unsolicited MWI NOTIFYs to appear out of dialog. If
@@ -224,13 +218,7 @@ static struct mwi_subscription *mwi_subscription_alloc(struct ast_sip_endpoint *
* state not being updated on the device
*/
if (is_solicited) {
- sub->sip_sub = ast_sip_create_subscription(&mwi_handler,
- role, endpoint, rdata);
- if (!sub->sip_sub) {
- ast_log(LOG_WARNING, "Unable to create MWI SIP subscription for endpoint %s\n", sub->id);
- ao2_cleanup(sub);
- return NULL;
- }
+ sub->sip_sub = ao2_bump(sip_sub);
}
sub->stasis_subs = ao2_container_alloc(STASIS_BUCKETS, stasis_sub_hash, stasis_sub_cmp);
@@ -314,7 +302,6 @@ struct unsolicited_mwi_data {
struct mwi_subscription *sub;
struct ast_sip_endpoint *endpoint;
pjsip_evsub_state state;
- const char *reason;
const struct ast_sip_body *body;
};
@@ -324,7 +311,6 @@ 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 char *reason = mwi_data->reason;
const struct ast_sip_body *body = mwi_data->body;
struct ast_sip_contact *contact = obj;
const char *state_name;
@@ -358,9 +344,6 @@ static int send_unsolicited_mwi_notify_to_contact(void *obj, void *arg, int flag
sub_state = pjsip_sub_state_hdr_create(tdata->pool);
pj_cstr(&sub_state->sub_state, state_name);
- if (reason) {
- pj_cstr(&sub_state->reason_param, reason);
- }
pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) sub_state);
event = pjsip_event_hdr_create(tdata->pool);
@@ -374,13 +357,15 @@ static int send_unsolicited_mwi_notify_to_contact(void *obj, void *arg, int flag
return 0;
}
-static void send_unsolicited_mwi_notify(struct mwi_subscription *sub, pjsip_evsub_state state, const char *reason,
- struct ast_sip_body *body)
+static void send_unsolicited_mwi_notify(struct mwi_subscription *sub,
+ struct ast_sip_message_accumulator *counter)
{
RAII_VAR(struct ast_sip_endpoint *, endpoint, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(),
"endpoint", sub->id), ao2_cleanup);
char *endpoint_aors;
char *aor_name;
+ struct ast_sip_body body;
+ struct ast_str *body_text;
if (!endpoint) {
ast_log(LOG_WARNING, "Unable to send unsolicited MWI to %s because endpoint does not exist\n",
@@ -393,17 +378,35 @@ static void send_unsolicited_mwi_notify(struct mwi_subscription *sub, pjsip_evsu
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, counter, &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",
+ sub->id, counter->new_msgs, counter->old_msgs);
+
while ((aor_name = strsep(&endpoint_aors, ","))) {
RAII_VAR(struct ast_sip_aor *, aor, ast_sip_location_retrieve_aor(aor_name), ao2_cleanup);
RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
struct unsolicited_mwi_data mwi_data = {
.sub = sub,
.endpoint = endpoint,
- .state = state,
- .reason = reason,
- .body = body,
+ .body = &body,
};
if (!aor) {
@@ -419,63 +422,25 @@ static void send_unsolicited_mwi_notify(struct mwi_subscription *sub, pjsip_evsu
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, pjsip_evsub_state state, const char *reason)
+static void send_mwi_notify(struct mwi_subscription *sub)
{
- const pj_str_t *reason_str_ptr = NULL;
struct ast_sip_message_accumulator counter = {
.old_msgs = 0,
.new_msgs = 0,
};
- RAII_VAR(struct ast_str *, body_text, ast_str_create(64), ast_free_ptr);
- pjsip_tx_data *tdata;
- pj_str_t reason_str;
- struct ast_sip_body body;
-
- body.type = sub->is_solicited ?
- ast_sip_subscription_get_body_type(sub->sip_sub) :
- MWI_TYPE;
-
- body.subtype = sub->is_solicited ?
- ast_sip_subscription_get_body_subtype(sub->sip_sub) :
- MWI_SUBTYPE;
ao2_callback(sub->stasis_subs, OBJ_NODATA, get_message_count, &counter);
- if (reason) {
- pj_cstr(&reason_str, reason);
- reason_str_ptr = &reason_str;
- }
-
- if (ast_sip_pubsub_generate_body_content(body.type, body.subtype, &counter, &body_text)) {
- ast_log(LOG_WARNING, "Unable to generate SIP MWI NOTIFY body.\n");
+ if (sub->is_solicited) {
+ ast_sip_subscription_notify(sub->sip_sub, &counter, 0);
return;
}
- body.body_text = ast_str_buffer(body_text);
-
- ast_debug(5, "Sending %s MWI NOTIFY to endpoint %s, new messages: %d, old messages: %d\n",
- sub->is_solicited ? "solicited" : "unsolicited", sub->id, counter.new_msgs,
- counter.old_msgs);
-
- if (sub->is_solicited) {
- if (pjsip_evsub_notify(ast_sip_subscription_get_evsub(sub->sip_sub),
- state, NULL, reason_str_ptr, &tdata) != PJ_SUCCESS) {
- ast_log(LOG_WARNING, "Unable to create MWI NOTIFY request to %s.\n", sub->id);
- return;
- }
- if (ast_sip_add_body(tdata, &body)) {
- ast_log(LOG_WARNING, "Unable to add body to MWI NOTIFY request\n");
- return;
- }
- if (ast_sip_subscription_send_request(sub->sip_sub, tdata) != PJ_SUCCESS) {
- ast_log(LOG_WARNING, "Unable to send MWI NOTIFY request to %s\n", sub->id);
- return;
- }
- } else {
- send_unsolicited_mwi_notify(sub, state, reason, &body);
- }
+ send_unsolicited_mwi_notify(sub, &counter);
}
static int unsubscribe_stasis(void *obj, void *arg, int flags)
@@ -620,10 +585,9 @@ static int mwi_on_aor(void *obj, void *arg, int flags)
}
static struct mwi_subscription *mwi_create_subscription(
- struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
+ struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
{
- struct mwi_subscription *sub = mwi_subscription_alloc(
- endpoint, AST_SIP_NOTIFIER, 1, rdata);
+ struct mwi_subscription *sub = mwi_subscription_alloc(endpoint, 1, sip_sub);
if (!sub) {
return NULL;
@@ -640,29 +604,23 @@ static struct mwi_subscription *mwi_create_subscription(
}
static struct mwi_subscription *mwi_subscribe_single(
- struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *name)
+ struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub, const char *name)
{
RAII_VAR(struct ast_sip_aor *, aor,
ast_sip_location_retrieve_aor(name), ao2_cleanup);
struct mwi_subscription *sub;
if (!aor) {
+ /*! I suppose it's possible for the AOR to disappear on us
+ * between accepting the subscription and sending the first
+ * NOTIFY...
+ */
ast_log(LOG_WARNING, "Unable to locate aor %s. MWI "
"subscription failed.\n", name);
return NULL;
}
- if (ast_strlen_zero(aor->mailboxes)) {
- ast_log(LOG_WARNING, "AOR %s has no configured mailboxes. "
- "MWI subscription failed\n", name);
- return NULL;
- }
-
- if (mwi_validate_for_aor(aor, endpoint, 0)) {
- return NULL;
- }
-
- if (!(sub = mwi_create_subscription(endpoint, rdata))) {
+ if (!(sub = mwi_create_subscription(endpoint, sip_sub))) {
return NULL;
}
@@ -671,15 +629,11 @@ static struct mwi_subscription *mwi_subscribe_single(
}
static struct mwi_subscription *mwi_subscribe_all(
- struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
+ struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
{
struct mwi_subscription *sub;
- if (ast_sip_for_each_aor(endpoint->aors, mwi_validate_for_aor, endpoint)) {
- return NULL;
- }
-
- sub = mwi_create_subscription(endpoint, rdata);
+ sub = mwi_create_subscription(endpoint, sip_sub);
if (!sub) {
return NULL;
@@ -689,106 +643,89 @@ static struct mwi_subscription *mwi_subscribe_all(
return sub;
}
-static struct ast_sip_subscription *mwi_new_subscribe(struct ast_sip_endpoint *endpoint,
- pjsip_rx_data *rdata)
+static int mwi_new_subscribe(struct ast_sip_endpoint *endpoint,
+ const char *resource)
{
- /* It's not obvious here, but the reference(s) to this subscription,
- * once this function exits, is held by the stasis subscription(s)
- * created in mwi_stasis_subscription_alloc()
- */
- RAII_VAR(struct mwi_subscription *, sub, NULL, ao2_cleanup);
- pjsip_uri *ruri = rdata->msg_info.msg->line.req.uri;
- pjsip_sip_uri *sip_ruri;
- char aor_name[80];
+ struct ast_sip_aor *aor;
- if (!PJSIP_URI_SCHEME_IS_SIP(ruri) && !PJSIP_URI_SCHEME_IS_SIPS(ruri)) {
- ast_log(LOG_WARNING, "Attempt to SUBSCRIBE to a non-SIP URI\n");
- return NULL;
- }
- sip_ruri = pjsip_uri_get_uri(ruri);
- ast_copy_pj_str(aor_name, &sip_ruri->user, sizeof(aor_name));
-
- /* no aor in uri? subscribe to all on endpoint */
- if (!(sub = ast_strlen_zero(aor_name) ? mwi_subscribe_all(endpoint, rdata) :
- mwi_subscribe_single(endpoint, rdata, aor_name))) {
- return NULL;
+ if (ast_strlen_zero(resource)) {
+ if (ast_sip_for_each_aor(endpoint->aors, mwi_validate_for_aor, endpoint)) {
+ return 500;
+ }
+ return 200;
}
- ast_sip_subscription_accept(sub->sip_sub, rdata, 200);
- send_mwi_notify(sub, PJSIP_EVSUB_STATE_ACTIVE, NULL);
+ aor = ast_sip_location_retrieve_aor(resource);
- return sub->sip_sub;
-}
-
-static void mwi_resubscribe(struct ast_sip_subscription *sub,
- pjsip_rx_data *rdata, struct ast_sip_subscription_response_data *response_data)
-{
- struct mwi_subscription *mwi_sub;
- pjsip_evsub_state state;
- pjsip_evsub *evsub;
- RAII_VAR(struct ast_datastore *, mwi_datastore,
- ast_sip_subscription_get_datastore(sub, "MWI datastore"), ao2_cleanup);
+ if (!aor) {
+ ast_log(LOG_WARNING, "Unable to locate aor %s. MWI "
+ "subscription failed.\n", resource);
+ return 404;
+ }
- if (!mwi_datastore) {
- return;
+ if (ast_strlen_zero(aor->mailboxes)) {
+ ast_log(LOG_WARNING, "AOR %s has no configured mailboxes. "
+ "MWI subscription failed\n", resource);
+ return 404;
}
- mwi_sub = mwi_datastore->data;
- evsub = ast_sip_subscription_get_evsub(sub);
- state = pjsip_evsub_get_state(evsub);
+ if (mwi_validate_for_aor(aor, endpoint, 0)) {
+ return 500;
+ }
- send_mwi_notify(mwi_sub, state, NULL);
+ return 200;
}
-static void mwi_subscription_timeout(struct ast_sip_subscription *sub)
+static int mwi_initial_subscription(struct ast_sip_subscription *sip_sub)
{
- struct mwi_subscription *mwi_sub;
- RAII_VAR(struct ast_datastore *, mwi_datastore,
- ast_sip_subscription_get_datastore(sub, "MWI datastore"), ao2_cleanup);
+ const char *resource = ast_sip_subscription_get_resource_name(sip_sub);
+ struct mwi_subscription *sub;
+ struct ast_sip_endpoint *endpoint = ast_sip_subscription_get_endpoint(sip_sub);
- if (!mwi_datastore) {
- return;
+ /* no aor in uri? subscribe to all on endpoint */
+ if (ast_strlen_zero(resource)) {
+ sub = mwi_subscribe_all(endpoint, sip_sub);
+ } else {
+ sub = mwi_subscribe_single(endpoint, sip_sub, resource);
}
+ if (!sub) {
+ ao2_cleanup(endpoint);
+ return -1;
+ }
- mwi_sub = mwi_datastore->data;
-
- ast_log(LOG_NOTICE, "MWI subscription for %s has timed out.\n", mwi_sub->id);
+ send_mwi_notify(sub);
- send_mwi_notify(mwi_sub, PJSIP_EVSUB_STATE_TERMINATED, "timeout");
+ ao2_cleanup(sub);
+ ao2_cleanup(endpoint);
+ return 0;
}
-static void mwi_subscription_terminated(struct ast_sip_subscription *sub, pjsip_rx_data *rdata)
+static int mwi_notify_required(struct ast_sip_subscription *sip_sub,
+ enum ast_sip_subscription_notify_reason reason)
{
struct mwi_subscription *mwi_sub;
- RAII_VAR(struct ast_datastore *, mwi_datastore,
- ast_sip_subscription_get_datastore(sub, "MWI datastore"), ao2_cleanup);
-
- if (!mwi_datastore) {
- return;
- }
+ struct ast_datastore *mwi_datastore;
- mwi_sub = mwi_datastore->data;
+ switch (reason) {
+ case AST_SIP_SUBSCRIPTION_NOTIFY_REASON_STARTED:
+ return mwi_initial_subscription(sip_sub);
+ case AST_SIP_SUBSCRIPTION_NOTIFY_REASON_RENEWED:
+ case AST_SIP_SUBSCRIPTION_NOTIFY_REASON_TERMINATED:
+ case AST_SIP_SUBSCRIPTION_NOTIFY_REASON_OTHER:
+ mwi_datastore = ast_sip_subscription_get_datastore(sip_sub, "MWI datastore");
- ast_log(LOG_NOTICE, "MWI subscription for %s has been terminated\n", mwi_sub->id);
+ if (!mwi_datastore) {
+ return -1;
+ }
- send_mwi_notify(mwi_sub, PJSIP_EVSUB_STATE_TERMINATED, NULL);
-}
+ mwi_sub = mwi_datastore->data;
-static void mwi_notify_response(struct ast_sip_subscription *sub, pjsip_rx_data *rdata)
-{
- /* We don't really care about NOTIFY responses for the moment */
-}
-
-static void mwi_notify_request(struct ast_sip_subscription *sub, pjsip_rx_data *rdata,
- struct ast_sip_subscription_response_data *response_data)
-{
- ast_log(LOG_WARNING, "Received an MWI NOTIFY request? This should not happen\n");
-}
+ send_mwi_notify(mwi_sub);
+ ao2_cleanup(mwi_datastore);
+ break;
+ }
-static int mwi_refresh_subscription(struct ast_sip_subscription *sub)
-{
- ast_log(LOG_WARNING, "Being told to refresh an MWI subscription? This should not happen\n");
return 0;
}
@@ -834,7 +771,7 @@ static int serialized_notify(void *userdata)
{
struct mwi_subscription *mwi_sub = userdata;
- send_mwi_notify(mwi_sub, PJSIP_EVSUB_STATE_ACTIVE, NULL);
+ send_mwi_notify(mwi_sub);
ao2_ref(mwi_sub, -1);
return 0;
}
@@ -885,7 +822,7 @@ static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, int flags
}
if (endpoint->subscription.mwi.aggregate) {
- aggregate_sub = mwi_subscription_alloc(endpoint, AST_SIP_NOTIFIER, 0, NULL);
+ aggregate_sub = mwi_subscription_alloc(endpoint, 0, NULL);
if (!aggregate_sub) {
return 0;
}
@@ -894,7 +831,7 @@ static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, int flags
mailboxes = ast_strdupa(endpoint->subscription.mwi.mailboxes);
while ((mailbox = strsep(&mailboxes, ","))) {
struct mwi_subscription *sub = aggregate_sub ?:
- mwi_subscription_alloc(endpoint, AST_SIP_SUBSCRIBER, 0, NULL);
+ mwi_subscription_alloc(endpoint, 0, NULL);
RAII_VAR(struct mwi_stasis_subscription *, mwi_stasis_sub,
mwi_stasis_subscription_alloc(mailbox, sub), ao2_cleanup);
if (mwi_stasis_sub) {