]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip_pubsub: Add some type safety when generating NOTIFY bodies.
authorMark Michelson <mmichelson@digium.com>
Thu, 18 Sep 2014 16:09:25 +0000 (16:09 +0000)
committerMark Michelson <mmichelson@digium.com>
Thu, 18 Sep 2014 16:09:25 +0000 (16:09 +0000)
res_pjsip_pubsub has two separate checks that it makes when a SUBSCRIBE
arrives.
* It checks that there is a subscription handler for the Event
* It checks that there are body generators for the types in the Accept header

The problem is, there's nothing that ensures that these two things will
actually mesh with each other. For instance, Asterisk will accept a subscription
to MWI that accepts pidf+xml bodies. That doesn't make sense.

With this commit, we add some type information to the mix. Subscription
handlers state they generate data of type X, and body generators state
that they consume data of type X. This way, Asterisk doesn't end up in
some hilariously mismatched situation like the one in the previous paragraph.

ASTERISK-24136 #close
Reported by Mark Michelson

Review: https://reviewboard.asterisk.org/r/3877
Review: https://reviewboard.asterisk.org/r/3878
........

Merged revisions 423344 from http://svn.asterisk.org/svn/asterisk/branches/12
........

Merged revisions 423348 from http://svn.asterisk.org/svn/asterisk/branches/13

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@423350 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/res_pjsip_pubsub.h
res/res_pjsip_dialog_info_body_generator.c
res/res_pjsip_exten_state.c
res/res_pjsip_mwi.c
res/res_pjsip_mwi_body_generator.c
res/res_pjsip_pidf_body_generator.c
res/res_pjsip_pubsub.c
res/res_pjsip_xpidf_body_generator.c

index 73b987479eca0f672d948f5f1c7df07a3c3c6606..aac4261c1e0d33b976950dc8172f34295add284d 100644 (file)
@@ -214,6 +214,21 @@ enum ast_sip_subscription_notify_reason {
        AST_SIP_SUBSCRIPTION_NOTIFY_REASON_OTHER
 };
 
