diff options
author | David M. Lee <dlee@digium.com> | 2013-06-11 15:46:35 +0000 |
---|---|---|
committer | David M. Lee <dlee@digium.com> | 2013-06-11 15:46:35 +0000 |
commit | dbdb2b1b3a618a79b3e42c77c05cb2688b4da08d (patch) | |
tree | 6d7174c03a0388cf81bee13403cf4c118184d1d9 /main | |
parent | 2053fc31594d4069cb178e591ab2b4e0df08b268 (diff) |
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
Diffstat (limited to 'main')
-rw-r--r-- | main/manager.c | 35 | ||||
-rw-r--r-- | main/manager_channels.c | 48 | ||||
-rw-r--r-- | main/parking.c | 12 | ||||
-rw-r--r-- | main/stasis_channels.c | 94 | ||||
-rw-r--r-- | main/stasis_message.c | 34 |
5 files changed, 138 insertions, 85 deletions
diff --git a/main/manager.c b/main/manager.c index b8e55de4f..eb01cc536 100644 --- a/main/manager.c +++ b/main/manager.c @@ -1313,6 +1313,23 @@ struct ast_str *ast_manager_str_from_json_object(struct ast_json *blob, key_excl return output_str; } +static void manager_default_msg_cb(void *data, struct stasis_subscription *sub, + struct stasis_topic *topic, + struct stasis_message *message) +{ + RAII_VAR(struct ast_manager_event_blob *, ev, NULL, ao2_cleanup); + + ev = stasis_message_to_ami(message); + + if (ev == NULL) { + /* Not and AMI message; disregard */ + return; + } + + manager_event(ev->event_flags, ev->manager_event, "%s", + ev->extra_fields); +} + static void manager_generic_msg_cb(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message) @@ -7686,7 +7703,12 @@ static void manager_shutdown(void) */ static int manager_subscriptions_init(void) { - STASIS_MESSAGE_TYPE_INIT(ast_manager_get_generic_type); + int res; + + res = STASIS_MESSAGE_TYPE_INIT(ast_manager_get_generic_type); + if (res != 0) { + return -1; + } manager_topic = stasis_topic_create("manager_topic"); if (!manager_topic) { return -1; @@ -7696,10 +7718,13 @@ static int manager_subscriptions_init(void) return -1; } - if (stasis_message_router_add(stasis_router, - ast_manager_get_generic_type(), - manager_generic_msg_cb, - NULL)) { + res |= stasis_message_router_set_default(stasis_router, + manager_default_msg_cb, NULL); + + res |= stasis_message_router_add(stasis_router, + ast_manager_get_generic_type(), manager_generic_msg_cb, NULL); + + if (res != 0) { return -1; } return 0; diff --git a/main/manager_channels.c b/main/manager_channels.c index b6eeb60b0..277dc873d 100644 --- a/main/manager_channels.c +++ b/main/manager_channels.c @@ -710,49 +710,6 @@ static void channel_snapshot_update(void *data, struct stasis_subscription *sub, } } -static void channel_varset_cb(void *data, struct stasis_subscription *sub, - struct stasis_topic *topic, struct stasis_message *message) -{ - struct ast_channel_blob *obj = stasis_message_data(message); - RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free); - const char *variable = ast_json_string_get(ast_json_object_get(obj->blob, "variable")); - const char *value = ast_json_string_get(ast_json_object_get(obj->blob, "value")); - - if (obj->snapshot) { - channel_event_string = ast_manager_build_channel_state_string(obj->snapshot); - } else { - channel_event_string = ast_str_create(35); - ast_str_set(&channel_event_string, 0, - "Channel: none\r\n" - "Uniqueid: none\r\n"); - } - - if (!channel_event_string) { - return; - } - - /*** DOCUMENTATION - <managerEventInstance> - <synopsis>Raised when a variable is set to a particular value.</synopsis> - <syntax> - <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" /> - <parameter name="Variable"> - <para>The variable being set.</para> - </parameter> - <parameter name="Value"> - <para>The new value of the variable.</para> - </parameter> - </syntax> - </managerEventInstance> - ***/ - manager_event(EVENT_FLAG_DIALPLAN, "VarSet", - "%s" - "Variable: %s\r\n" - "Value: %s\r\n", - ast_str_buffer(channel_event_string), - variable, value); -} - static int userevent_exclusion_cb(const char *key) { if (!strcmp("type", key)) { @@ -1280,11 +1237,6 @@ int manager_channels_init(void) NULL); ret |= stasis_message_router_add(message_router, - ast_channel_varset_type(), - channel_varset_cb, - NULL); - - ret |= stasis_message_router_add(message_router, ast_channel_user_event_type(), channel_user_event_cb, NULL); diff --git a/main/parking.c b/main/parking.c index 2a5b72e61..a7cd0ba54 100644 --- a/main/parking.c +++ b/main/parking.c @@ -35,7 +35,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/channel.h" /*! \brief Message type for parked calls */ -static struct stasis_message_type *parked_call_type; +STASIS_MESSAGE_TYPE_DEFN(ast_parked_call_type); /*! \brief Topic for parking lots */ static struct stasis_topic *parking_topic; @@ -48,15 +48,14 @@ static ast_bridge_channel_park_fn ast_bridge_channel_park_func = NULL; void ast_parking_stasis_init(void) { - parked_call_type = stasis_message_type_create("ast_parked_call"); + STASIS_MESSAGE_TYPE_INIT(ast_parked_call_type); parking_topic = stasis_topic_create("ast_parking"); } void ast_parking_stasis_disable(void) { - ao2_cleanup(parked_call_type); + STASIS_MESSAGE_TYPE_CLEANUP(ast_parked_call_type); ao2_cleanup(parking_topic); - parked_call_type = NULL; parking_topic = NULL; } @@ -65,11 +64,6 @@ struct stasis_topic *ast_parking_topic(void) return parking_topic; } -struct stasis_message_type *ast_parked_call_type(void) -{ - return parked_call_type; -} - /*! \brief Destructor for parked_call_payload objects */ static void parked_call_payload_destructor(void *obj) { diff --git a/main/stasis_channels.c b/main/stasis_channels.c index 65e9f917d..8327384d7 100644 --- a/main/stasis_channels.c +++ b/main/stasis_channels.c @@ -36,29 +36,24 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/astobj2.h" #include "asterisk/stasis_channels.h" -#define NUM_MULTI_CHANNEL_BLOB_BUCKETS 7 +/*** DOCUMENTATION + <managerEvent language="en_US" name="VarSet"> + <managerEventInstance class="EVENT_FLAG_DIALPLAN"> + <synopsis>Raised when a variable is set to a particular value.</synopsis> + <syntax> + <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" /> + <parameter name="Variable"> + <para>The variable being set.</para> + </parameter> + <parameter name="Value"> + <para>The new value of the variable.</para> + </parameter> + </syntax> + </managerEventInstance> + </managerEvent> +***/ -/*! - * @{ \brief Define channel message types. - */ -STASIS_MESSAGE_TYPE_DEFN(ast_channel_snapshot_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_dial_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_varset_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_user_event_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_hangup_request_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_begin_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_end_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_hold_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_unhold_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_chanspy_start_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_chanspy_stop_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_fax_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_hangup_handler_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_moh_start_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_moh_stop_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_monitor_start_type); -STASIS_MESSAGE_TYPE_DEFN(ast_channel_monitor_stop_type); -/*! @} */ +#define NUM_MULTI_CHANNEL_BLOB_BUCKETS 7 /*! \brief Topic for all channels */ struct stasis_topic *channel_topic_all; @@ -540,6 +535,36 @@ void ast_channel_publish_varset(struct ast_channel *chan, const char *name, cons ast_channel_publish_blob(chan, ast_channel_varset_type(), blob); } +static struct ast_manager_event_blob *varset_to_ami(struct stasis_message *msg) +{ + RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free); + struct ast_channel_blob *obj = stasis_message_data(msg); + const char *variable = + ast_json_string_get(ast_json_object_get(obj->blob, "variable")); + const char *value = + ast_json_string_get(ast_json_object_get(obj->blob, "value")); + + if (obj->snapshot) { + channel_event_string = + ast_manager_build_channel_state_string(obj->snapshot); + } else { + channel_event_string = ast_str_create(35); + ast_str_set(&channel_event_string, 0, + "Channel: none\r\n" + "Uniqueid: none\r\n"); + } + + if (!channel_event_string) { + return NULL; + } + + return ast_manager_event_blob_create(EVENT_FLAG_DIALPLAN, "VarSet", + "%s" + "Variable: %s\r\n" + "Value: %s\r\n", + ast_str_buffer(channel_event_string), variable, value); +} + void ast_publish_channel_state(struct ast_channel *chan) { RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup); @@ -626,6 +651,31 @@ int ast_channel_snapshot_caller_id_equal( strcmp(old_snapshot->caller_name, new_snapshot->caller_name) == 0; } +/*! + * @{ \brief Define channel message types. + */ +STASIS_MESSAGE_TYPE_DEFN(ast_channel_snapshot_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_dial_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_varset_type, + .to_ami = varset_to_ami, + ); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_user_event_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_hangup_request_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_begin_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_end_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_hold_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_unhold_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_chanspy_start_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_chanspy_stop_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_fax_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_hangup_handler_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_moh_start_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_moh_stop_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_monitor_start_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_monitor_stop_type); + +/*! @} */ + static void stasis_channels_cleanup(void) { channel_topic_all_cached = stasis_caching_unsubscribe_and_join(channel_topic_all_cached); diff --git a/main/stasis_message.c b/main/stasis_message.c index 8d2373f4d..b25d1f25a 100644 --- a/main/stasis_message.c +++ b/main/stasis_message.c @@ -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); +} |