Add vtable and methods for to_json and to_ami for Stasis messages

When a Stasis message type is defined in a loadable module, handling
those messages for AMI and res_stasis events can be cumbersome.

This patch adds a vtable to stasis_message_type, with to_ami and
to_json virtual functions. These allow messages to be handled
abstractly without putting module-specific code in core.

As an example, the VarSet AMI event was refactored to use the to_ami
virtual function.

(closes issue ASTERISK-21817)
Review: https://reviewboard.asterisk.org/r/2579/


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@391403 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
David M. Lee
2013-06-11 15:46:35 +00:00
parent 2053fc3159
commit dbdb2b1b3a
8 changed files with 430 additions and 119 deletions

View File

@@ -37,9 +37,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
/*! \internal */
struct stasis_message_type {
struct stasis_message_vtable *vtable;
char *name;
};
static struct stasis_message_vtable null_vtable = {};
static void message_type_dtor(void *obj)
{
struct stasis_message_type *type = obj;
@@ -47,7 +50,8 @@ static void message_type_dtor(void *obj)
type->name = NULL;
}
struct stasis_message_type *stasis_message_type_create(const char *name)
struct stasis_message_type *stasis_message_type_create(const char *name,
struct stasis_message_vtable *vtable)
{
RAII_VAR(struct stasis_message_type *, type, NULL, ao2_cleanup);
@@ -55,11 +59,16 @@ struct stasis_message_type *stasis_message_type_create(const char *name)
if (!type) {
return NULL;
}
if (!vtable) {
/* Null object pattern, FTW! */
vtable = &null_vtable;
}
type->name = ast_strdup(name);
if (!type->name) {
return NULL;
}
type->vtable = vtable;
ao2_ref(type, +1);
return type;
@@ -133,3 +142,26 @@ const struct timeval *stasis_message_timestamp(const struct stasis_message *msg)
}
return &msg->timestamp;
}
#define INVOKE_VIRTUAL(fn, ...) \
({ \
if (msg == NULL) { \
return NULL; \
} \
ast_assert(msg->type != NULL); \
ast_assert(msg->type->vtable != NULL); \
if (msg->type->vtable->fn == NULL) { \
return NULL; \
} \
msg->type->vtable->fn(__VA_ARGS__); \
})
struct ast_manager_event_blob *stasis_message_to_ami(struct stasis_message *msg)
{
return INVOKE_VIRTUAL(to_ami, msg);
}
struct ast_json *stasis_message_to_json(struct stasis_message *msg)
{
return INVOKE_VIRTUAL(to_json, msg);
}