+/*! Type used for conveying mailbox state */
+#define AST_SIP_EXTEN_STATE_DATA "ast_sip_exten_state_data"
+/*! Type used for extension state/presence */
+#define AST_SIP_MESSAGE_ACCUMULATOR "ast_sip_message_accumulator"
+
+/*!
+ * \brief Data used to create bodies for NOTIFY/PUBLISH requests.
+ */
+struct ast_sip_body_data {
+       /*! The type of the data */
+       const char *body_type;
+       /*! The actual data from which the body is generated */
+       void *body_data;
+};
+
 struct ast_sip_notifier {
        /*!
         * \brief Default body type defined for the event package this notifier handles.
@@ -285,6 +300,8 @@ struct ast_sip_subscriber {
 struct ast_sip_subscription_handler {
        /*! The name of the event this subscriber deals with */
        const char *event_name;
+       /*! Type of data used to generate NOTIFY bodies */
+       const char *body_type;
        /*! The types of body this subscriber accepts. */
        const char *accept[AST_SIP_MAX_ACCEPT];
        /*!
@@ -359,7 +376,7 @@ struct ast_taskprocessor *ast_sip_subscription_get_serializer(struct ast_sip_sub
  * \retval 0 Success
  * \retval non-zero Failure
  */
-int ast_sip_subscription_notify(struct ast_sip_subscription *sub, void *notify_data, int terminate);
+int ast_sip_subscription_notify(struct ast_sip_subscription *sub, struct ast_sip_body_data *notify_data, int terminate);
 
 /*!
  * \brief Retrieve the local URI for this subscription
@@ -501,6 +518,8 @@ struct ast_sip_pubsub_body_generator {
         * In "plain/text", "text" is the subtype
         */
        const char *subtype;
+       /*! Type of data the body generator takes as input */
+       const char *body_type;
        /*!
         * \brief allocate body structure.
         *
@@ -597,7 +616,7 @@ struct ast_sip_pubsub_body_supplement {
  * \retval non-zero Failure
  */
 int ast_sip_pubsub_generate_body_content(const char *content_type,
-               const char *content_subtype, void *data, struct ast_str **str);
+               const char *content_subtype, struct ast_sip_body_data *data, struct ast_str **str);
 
 /*!
  * \since 13.0.0
index 848ec10e41f1ac82ca84d05b05efd8d95870691b..06cff8d580f266af17df1ead2068d303ba9ffc49 100644 (file)
@@ -182,6 +182,7 @@ static void dialog_info_to_string(void *body, struct ast_str **str)
 static struct ast_sip_pubsub_body_generator dialog_info_body_generator = {
        .type = "application",
        .subtype = "dialog-info+xml",
+       .body_type = AST_SIP_EXTEN_STATE_DATA,
        .allocate_body = dialog_info_allocate_body,
        .generate_body_content = dialog_info_generate_body_content,
        .to_string = dialog_info_to_string,
index 29b26cc693c888f8314893ee328c9eae121a068c..4cc5a5881a8c5daeeb553f327fd0aaf22a7a6b68 100644 (file)
@@ -91,6 +91,7 @@ struct ast_sip_notifier dialog_notifier = {
 
 struct ast_sip_subscription_handler presence_handler = {
        .event_name = "presence",
+       .body_type = AST_SIP_EXTEN_STATE_DATA,
        .accept = { DEFAULT_PRESENCE_BODY, },
        .subscription_shutdown = subscription_shutdown,
        .to_ami = to_ami,
@@ -99,6 +100,7 @@ struct ast_sip_subscription_handler presence_handler = {
 
 struct ast_sip_subscription_handler dialog_handler = {
        .event_name = "dialog",
+       .body_type = AST_SIP_EXTEN_STATE_DATA,
        .accept = { DEFAULT_DIALOG_BODY, },
        .subscription_shutdown = subscription_shutdown,
        .to_ami = to_ami,
@@ -221,6 +223,10 @@ static struct notify_task_data *alloc_notify_task_data(char *exten, struct exten
 static int notify_task(void *obj)
 {
        RAII_VAR(struct notify_task_data *, task_data, obj, ao2_cleanup);
+       struct ast_sip_body_data data = {
+               .body_type = AST_SIP_EXTEN_STATE_DATA,
+               .body_data = &task_data->exten_state_data,
+       };
 
        /* Pool allocation has to happen here so that we allocate within a PJLIB thread */
        task_data->exten_state_data.pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(),
@@ -231,7 +237,7 @@ static int notify_task(void *obj)
 
        task_data->exten_state_data.sub = task_data->exten_state_sub->sip_sub;
 
