summaryrefslogtreecommitdiff
path: root/res/res_pjsip_pubsub.c
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2014-09-18 16:09:25 +0000
committerMark Michelson <mmichelson@digium.com>2014-09-18 16:09:25 +0000
commit79eac1ffcaa419a2c21c43dc9f1c26dda92594f9 (patch)
tree1f3a9272d8a70d968e0401e9bcc2df524c7eb096 /res/res_pjsip_pubsub.c
parent126334a7aa9a8ba27e5abe02f1a07e526675aab4 (diff)
res_pjsip_pubsub: Add some type safety when generating NOTIFY bodies.
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
Diffstat (limited to 'res/res_pjsip_pubsub.c')
-rw-r--r--res/res_pjsip_pubsub.c34
1 files changed, 25 insertions, 9 deletions
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index bf12a28e6..0611f2595 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -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;
}