[asterisk-commits] kmoore: branch kmoore/stasis-channel_events r383943 - in /team/kmoore/stasis-...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Mar 26 20:37:14 CDT 2013
Author: kmoore
Date: Tue Mar 26 20:37:10 2013
New Revision: 383943
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383943
Log:
Re-commit all work up to this point
Modified:
team/kmoore/stasis-channel_events/apps/app_userevent.c
team/kmoore/stasis-channel_events/include/asterisk/channel.h
team/kmoore/stasis-channel_events/main/channel.c
team/kmoore/stasis-channel_events/main/channel_internal_api.c
team/kmoore/stasis-channel_events/main/manager_channels.c
Modified: team/kmoore/stasis-channel_events/apps/app_userevent.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-channel_events/apps/app_userevent.c?view=diff&rev=383943&r1=383942&r2=383943
==============================================================================
--- team/kmoore/stasis-channel_events/apps/app_userevent.c (original)
+++ team/kmoore/stasis-channel_events/apps/app_userevent.c Tue Mar 26 20:37:10 2013
@@ -69,7 +69,6 @@
AST_APP_ARG(eventname);
AST_APP_ARG(extra)[100];
);
- RAII_VAR(struct ast_str *, body, ast_str_create(16), ast_free);
RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
@@ -78,26 +77,37 @@
return -1;
}
- if (!body) {
- ast_log(LOG_WARNING, "Unable to allocate buffer\n");
- return -1;
- }
-
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
- for (x = 0; x < args.argc - 1; x++) {
- ast_str_append(&body, 0, "%s\r\n", args.extra[x]);
+ blob = ast_json_pack("{s: s, s: s}",
+ "type", "userevent",
+ "eventname", args.eventname);
+
+ if (!blob) {
+ return -1;
}
- blob = ast_json_pack("{s: s, s: s, s: s}",
- "type", "userevent",
- "eventname", args.eventname,
- "body", ast_str_buffer(body));
- if (!blob) {
- ast_log(LOG_WARNING, "Unable to create message buffer\n");
- return -1;
+ for (x = 0; x < args.argc - 1; x++) {
+ char *key, *value = args.extra[x];
+ RAII_VAR(struct ast_json *, json_value, NULL, ast_json_unref);
+
+ key = strsep(&value, ":");
+ if (!value) {
+ /* no ':' in string? */
+ continue;
+ }
+
+ value = ast_strip(value);
+ json_value = ast_json_string_create(value);
+ if (!json_value) {
+ return -1;
+ }
+
+ if (ast_json_object_set(blob, key, json_value)) {
+ return -1;
+ }
}
msg = ast_channel_blob_create(chan, blob);
Modified: team/kmoore/stasis-channel_events/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-channel_events/include/asterisk/channel.h?view=diff&rev=383943&r1=383942&r2=383943
==============================================================================
--- team/kmoore/stasis-channel_events/include/asterisk/channel.h (original)
+++ team/kmoore/stasis-channel_events/include/asterisk/channel.h Tue Mar 26 20:37:10 2013
@@ -4199,6 +4199,16 @@
/*!
* \since 12
+ * \brief Get the channel topic using the channel's uniqueid.
+ *
+ * \param uniqueid Unique ID of the channel for which to retreive the topic.
+ *
+ * \retval Topic for channel's events.
+ */
+struct stasis_topic *ast_channel_topic_by_uniqueid(const char *uniqueid);
+
+/*!
+ * \since 12
* \brief A topic which publishes the events for all channels.
* \retval Topic for all channel events.
*/
@@ -4247,6 +4257,22 @@
/*!
* \since 12
+ * \brief Creates a \ref ast_channel_blob message from an existing snapshot.
+ *
+ * The \a blob JSON object requires a \c "type" field describing the blob. It
+ * should also be treated as immutable and not modified after it is put into the
+ * message.
+ *
+ * \param snapshot Snapshot of channel blob is associated with.
+ * \param blob JSON object representing the data.
+ * \return \ref ast_channel_blob message.
+ * \return \c NULL on error
+ */
+struct stasis_message *ast_channel_blob_create_from_snapshot(struct ast_channel_snapshot *snapshot,
+ struct ast_json *blob);
+
+/*!
+ * \since 12
* \brief Creates a \ref ast_channel_blob message.
*
* The \a blob JSON object requires a \c "type" field describing the blob. It
Modified: team/kmoore/stasis-channel_events/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-channel_events/main/channel.c?view=diff&rev=383943&r1=383942&r2=383943
==============================================================================
--- team/kmoore/stasis-channel_events/main/channel.c (original)
+++ team/kmoore/stasis-channel_events/main/channel.c Tue Mar 26 20:37:10 2013
@@ -160,6 +160,8 @@
struct stasis_topic *__channel_topic_all;
struct stasis_caching_topic *__channel_topic_all_cached;
+
+struct stasis_topic_pool *channel_topic_pool;
/*! \brief map AST_CAUSE's to readable string representations
*
@@ -262,17 +264,15 @@
ast_json_unref(event->blob);
}
-struct stasis_message *ast_channel_blob_create(struct ast_channel *chan,
- struct ast_json *blob)
+struct stasis_message *ast_channel_blob_create_from_snapshot(struct ast_channel_snapshot *snapshot,
+ struct ast_json *blob)
{
RAII_VAR(struct ast_channel_blob *, obj, NULL, ao2_cleanup);
- RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
- struct ast_json *type;
+ struct stasis_message *msg;
ast_assert(blob != NULL);
- type = ast_json_object_get(blob, "type");
- if (type == NULL) {
+ if (!ast_json_object_get(blob, "type")) {
ast_log(LOG_ERROR, "Invalid ast_channel_blob; missing type field");
return NULL;
}
@@ -282,11 +282,9 @@
return NULL;
}
- if (chan) {
- obj->snapshot = ast_channel_snapshot_create(chan);
- if (obj->snapshot == NULL) {
- return NULL;
- }
+ if (snapshot) {
+ obj->snapshot = snapshot;
+ ao2_ref(snapshot, +1);
}
obj->blob = ast_json_ref(blob);
@@ -296,8 +294,22 @@
return NULL;
}
- ao2_ref(msg, +1);
return msg;
+}
+
+struct stasis_message *ast_channel_blob_create(struct ast_channel *chan,
+ struct ast_json *blob)
+{
+ RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+
+ if (chan) {
+ snapshot = ast_channel_snapshot_create(chan);
+ if (!snapshot) {
+ return NULL;
+ }
+ }
+
+ return ast_channel_blob_create_from_snapshot(snapshot, blob);
}
const char *ast_channel_blob_type(struct ast_channel_blob *obj)
@@ -318,7 +330,7 @@
ast_assert(value != NULL);
blob = ast_json_pack("{s: s, s: s, s: s}",
- "type", "varset",
+ "type", "VarSet",
"variable", name,
"value", value);
publish_channel_blob(chan, blob);
@@ -8707,6 +8719,8 @@
__channel_blob = NULL;
ao2_cleanup(__channel_topic_all);
__channel_topic_all = NULL;
+ ao2_cleanup(channel_topic_pool);
+ channel_topic_pool = NULL;
__channel_topic_all_cached = stasis_caching_unsubscribe(__channel_topic_all_cached);
ast_data_unregister(NULL);
ast_cli_unregister_multiple(cli_channel, ARRAY_LEN(cli_channel));
@@ -8740,6 +8754,8 @@
__channel_topic_all = stasis_topic_create("ast_channel_topic_all");
__channel_topic_all_cached = stasis_caching_topic_create(__channel_topic_all, channel_snapshot_get_id);
+
+ channel_topic_pool = stasis_topic_pool_create(__channel_topic_all);
ast_cli_register_multiple(cli_channel, ARRAY_LEN(cli_channel));
@@ -11399,6 +11415,16 @@
return __channel_topic_all_cached;
}
+struct stasis_topic *ast_channel_topic_by_uniqueid(const char *uniqueid)
+{
+ return stasis_topic_pool_get_topic(channel_topic_pool, uniqueid);
+}
+
+struct stasis_topic *ast_channel_topic(struct ast_channel *chan)
+{
+ return chan ? ast_channel_topic_by_uniqueid(ast_channel_uniqueid(chan)) : ast_channel_topic_all();
+}
+
/* DO NOT PUT ADDITIONAL FUNCTIONS BELOW THIS BOUNDARY
*
* ONLY FUNCTIONS FOR PROVIDING BACKWARDS ABI COMPATIBILITY BELONG HERE
Modified: team/kmoore/stasis-channel_events/main/channel_internal_api.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-channel_events/main/channel_internal_api.c?view=diff&rev=383943&r1=383942&r2=383943
==============================================================================
--- team/kmoore/stasis-channel_events/main/channel_internal_api.c (original)
+++ team/kmoore/stasis-channel_events/main/channel_internal_api.c Tue Mar 26 20:37:10 2013
@@ -195,8 +195,6 @@
char dtmf_digit_to_emulate; /*!< Digit being emulated */
char sending_dtmf_digit; /*!< Digit this channel is currently sending out. (zero if not sending) */
struct timeval sending_dtmf_tv; /*!< The time this channel started sending the current digit. (Invalid if sending_dtmf_digit is zero.) */
- struct stasis_topic *topic; /*!< Topic for all channel's events */
- struct stasis_subscription *forwarder; /*!< Subscription for event forwarding to all topic */
};
/* AST_DATA definitions, which will probably have to be re-thought since the channel will be opaque */
@@ -1366,11 +1364,6 @@
}
ast_string_field_free_memory(chan);
-
- chan->forwarder = stasis_unsubscribe(chan->forwarder);
-
- ao2_cleanup(chan->topic);
- chan->topic = NULL;
}
void ast_channel_internal_finalize(struct ast_channel *chan)
@@ -1383,21 +1376,10 @@
return chan->finalized;
}
-struct stasis_topic *ast_channel_topic(struct ast_channel *chan)
-{
- return chan ? chan->topic : ast_channel_topic_all();
-}
-
void ast_channel_internal_setup_topics(struct ast_channel *chan)
{
- const char *topic_name = chan->uniqueid;
- ast_assert(chan->topic == NULL);
- ast_assert(chan->forwarder == NULL);
-
- if (ast_strlen_zero(topic_name)) {
- topic_name = "<dummy-channel>";
- }
-
- chan->topic = stasis_topic_create(topic_name);
- chan->forwarder = stasis_forward_all(chan->topic, ast_channel_topic_all());
-}
+ struct stasis_topic *topic;
+
+ topic = ast_channel_topic_by_uniqueid(chan->uniqueid);
+ ast_assert(topic != NULL);
+}
Modified: team/kmoore/stasis-channel_events/main/manager_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/stasis-channel_events/main/manager_channels.c?view=diff&rev=383943&r1=383942&r2=383943
==============================================================================
--- team/kmoore/stasis-channel_events/main/manager_channels.c (original)
+++ team/kmoore/stasis-channel_events/main/manager_channels.c Tue Mar 26 20:37:10 2013
@@ -37,6 +37,10 @@
#include "asterisk/pbx.h"
static struct stasis_message_router *channel_state_router;
+
+static struct ao2_container *channel_blob_handlers;
+
+#define BLOB_HANDLER_BUCKETS 57
/*** DOCUMENTATION
<managerEvent language="en_US" name="Newchannel">
@@ -150,6 +154,20 @@
<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
<parameter name="CID-CallingPres">
<para>A description of the Caller ID presentation.</para>
+ </parameter>
+ </syntax>
+ </managerEventInstance>
+ </managerEvent>
+ <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>
@@ -216,86 +234,32 @@
return out;
}
-/*! \brief Struct containing info for an AMI channel event to send out. */
-struct snapshot_manager_event {
- /*! event_flags manager_event() flags parameter. */
- int event_flags;
- /*! manager_event manager_event() category. */
- const char *manager_event;
- AST_DECLARE_STRING_FIELDS(
- /* extra fields to include in the event. */
- AST_STRING_FIELD(extra_fields);
- );
-};
-
-static void snapshot_manager_event_dtor(void *obj)
-{
- struct snapshot_manager_event *ev = obj;
- ast_string_field_free_memory(ev);
-}
-
-/*!
- * \brief Construct a \ref snapshot_manager_event.
- * \param event_flags manager_event() flags parameter.
- * \param manager_event manager_event() category.
- * \param extra_fields_fmt Format string for extra fields to include.
- * Or NO_EXTRA_FIELDS for no extra fields.
- * \return New \ref snapshot_manager_event object.
- * \return \c NULL on error.
- */
-static struct snapshot_manager_event *
-__attribute__((format(printf, 3, 4)))
-snapshot_manager_event_create(
- int event_flags,
- const char *manager_event,
- const char *extra_fields_fmt,
- ...)
-{
- RAII_VAR(struct snapshot_manager_event *, ev, NULL, ao2_cleanup);
- va_list argp;
-
- ast_assert(extra_fields_fmt != NULL);
- ast_assert(manager_event != NULL);
-
- ev = ao2_alloc(sizeof(*ev), snapshot_manager_event_dtor);
- if (!ev) {
- return NULL;
- }
-
- if (ast_string_field_init(ev, 20)) {
- return NULL;
- }
-
- ev->manager_event = manager_event;
- ev->event_flags = event_flags;
-
- va_start(argp, extra_fields_fmt);
- ast_string_field_ptr_build_va(ev, &ev->extra_fields, extra_fields_fmt,
- argp);
- va_end(argp);
-
- ao2_ref(ev, +1);
- return ev;
-}
-
-/*! GCC warns about blank or NULL format strings. So, shenanigans! */
-#define NO_EXTRA_FIELDS "%s", ""
-
-/*! \brief Typedef for callbacks that get called on channel snapshot updates */
-typedef struct snapshot_manager_event *(*snapshot_monitor)(
- struct ast_channel_snapshot *old_snapshot,
- struct ast_channel_snapshot *new_snapshot);
+static void publish_channel_blob(struct ast_channel_snapshot *snapshot, struct ast_json *blob)
+{
+ RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+
+ if (!blob) {
+ return;
+ }
+
+ msg = ast_channel_blob_create_from_snapshot(snapshot, blob);
+ if (!msg) {
+ return;
+ }
+
+ stasis_publish(ast_channel_topic_by_uniqueid(snapshot->uniqueid), msg);
+}
/*! \brief Handle channel state changes */
-static struct snapshot_manager_event *channel_state_change(
+static void channel_generate_state_change(
struct ast_channel_snapshot *old_snapshot,
struct ast_channel_snapshot *new_snapshot)
{
- int is_hungup, was_hungup;
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
if (!new_snapshot) {
/* Ignore cache clearing events; we'll see the hangup first */
- return NULL;
+ return;
}
/* The Newchannel, Newstate and Hangup events are closely related, in
@@ -304,29 +268,19 @@
*/
if (!old_snapshot) {
- return snapshot_manager_event_create(
- EVENT_FLAG_CALL, "Newchannel", NO_EXTRA_FIELDS);
- }
-
- was_hungup = ast_test_flag(&old_snapshot->flags, AST_FLAG_ZOMBIE) ? 1 : 0;
- is_hungup = ast_test_flag(&new_snapshot->flags, AST_FLAG_ZOMBIE) ? 1 : 0;
-
- if (!was_hungup && is_hungup) {
- return snapshot_manager_event_create(
- EVENT_FLAG_CALL, "Hangup",
- "Cause: %d\r\n"
- "Cause-txt: %s\r\n",
- new_snapshot->hangupcause,
- ast_cause2str(new_snapshot->hangupcause));
- }
-
- if (old_snapshot->state != new_snapshot->state) {
- return snapshot_manager_event_create(
- EVENT_FLAG_CALL, "Newstate", NO_EXTRA_FIELDS);
- }
-
- /* No event */
- return NULL;
+ blob = ast_json_pack("{s: s}",
+ "type", "Newchannel");
+ } else if (!ast_test_flag(&old_snapshot->flags, AST_FLAG_ZOMBIE) && ast_test_flag(&new_snapshot->flags, AST_FLAG_ZOMBIE)) {
+ blob = ast_json_pack("{s: s, s: i, s: s}",
+ "type", "Hangup",
+ "Cause", new_snapshot->hangupcause,
+ "Cause-txt", ast_cause2str(new_snapshot->hangupcause));
+ } else if (old_snapshot->state != new_snapshot->state) {
+ blob = ast_json_pack("{s: s}",
+ "type", "Newstate");
+ }
+
+ publish_channel_blob(new_snapshot, blob);
}
/*!
@@ -357,33 +311,32 @@
strcmp(old_snapshot->exten, new_snapshot->exten) == 0;
}
-static struct snapshot_manager_event *channel_newexten(
+static void channel_generate_newexten(
struct ast_channel_snapshot *old_snapshot,
struct ast_channel_snapshot *new_snapshot)
{
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
/* No Newexten event on cache clear */
if (!new_snapshot) {
- return NULL;
+ return;
}
/* Empty application is not valid for a Newexten event */
if (ast_strlen_zero(new_snapshot->appl)) {
- return NULL;
+ return;
}
if (old_snapshot && cep_equal(old_snapshot, new_snapshot)) {
- return NULL;
- }
-
- /* DEPRECATED: Extension field deprecated in 12; remove in 14 */
- return snapshot_manager_event_create(
- EVENT_FLAG_CALL, "Newexten",
- "Extension: %s\r\n"
- "Application: %s\r\n"
- "AppData: %s\r\n",
- new_snapshot->exten,
- new_snapshot->appl,
- new_snapshot->data);
+ return;
+ }
+
+ blob = ast_json_pack("{s: s, s: s, s: s}",
+ "type", "Newexten",
+ "Application", new_snapshot->appl,
+ "AppData", new_snapshot->data);
+
+ publish_channel_blob(new_snapshot, blob);
}
/*!
@@ -403,37 +356,48 @@
strcmp(old_snapshot->caller_name, new_snapshot->caller_name) == 0;
}
-static struct snapshot_manager_event *channel_new_callerid(
+static void channel_generate_newcallerid(
struct ast_channel_snapshot *old_snapshot,
struct ast_channel_snapshot *new_snapshot)
{
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+ RAII_VAR(struct ast_str *, calling_pres, ast_str_create(32), ast_free);
+
/* No NewCallerid event on cache clear or first event */
if (!old_snapshot || !new_snapshot) {
- return NULL;
+ return;
}
if (caller_id_equal(old_snapshot, new_snapshot)) {
- return NULL;
- }
-
- return snapshot_manager_event_create(
- EVENT_FLAG_CALL, "NewCallerid",
- "CID-CallingPres: %d (%s)\r\n",
+ return;
+ }
+
+ ast_str_set(&calling_pres, 0, "%d (%s)",
new_snapshot->caller_pres,
ast_describe_caller_presentation(new_snapshot->caller_pres));
-}
+
+ blob = ast_json_pack("{s: s, s: s}",
+ "type", "NewCallerid",
+ "CID-CallingPres", ast_str_buffer(calling_pres));
+
+ publish_channel_blob(new_snapshot, blob);
+}
+
+/*! \brief Typedef for callbacks that get called on channel snapshot updates */
+typedef void (*snapshot_monitor)(
+ struct ast_channel_snapshot *old_snapshot,
+ struct ast_channel_snapshot *new_snapshot);
snapshot_monitor monitors[] = {
- channel_state_change,
- channel_newexten,
- channel_new_callerid
+ channel_generate_state_change,
+ channel_generate_newexten,
+ channel_generate_newcallerid
};
static void channel_snapshot_update(void *data, struct stasis_subscription *sub,
struct stasis_topic *topic,
struct stasis_message *message)
{
- RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
struct stasis_cache_update *update;
struct ast_channel_snapshot *old_snapshot;
struct ast_channel_snapshot *new_snapshot;
@@ -449,33 +413,57 @@
new_snapshot = stasis_message_data(update->new_snapshot);
for (i = 0; i < ARRAY_LEN(monitors); ++i) {
- RAII_VAR(struct snapshot_manager_event *, ev, NULL, ao2_cleanup);
- ev = monitors[i](old_snapshot, new_snapshot);
-
- if (!ev) {
+ monitors[i](old_snapshot, new_snapshot);
+ }
+}
+
+/*!
+ * \brief Callback used to determine whether a key should be skipped when converting a JSON object to a manager blob
+ * \param key Key from JSON blob to be evaluated
+ * \retval non-zero if the key should be excluded
+ * \retval zero if the key should not be excluded
+ */
+typedef int (*key_exclusion_cb)(const char *key);
+
+static int default_exclusion_cb(const char *key)
+{
+ if (!strcmp("type", key)) {
+ return 1;
+ }
+ return 0;
+}
+
+#define manager_str_from_blob(blob) \
+ manager_str_from_blob_exclusion(blob, default_exclusion_cb)
+
+static struct ast_str *manager_str_from_blob_exclusion(struct ast_json *blob, key_exclusion_cb exclusion_cb)
+{
+ struct ast_str *output_str = ast_str_create(32);
+ struct ast_json_iter *blob_iter = ast_json_object_iter(blob);
+ if (!output_str || !blob_iter) {
+ return NULL;
+ }
+
+ do {
+ const char *key = ast_json_object_iter_key(blob_iter);
+ const char *value = ast_json_string_get(ast_json_object_iter_value(blob_iter));
+ if (exclusion_cb && exclusion_cb(key)) {
continue;
}
- /* If we haven't already, build the channel event string */
- if (!channel_event_string) {
- channel_event_string =
- manager_build_channel_state_string(new_snapshot);
- if (!channel_event_string) {
- return;
- }
+ ast_str_append(&output_str, 0, "%s: %s\r\n", key, value);
+ if (!output_str) {
+ return NULL;
}
-
- manager_event(ev->event_flags, ev->manager_event, "%s%s",
- ast_str_buffer(channel_event_string),
- ev->extra_fields);
- }
-}
-
-static void channel_varset(struct ast_channel_blob *obj)
+ } while ((blob_iter = ast_json_object_iter_next(blob, blob_iter)));
+
+ return output_str;
+}
+
+static void channel_manager_generic(struct ast_channel_blob *obj, int manager_flag)
{
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"));
+ RAII_VAR(struct ast_str *, blob_str, manager_str_from_blob(obj->blob), ast_free);
if (obj->snapshot) {
channel_event_string = manager_build_channel_state_string(obj->snapshot);
@@ -486,43 +474,38 @@
"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",
+ if (!channel_event_string || !blob_str) {
+ return;
+ }
+
+ manager_event(manager_flag, ast_channel_blob_type(obj),
"%s"
- "Variable: %s\r\n"
- "Value: %s\r\n",
+ "%s",
ast_str_buffer(channel_event_string),
- variable, value);
-}
-
-static void channel_userevent(struct ast_channel_blob *obj)
+ ast_str_buffer(blob_str));
+}
+
+static int userevent_exclusion_cb(const char *key)
+{
+ if (!strcmp("type", key)) {
+ return 1;
+ }
+ if (!strcmp("eventname", key)) {
+ return 1;
+ }
+ return 0;
+}
+
+static void channel_userevent(struct ast_channel_blob *obj, int manager_flag)
{
RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
+ RAII_VAR(struct ast_str *, body, manager_str_from_blob_exclusion(obj->blob, userevent_exclusion_cb), ast_free);
const char *eventname;
- const char *body;
eventname = ast_json_string_get(ast_json_object_get(obj->blob, "eventname"));
- body = ast_json_string_get(ast_json_object_get(obj->blob, "body"));
channel_event_string = manager_build_channel_state_string(obj->snapshot);
- if (!channel_event_string) {
+ if (!channel_event_string || !body) {
return;
}
@@ -544,10 +527,10 @@
"%s"
"UserEvent: %s\r\n"
"%s",
- ast_str_buffer(channel_event_string), eventname, body);
-}
-
-static void channel_hangup_request(struct ast_channel_blob *obj)
+ ast_str_buffer(channel_event_string), eventname, ast_str_buffer(body));
+}
+
+static void channel_hangup_request(struct ast_channel_blob *obj, int manager_flag)
{
RAII_VAR(struct ast_str *, extra, NULL, ast_free);
RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
@@ -582,6 +565,60 @@
"%s%s",
ast_str_buffer(channel_event_string),
ast_str_buffer(extra));
+}
+
+static void channel_newexten(struct ast_channel_blob *obj, int manager_flag)
+{
+ RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
+ RAII_VAR(struct ast_str *, blob_str, manager_str_from_blob(obj->blob), ast_free);
+
+ channel_event_string = manager_build_channel_state_string(obj->snapshot);
+
+ if (!channel_event_string || !blob_str) {
+ return;
+ }
+
+ /* DEPRECATED: Extension field deprecated in 12; remove in 14 */
+ manager_event(manager_flag, ast_channel_blob_type(obj),
+ "%s"
+ "%s"
+ "Extension: %s\r\n",
+ ast_str_buffer(channel_event_string),
+ ast_str_buffer(blob_str),
+ obj->snapshot->exten);
+}
+
+typedef void (*blob_handler_cb)(struct ast_channel_blob *obj, int manager_flag);
+
+struct blob_handler {
+ char *type;
+ int flag;
+ blob_handler_cb handler_cb;
+};
+
+static void blob_handler_destroy(void *obj)
+{
+ struct blob_handler *handler = obj;
+ ast_free(handler->type);
+}
+
+static void register_blob_handler(char *type, int flag, blob_handler_cb handler_cb)
+{
+ RAII_VAR(struct blob_handler *, handler, ao2_alloc(sizeof(*handler), blob_handler_destroy), ao2_cleanup);
+
+ if (!handler) {
+ return;
+ }
+
+ handler->type = ast_strdup(type);
+
+ if (!type) {
+ return;
+ }
+
+ handler->handler_cb = handler_cb;
+ handler->flag = flag;
+ ao2_link(channel_blob_handlers, handler);
}
/*!
@@ -592,20 +629,32 @@
struct stasis_message *message)
{
struct ast_channel_blob *obj = stasis_message_data(message);
-
- if (strcmp("varset", ast_channel_blob_type(obj)) == 0) {
- channel_varset(obj);
- } else if (strcmp("userevent", ast_channel_blob_type(obj)) == 0) {
- channel_userevent(obj);
- } else if (strcmp("hangup_request", ast_channel_blob_type(obj)) == 0) {
- channel_hangup_request(obj);
- }
+ RAII_VAR(struct blob_handler *, handler, ao2_find(channel_blob_handlers, ast_channel_blob_type(obj), OBJ_KEY), ao2_cleanup);
+
+ if (handler) {
+ handler->handler_cb(obj, handler->flag);
+ }
+}
+
+static int blob_handler_hash(const void *obj, const int flags)
+{
+ const char *handler_type = (flags & OBJ_KEY) ? obj : ((struct blob_handler*) obj)->type;
+ return ast_str_case_hash(handler_type);
+}
+
+static int blob_handler_cmp(void *obj, void *arg, int flags)
+{
+ struct blob_handler *opt1 = obj, *opt2 = arg;
+ const char *handler_type = (flags & OBJ_KEY) ? arg : opt2->type;
+ return strcasecmp(opt1->type, handler_type) ? 0 : CMP_MATCH | CMP_STOP;
}
static void manager_channels_shutdown(void)
{
stasis_message_router_unsubscribe(channel_state_router);
channel_state_router = NULL;
+ ao2_cleanup(channel_blob_handlers);
+ channel_blob_handlers = NULL;
}
int manager_channels_init(void)
@@ -644,5 +693,21 @@
return -1;
}
+ channel_blob_handlers = ao2_container_alloc(BLOB_HANDLER_BUCKETS, blob_handler_hash, blob_handler_cmp);
+
+ if (!channel_blob_handlers) {
+ manager_channels_shutdown();
+ return -1;
+ }
+
+ register_blob_handler("userevent", EVENT_FLAG_USER, channel_userevent);
+ register_blob_handler("hangup_request", EVENT_FLAG_CALL, channel_hangup_request);
+ register_blob_handler("Newexten", EVENT_FLAG_CALL, channel_newexten);
+ register_blob_handler("VarSet", EVENT_FLAG_DIALPLAN, channel_manager_generic);
+ register_blob_handler("NewCallerid", EVENT_FLAG_CALL, channel_manager_generic);
+ register_blob_handler("Newchannel", EVENT_FLAG_CALL, channel_manager_generic);
+ register_blob_handler("Newstate", EVENT_FLAG_CALL, channel_manager_generic);
+ register_blob_handler("Hangup", EVENT_FLAG_CALL, channel_manager_generic);
+
return 0;
}
More information about the asterisk-commits
mailing list