-       ast_sip_subscription_notify(task_data->exten_state_sub->sip_sub, &task_data->exten_state_data,
+       ast_sip_subscription_notify(task_data->exten_state_sub->sip_sub, &data,
                        task_data->terminate);
 
        pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(),
index 37e1da0bbe9cc459907a4ee44fd22c5b3be0e987..bed07193e2ae88c86904c2eb9a5b91a73a5e06a1 100644 (file)
@@ -66,6 +66,7 @@ static struct ast_sip_notifier mwi_notifier = {
 
 static struct ast_sip_subscription_handler mwi_handler = {
        .event_name = "message-summary",
+       .body_type = AST_SIP_MESSAGE_ACCUMULATOR,
        .accept = { MWI_TYPE"/"MWI_SUBTYPE, },
        .subscription_shutdown = mwi_subscription_shutdown,
        .to_ami = mwi_to_ami,
@@ -369,6 +370,10 @@ static void send_unsolicited_mwi_notify(struct mwi_subscription *sub,
        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",
@@ -390,7 +395,7 @@ static void send_unsolicited_mwi_notify(struct mwi_subscription *sub,
                return;
        }
 
-       if (ast_sip_pubsub_generate_body_content(body.type, body.subtype, counter, &body_text)) {
+       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;
@@ -435,11 +440,15 @@ static void send_mwi_notify(struct mwi_subscription *sub)
                .old_msgs = 0,
                .new_msgs = 0,
        };
+       struct ast_sip_body_data data = {
+               .body_type = AST_SIP_MESSAGE_ACCUMULATOR,
+               .body_data = &counter,
+       };
 
        ao2_callback(sub->stasis_subs, OBJ_NODATA, get_message_count, &counter);
 
        if (sub->is_solicited) {
-               ast_sip_subscription_notify(sub->sip_sub, &counter, 0);
+               ast_sip_subscription_notify(sub->sip_sub, &data, 0);
                return;
        }
 
index 14c3d62161e75c9efb0b5af3d49397f163183f8e..2020e26ded558e2a82bac720409693282c75bd89 100644 (file)
@@ -85,6 +85,7 @@ static void mwi_destroy_body(void *body)
 static struct ast_sip_pubsub_body_generator mwi_generator = {
        .type = MWI_TYPE,
        .subtype = MWI_SUBTYPE,
+       .body_type = AST_SIP_MESSAGE_ACCUMULATOR,
        .allocate_body = mwi_allocate_body,
        .generate_body_content = mwi_generate_body_content,
        .to_string = mwi_to_string,
index 3181b2982a7e59cf4ffbce0ad0476c48c44d3339..e5002ceb5677e43d10cd76283504449c1c97f3c2 100644 (file)
@@ -108,6 +108,7 @@ static void pidf_to_string(void *body, struct ast_str **str)
 static struct ast_sip_pubsub_body_generator pidf_body_generator = {
        .type = "application",
        .subtype = "pidf+xml",
+       .body_type = AST_SIP_EXTEN_STATE_DATA,
        .allocate_body = pidf_allocate_body,
        .generate_body_content = pidf_generate_body_content,
        .to_string = pidf_to_string,
index bf12a28e6aeee70f4a2ba7cb7bec64251aeadf09..0611f2595395b1221ec6c0b9a089add58c050db8 100644 (file)
@@ -587,7 +587,7 @@ static void subscription_persistence_remove(struct sip_subscription_tree *sub_tr
 
 static struct ast_sip_subscription_handler *find_sub_handler_for_event_name(const char *event_name);
 static struct ast_sip_pubsub_body_generator *find_body_generator(char accept[AST_SIP_MAX_ACCEPT][64],
-               size_t num_accept);
+               size_t num_accept, const char *body_type);
 
 /*! \brief Retrieve a handler using the Event header of an rdata message */
 static struct ast_sip_subscription_handler *subscription_get_handler_from_rdata(pjsip_rx_data *rdata)
@@ -674,7 +674,7 @@ static struct ast_sip_pubsub_body_generator *subscription_get_generator_from_rda
                num_accept_headers = 1;
        }
 
-       return find_body_generator(accept, num_accept_headers);
+       return find_body_generator(accept, num_accept_headers, handler->body_type);
 }
 
 /*! \brief Check if the rdata has a Supported header containing 'eventlist'
@@ -2105,7 +2105,7 @@ static int schedule_notification(struct sip_subscription_tree *sub_tree)
        return 0;
 }
 
-int ast_sip_subscription_notify(struct ast_sip_subscription *sub, void *notify_data,
+int ast_sip_subscription_notify(struct ast_sip_subscription *sub, struct ast_sip_body_data *notify_data,
                int terminate)
 {
        if (ast_sip_pubsub_generate_body_content(ast_sip_subscription_get_body_type(sub),
@@ -2418,7 +2418,7 @@ static struct ast_sip_pubsub_body_generator *find_body_generator_accept(const ch
 }
 
 static struct ast_sip_pubsub_body_generator *find_body_generator(char accept[AST_SIP_MAX_ACCEPT][64],
-               size_t num_accept)
+               size_t num_accept, const char *body_type)
 {
        int i;
        struct ast_sip_pubsub_body_generator *generator = NULL;
@@ -2427,6 +2427,12 @@ static struct ast_sip_pubsub_body_generator *find_body_generator(char accept[AST
                generator = find_body_generator_accept(accept[i]);
                if (generator) {
                        ast_debug(3, "Body generator %p found for accept type %s\n", generator, accept[i]);
+                       if (strcmp(generator->body_type, body_type)) {
+                               ast_log(LOG_WARNING, "Body generator '%s/%s'(%p) does not accept the type of data this event generates\n",
+                                               generator->type, generator->subtype, generator);
+                               generator = NULL;
+                               continue;
+                       }
                        break;
                } else {
                        ast_debug(3, "No body generator found for accept type %s\n", accept[i]);
@@ -2440,6 +2446,9 @@ static int generate_initial_notify(struct ast_sip_subscription *sub)
 {
        void *notify_data;
        int res;
+       struct ast_sip_body_data data = {
+               .body_type = sub->handler->body_type,
+       };
 
        if (AST_VECTOR_SIZE(&sub->children) > 0) {
                int i;
@@ -2462,8 +2471,10 @@ static int generate_initial_notify(struct ast_sip_subscription *sub)
                return -1;
        }
 
+       data.body_data = notify_data;
+
        res = ast_sip_pubsub_generate_body_content(ast_sip_subscription_get_body_type(sub),
-                       ast_sip_subscription_get_body_subtype(sub), notify_data, &sub->body_text);
+                       ast_sip_subscription_get_body_subtype(sub), &data, &sub->body_text);
 
        ao2_cleanup(notify_data);
 
@@ -2981,7 +2992,7 @@ const char *ast_sip_subscription_get_body_subtype(struct ast_sip_subscription *s
 }
 
 int ast_sip_pubsub_generate_body_content(const char *type, const char *subtype,
-               void *data, struct ast_str **str)
+               struct ast_sip_body_data *data, struct ast_str **str)
 {
        struct ast_sip_pubsub_body_supplement *supplement;
        struct ast_sip_pubsub_body_generator *generator;
@@ -2995,14 +3006,19 @@ int ast_sip_pubsub_generate_body_content(const char *type, const char *subtype,
                return -1;
        }
 
-       body = generator->allocate_body(data);
+       if (strcmp(data->body_type, generator->body_type)) {
+               ast_log(LOG_WARNING, "Body generator does not accept the type of data provided\n");
+               return -1;
+       }
+
+       body = generator->allocate_body(data->body_data);
        if (!body) {
                ast_log(LOG_WARNING, "Unable to allocate a NOTIFY body of type %s/%s\n",
                                type, subtype);
                return -1;
        }
 
-       if (generator->generate_body_content(body, data)) {
+       if (generator->generate_body_content(body, data->body_data)) {
                res = -1;
                goto end;
        }
@@ -3011,7 +3027,7 @@ int ast_sip_pubsub_generate_body_content(const char *type, const char *subtype,
        AST_RWLIST_TRAVERSE(&body_supplements, supplement, list) {
                if (!strcmp(generator->type, supplement->type) &&
                                !strcmp(generator->subtype, supplement->subtype)) {
-                       res = supplement->supplement_body(body, data);
+                       res = supplement->supplement_body(body, data->body_data);
                        if (res) {
                                break;
                        }
index 38e036a7be5bfeb8b2888960985522004a372142..e7009afdfc60fddd595140aa1a52c61fb85b2f26 100644 (file)
@@ -125,6 +125,7 @@ static void xpidf_to_string(void *body, struct ast_str **str)
 static struct ast_sip_pubsub_body_generator xpidf_body_generator = {
        .type = "application",
        .subtype = "xpidf+xml",
+       .body_type = AST_SIP_EXTEN_STATE_DATA,
        .allocate_body = xpidf_allocate_body,
        .generate_body_content = xpidf_generate_body_content,
        .to_string = xpidf_to_string,
@@ -134,6 +135,7 @@ static struct ast_sip_pubsub_body_generator xpidf_body_generator = {
 static struct ast_sip_pubsub_body_generator cpim_pidf_body_generator = {
        .type = "application",
        .subtype = "cpim-pidf+xml",
+       .body_type = AST_SIP_EXTEN_STATE_DATA,
        .allocate_body = xpidf_allocate_body,
        .generate_body_content = xpidf_generate_body_content,
        .to_string = xpidf_to_string,