summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorDavid M. Lee <dlee@digium.com>2013-06-11 15:46:35 +0000
committerDavid M. Lee <dlee@digium.com>2013-06-11 15:46:35 +0000
commitdbdb2b1b3a618a79b3e42c77c05cb2688b4da08d (patch)
tree6d7174c03a0388cf81bee13403cf4c118184d1d9 /main
parent2053fc31594d4069cb178e591ab2b4e0df08b268 (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.c35
-rw-r--r--main/manager_channels.c48
-rw-r--r--main/parking.c12
-rw-r--r--main/stasis_channels.c94
-rw-r--r--main/stasis_message.c34
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);
+}