diff --git a/apps/app_userevent.c b/apps/app_userevent.c index 0c44cf25e226e872fd41878734492dd6cc6e5556..ded039e3fe5254817ca8062665b7c398b1acb3d8 100644 --- a/apps/app_userevent.c +++ b/apps/app_userevent.c @@ -93,7 +93,6 @@ static int userevent_exec(struct ast_channel *chan, const char *data) } blob = ast_json_pack("{s: s, s: s, s: s}", - "type", "userevent", "eventname", args.eventname, "body", ast_str_buffer(body)); if (!blob) { @@ -101,7 +100,8 @@ static int userevent_exec(struct ast_channel *chan, const char *data) return -1; } - msg = ast_channel_blob_create(chan, blob); + msg = ast_channel_blob_create( + chan, ast_channel_user_event_type(), blob); if (!msg) { return -1; } diff --git a/include/asterisk/stasis.h b/include/asterisk/stasis.h index 48d51e369e5bdcab32a4d5b83ac18c10ee4381c0..da816874643b4029040597ccd6ba6e4e670f5ab4 100644 --- a/include/asterisk/stasis.h +++ b/include/asterisk/stasis.h @@ -542,6 +542,43 @@ struct ao2_container *stasis_cache_dump(struct stasis_caching_topic *caching_top /*! @{ */ +/*! + * \brief Boiler-plate removing macro for defining message types. + * + * \param name Name of message type. + * \since 12 + */ +#define STASIS_MESSAGE_TYPE_DEFN(name) \ + static struct stasis_message_type *__ ## name; \ + struct stasis_message_type *name(void) { \ + ast_assert(__ ## name != NULL); \ + return __ ## name; \ + } + +/*! + * \brief Boiler-plate removing macro for initializing message types. + * + * \param name Name of message type. + * \return 0 if initialization is successful. + * \return Non-zero on failure. + * \since 12 + */ +#define STASIS_MESSAGE_TYPE_INIT(name) \ + ({ \ + __ ## name = stasis_message_type_create(#name); \ + __ ## name ? 0 : -1; \ + }) + +#define STASIS_MESSAGE_TYPE_CLEANUP(name) \ + ({ \ + ao2_cleanup(__ ## name); \ + __ ## name = NULL; \ + }) + +/*! @} */ + +/*! @{ */ + /*! * \brief Initialize the Stasis subsystem * \return 0 on success. diff --git a/include/asterisk/stasis_channels.h b/include/asterisk/stasis_channels.h index 53dcc24e82f878ace4a0b5dd77bd20e8c4019c10..af571eda185086608cb5c3db85d5485e1db1331f 100644 --- a/include/asterisk/stasis_channels.h +++ b/include/asterisk/stasis_channels.h @@ -70,8 +70,7 @@ struct ast_channel_snapshot { * \since 12 * \brief Blob of data associated with a channel. * - * The \c blob is actually a JSON object of structured data. It has a "type" field - * which contains the type string describing this blob. + * This blob is actually shared amongst several \ref stasis_message_type's. */ struct ast_channel_blob { /*! Channel blob is associated with (or NULL for global/all channels) */ @@ -110,14 +109,6 @@ struct stasis_caching_topic *ast_channel_topic_all_cached(void); */ struct stasis_message_type *ast_channel_snapshot_type(void); -/*! - * \since 12 - * \brief Message type for \ref ast_channel_blob messages. - * - * \retval Message type for \ref ast_channel_blob messages. - */ -struct stasis_message_type *ast_channel_blob_type(void); - /*! * \since 12 * \brief Generate a snapshot of the channel state. This is an ao2 object, so @@ -128,44 +119,35 @@ struct stasis_message_type *ast_channel_blob_type(void); * \retval pointer on success (must be ast_freed) * \retval NULL on error */ -struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan); +struct ast_channel_snapshot *ast_channel_snapshot_create( + struct ast_channel *chan); /*! * \since 12 * \brief Creates a \ref ast_channel_blob message. * - * 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. + * The given \a blob should be treated as immutable and not modified after it is + * put into the message. + * + * \param chan Channel blob is associated with, or \c NULL for global/all channels. + * \param type Message type for this blob. + * \param blob JSON object representing the data, or \c NULL for no data. If + * \c NULL, ast_json_null() is put into the object. * - * \param chan Channel blob is associated with, or NULL for global/all channels. - * \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(struct ast_channel *chan, - struct ast_json *blob); - -/*! - * \since 12 - * \brief Extracts the type field from a \ref ast_channel_blob. - * Returned \c char* is still owned by \a obj - * \param obj Channel blob object. - * \return Type field value from the blob. - * \return \c NULL on error. - */ -const char *ast_channel_blob_json_type(struct ast_channel_blob *obj); + struct stasis_message_type *type, struct ast_json *blob); /*! * \since 12 - * \brief Create a \ref ast_multi_channel_blob suitable for a \ref stasis_message + * \brief Create a \ref ast_multi_channel_blob suitable for a \ref stasis_message. * - * \note Similar to a \ref ast_channel_blob, the \ref ast_multi_channel_blob requires - * a \a blob JSON object containing a \c "type" field describing the blob. It - * should also be treated as immutable and not modified after it is put into the - * message. + * The given \a blob should be treated as immutable and not modified after it is + * put into the message. * - * \param blob The JSON blob that defines the type of this \ref ast_multi_channel_blob + * \param blob The JSON blob that defines the data of this \ref ast_multi_channel_blob * * \return \ref ast_multi_channel_blob object * \return \c NULL on error @@ -189,8 +171,7 @@ struct ast_multi_channel_blob *ast_multi_channel_blob_create(struct ast_json *bl * \retval NULL on error or not found for the role specified */ struct ast_channel_snapshot *ast_multi_channel_blob_get_channel( - struct ast_multi_channel_blob *obj, - const char *role); + struct ast_multi_channel_blob *obj, const char *role); /*! * \since 12 @@ -212,8 +193,7 @@ struct ast_channel_snapshot *ast_multi_channel_blob_get_channel( * \retval NULL on error or not found for the role specified */ struct ao2_container *ast_multi_channel_blob_get_channels( - struct ast_multi_channel_blob *obj, - const char *role); + struct ast_multi_channel_blob *obj, const char *role); /*! * \since 12 @@ -226,17 +206,6 @@ struct ao2_container *ast_multi_channel_blob_get_channels( */ struct ast_json *ast_multi_channel_blob_get_json(struct ast_multi_channel_blob *obj); -/*! - * \since 12 - * \brief Extracts the type field from a \ref ast_multi_channel_blob. - * Returned \c char* is still owned by \a obj - * - * \param obj Channel blob object. - * \return Type field value from the blob. - * \return \c NULL on error. - */ -const char *ast_multi_channel_blob_get_type(struct ast_multi_channel_blob *obj); - /*! * \since 12 * \brief Add a \ref ast_channel_snapshot to a \ref ast_multi_channel_blob object @@ -250,8 +219,7 @@ const char *ast_multi_channel_blob_get_type(struct ast_multi_channel_blob *obj); * \ref ast_multi_channel_blob object */ void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, - const char *role, - struct ast_channel_snapshot *snapshot); + const char *role, struct ast_channel_snapshot *snapshot); /*! * \since 12 @@ -272,6 +240,46 @@ void ast_channel_publish_varset(struct ast_channel *chan, */ struct stasis_message_type *ast_channel_dial_type(void); +/*! + * \since 12 + * \brief Message type for when a variable is set on a channel. + * + * \retval A stasis message type + */ +struct stasis_message_type *ast_channel_varset_type(void); + +/*! + * \since 12 + * \brief Message type for when a custom user event is sent on a channel. + * + * \retval A stasis message type + */ +struct stasis_message_type *ast_channel_user_event_type(void); + +/*! + * \since 12 + * \brief Message type for when a hangup is requested on a channel. + * + * \retval A stasis message type + */ +struct stasis_message_type *ast_channel_hangup_request_type(void); + +/*! + * \since 12 + * \brief Message type for when DTMF begins on a channel. + * + * \retval A stasis message type + */ +struct stasis_message_type *ast_channel_dtmf_begin_type(void); + +/*! + * \since 12 + * \brief Message type for when DTMF ends on a channel. + * + * \retval A stasis message type + */ +struct stasis_message_type *ast_channel_dtmf_end_type(void); + /*! * \since 12 * \brief Publish in the \ref ast_channel_topic or \ref ast_channel_topic_all diff --git a/main/channel.c b/main/channel.c index 9ed7e5f25999ae240a45c02603d6ffd9907a3b6a..d63aeb2ba73a3d65b23ae7e85f52a1f5b8b7fcd7 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1368,11 +1368,12 @@ int ast_queue_frame_head(struct ast_channel *chan, struct ast_frame *fin) } /*! \internal \brief Publish a channel blob message */ -static void publish_channel_blob(struct ast_channel *chan, struct ast_json *blob) +static void publish_channel_blob(struct ast_channel *chan, + struct stasis_message_type *type, struct ast_json *blob) { RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); if (blob) { - message = ast_channel_blob_create(chan, blob); + message = ast_channel_blob_create(chan, type, blob); } if (message) { stasis_publish(ast_channel_topic(chan), message); @@ -1382,7 +1383,6 @@ static void publish_channel_blob(struct ast_channel *chan, struct ast_json *blob /*! \brief Queue a hangup frame for channel */ int ast_queue_hangup(struct ast_channel *chan) { - RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP }; int res; @@ -1390,8 +1390,7 @@ int ast_queue_hangup(struct ast_channel *chan) /* Yeah, let's not change a lock-critical value without locking */ ast_channel_lock(chan); ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV); - blob = ast_json_pack("{s: s}", "type", "hangup_request"); - publish_channel_blob(chan, blob); + publish_channel_blob(chan, ast_channel_hangup_request_type(), NULL); res = ast_queue_frame(chan, &f); ast_channel_unlock(chan); @@ -1416,10 +1415,9 @@ int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause) if (cause < 0) { f.data.uint32 = ast_channel_hangupcause(chan); } - blob = ast_json_pack("{s: s, s: i}", - "type", "hangup_request", + blob = ast_json_pack("{s: i}", "cause", cause); - publish_channel_blob(chan, blob); + publish_channel_blob(chan, ast_channel_hangup_request_type(), blob); res = ast_queue_frame(chan, &f); ast_channel_unlock(chan); @@ -2727,11 +2725,10 @@ int ast_softhangup(struct ast_channel *chan, int cause) ast_channel_lock(chan); res = ast_softhangup_nolock(chan, cause); - blob = ast_json_pack("{s: s, s: i, s: b}", - "type", "hangup_request", + blob = ast_json_pack("{s: i, s: b}", "cause", cause, "soft", 1); - publish_channel_blob(chan, blob); + publish_channel_blob(chan, ast_channel_hangup_request_type(), blob); ast_channel_unlock(chan); return res; @@ -3737,15 +3734,14 @@ static void send_dtmf_begin_event(struct ast_channel *chan, RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); char digit_str[] = { digit, '\0' }; - blob = ast_json_pack("{ s: s, s: s, s: s }", - "type", "dtmf_begin", + blob = ast_json_pack("{ s: s, s: s }", "digit", digit_str, "direction", dtmf_direction_to_string(direction)); if (!blob) { return; } - publish_channel_blob(chan, blob); + publish_channel_blob(chan, ast_channel_dtmf_begin_type(), blob); } static void send_dtmf_end_event(struct ast_channel *chan, @@ -3754,8 +3750,7 @@ static void send_dtmf_end_event(struct ast_channel *chan, RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); char digit_str[] = { digit, '\0' }; - blob = ast_json_pack("{ s: s, s: s, s: s, s: i }", - "type", "dtmf_end", + blob = ast_json_pack("{ s: s, s: s, s: i }", "digit", digit_str, "direction", dtmf_direction_to_string(direction), "duration_ms", duration_ms); @@ -3763,7 +3758,7 @@ static void send_dtmf_end_event(struct ast_channel *chan, return; } - publish_channel_blob(chan, blob); + publish_channel_blob(chan, ast_channel_dtmf_end_type(), blob); } static void ast_read_generator_actions(struct ast_channel *chan, struct ast_frame *f) diff --git a/main/manager_channels.c b/main/manager_channels.c index 004467e3bc005e047b65a6109787301b1618adef..804bca663c7f08b05b14e42c1da33338e326ebc9 100644 --- a/main/manager_channels.c +++ b/main/manager_channels.c @@ -544,8 +544,10 @@ static void channel_snapshot_update(void *data, struct stasis_subscription *sub, } } -static void channel_varset(struct ast_channel_blob *obj) +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")); @@ -585,8 +587,10 @@ static void channel_varset(struct ast_channel_blob *obj) variable, value); } -static void channel_userevent(struct ast_channel_blob *obj) +static void channel_user_event_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 *eventname; const char *body; @@ -620,8 +624,11 @@ static void channel_userevent(struct ast_channel_blob *obj) ast_str_buffer(channel_event_string), eventname, body); } -static void channel_hangup_request(struct ast_channel_blob *obj) +static void channel_hangup_request_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 *, extra, NULL, ast_free); RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free); struct ast_json *cause; @@ -657,8 +664,10 @@ static void channel_hangup_request(struct ast_channel_blob *obj) ast_str_buffer(extra)); } -static void channel_dtmf_begin(struct ast_channel_blob *obj) +static void channel_dtmf_begin_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 *digit = ast_json_string_get(ast_json_object_get(obj->blob, "digit")); @@ -696,8 +705,10 @@ static void channel_dtmf_begin(struct ast_channel_blob *obj) digit, direction); } -static void channel_dtmf_end(struct ast_channel_blob *obj) +static void channel_dtmf_end_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 *digit = ast_json_string_get(ast_json_object_get(obj->blob, "digit")); @@ -741,34 +752,11 @@ static void channel_dtmf_end(struct ast_channel_blob *obj) digit, duration_ms, direction); } -/*! - * \brief Callback processing messages on the channel topic. - */ -static void channel_blob_cb(void *data, struct stasis_subscription *sub, - struct stasis_topic *topic, - struct stasis_message *message) -{ - struct ast_channel_blob *obj = stasis_message_data(message); - - if (strcmp("varset", ast_channel_blob_json_type(obj)) == 0) { - channel_varset(obj); - } else if (strcmp("userevent", ast_channel_blob_json_type(obj)) == 0) { - channel_userevent(obj); - } else if (strcmp("hangup_request", ast_channel_blob_json_type(obj)) == 0) { - channel_hangup_request(obj); - } else if (strcmp("dtmf_begin", ast_channel_blob_json_type(obj)) == 0) { - channel_dtmf_begin(obj); - } else if (strcmp("dtmf_end", ast_channel_blob_json_type(obj)) == 0) { - channel_dtmf_end(obj); - } -} - /*! * \brief Callback processing messages for channel dialing */ static void channel_dial_cb(void *data, struct stasis_subscription *sub, - struct stasis_topic *topic, - struct stasis_message *message) + struct stasis_topic *topic, struct stasis_message *message) { struct ast_multi_channel_blob *obj = stasis_message_data(message); const char *dialstatus; @@ -778,11 +766,6 @@ static void channel_dial_cb(void *data, struct stasis_subscription *sub, RAII_VAR(struct ast_str *, caller_event_string, NULL, ast_free); RAII_VAR(struct ast_str *, peer_event_string, NULL, ast_free); - if (strcmp("dial", ast_multi_channel_blob_get_type(obj))) { - ast_assert(0); - return; - } - caller = ast_multi_channel_blob_get_channel(obj, "caller"); peer = ast_multi_channel_blob_get_channel(obj, "peer"); @@ -852,8 +835,28 @@ int manager_channels_init(void) NULL); ret |= stasis_message_router_add(channel_state_router, - ast_channel_blob_type(), - channel_blob_cb, + ast_channel_varset_type(), + channel_varset_cb, + NULL); + + ret |= stasis_message_router_add(channel_state_router, + ast_channel_user_event_type(), + channel_user_event_cb, + NULL); + + ret |= stasis_message_router_add(channel_state_router, + ast_channel_dtmf_begin_type(), + channel_dtmf_begin_cb, + NULL); + + ret |= stasis_message_router_add(channel_state_router, + ast_channel_dtmf_end_type(), + channel_dtmf_end_cb, + NULL); + + ret |= stasis_message_router_add(channel_state_router, + ast_channel_hangup_request_type(), + channel_hangup_request_cb, NULL); ret |= stasis_message_router_add(channel_state_router, diff --git a/main/stasis_channels.c b/main/stasis_channels.c index b40f1357257902b286d11b511220ff2af4985615..c032ec9567e0e8e0e588afef9ae24bdf18bfbe04 100644 --- a/main/stasis_channels.c +++ b/main/stasis_channels.c @@ -38,14 +38,17 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define NUM_MULTI_CHANNEL_BLOB_BUCKETS 7 -/*! \brief Message type for channel snapshot messages */ -static struct stasis_message_type *channel_snapshot_type; - -/*! \brief Message type for channel blob messages */ -static struct stasis_message_type *channel_blob_type; - -/*! \brief Message type for channel dial messages */ -static struct stasis_message_type *channel_dial_type; +/*! + * @{ \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); +/*! @} */ /*! \brief Topic for all channels */ struct stasis_topic *channel_topic_all; @@ -53,21 +56,6 @@ struct stasis_topic *channel_topic_all; /*! \brief Caching topic for all channels */ struct stasis_caching_topic *channel_topic_all_cached; -struct stasis_message_type *ast_channel_dial_type(void) -{ - return channel_dial_type; -} - -struct stasis_message_type *ast_channel_blob_type(void) -{ - return channel_blob_type; -} - -struct stasis_message_type *ast_channel_snapshot_type(void) -{ - return channel_snapshot_type; -} - struct stasis_topic *ast_channel_topic_all(void) { return channel_topic_all; @@ -221,18 +209,13 @@ void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *pe } struct stasis_message *ast_channel_blob_create(struct ast_channel *chan, - struct ast_json *blob) + struct stasis_message_type *type, 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; - ast_assert(blob != NULL); - - type = ast_json_object_get(blob, "type"); - if (type == NULL) { - ast_log(LOG_ERROR, "Invalid ast_channel_blob; missing type field\n"); - return NULL; + if (blob == NULL) { + blob = ast_json_null(); } obj = ao2_alloc(sizeof(*obj), channel_blob_dtor); @@ -249,7 +232,7 @@ struct stasis_message *ast_channel_blob_create(struct ast_channel *chan, obj->blob = ast_json_ref(blob); - msg = stasis_message_create(ast_channel_blob_type(), obj); + msg = stasis_message_create(type, obj); if (!msg) { return NULL; } @@ -258,15 +241,6 @@ struct stasis_message *ast_channel_blob_create(struct ast_channel *chan, return msg; } -const char *ast_channel_blob_json_type(struct ast_channel_blob *obj) -{ - if (obj == NULL) { - return NULL; - } - - return ast_json_string_get(ast_json_object_get(obj->blob, "type")); -} - /*! \brief A channel snapshot wrapper object used in \ref ast_multi_channel_blob objects */ struct channel_role_snapshot { struct ast_channel_snapshot *snapshot; /*!< A channel snapshot */ @@ -319,7 +293,6 @@ struct ast_multi_channel_blob *ast_multi_channel_blob_create(struct ast_json *bl RAII_VAR(struct ast_multi_channel_blob *, obj, ao2_alloc(sizeof(*obj), multi_channel_blob_dtor), ao2_cleanup); - struct ast_json *type; ast_assert(blob != NULL); @@ -327,12 +300,6 @@ struct ast_multi_channel_blob *ast_multi_channel_blob_create(struct ast_json *bl return NULL; } - type = ast_json_object_get(blob, "type"); - if (type == NULL) { - ast_log(LOG_ERROR, "Invalid ast_multi_channel_blob; missing type field\n"); - return NULL; - } - obj->channel_snapshots = ao2_container_alloc(NUM_MULTI_CHANNEL_BLOB_BUCKETS, channel_role_hash_cb, channel_role_single_cmp_cb); if (!obj->channel_snapshots) { @@ -423,15 +390,6 @@ struct ast_json *ast_multi_channel_blob_get_json(struct ast_multi_channel_blob * return obj->blob; } -const char *ast_multi_channel_blob_get_type(struct ast_multi_channel_blob *obj) -{ - if (!obj) { - return NULL; - } - - return ast_json_string_get(ast_json_object_get(obj->blob, "type")); -} - void ast_channel_publish_varset(struct ast_channel *chan, const char *name, const char *value) { RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); @@ -449,7 +407,8 @@ void ast_channel_publish_varset(struct ast_channel *chan, const char *name, cons return; } - msg = ast_channel_blob_create(chan, ast_json_ref(blob)); + msg = ast_channel_blob_create(chan, ast_channel_varset_type(), + ast_json_ref(blob)); if (!msg) { return; @@ -491,12 +450,13 @@ struct ast_json *ast_channel_snapshot_to_json(const struct ast_channel_snapshot void ast_stasis_channels_shutdown(void) { - ao2_cleanup(channel_snapshot_type); - channel_snapshot_type = NULL; - ao2_cleanup(channel_blob_type); - channel_blob_type = NULL; - ao2_cleanup(channel_dial_type); - channel_dial_type = NULL; + STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_snapshot_type); + STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_dial_type); + STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_varset_type); + STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_user_event_type); + STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_hangup_request_type); + STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_dtmf_begin_type); + STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_dtmf_end_type); ao2_cleanup(channel_topic_all); channel_topic_all = NULL; channel_topic_all_cached = stasis_caching_unsubscribe(channel_topic_all_cached); @@ -504,9 +464,14 @@ void ast_stasis_channels_shutdown(void) void ast_stasis_channels_init(void) { - channel_snapshot_type = stasis_message_type_create("ast_channel_snapshot"); - channel_blob_type = stasis_message_type_create("ast_channel_blob"); - channel_dial_type = stasis_message_type_create("ast_channel_dial"); + STASIS_MESSAGE_TYPE_INIT(ast_channel_snapshot_type); + STASIS_MESSAGE_TYPE_INIT(ast_channel_dial_type); + STASIS_MESSAGE_TYPE_INIT(ast_channel_varset_type); + STASIS_MESSAGE_TYPE_INIT(ast_channel_user_event_type); + STASIS_MESSAGE_TYPE_INIT(ast_channel_hangup_request_type); + STASIS_MESSAGE_TYPE_INIT(ast_channel_dtmf_begin_type); + STASIS_MESSAGE_TYPE_INIT(ast_channel_dtmf_end_type); + 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); } diff --git a/res/res_stasis.c b/res/res_stasis.c index ff4fa8c56ff3c4abcc2c3f47db81721714dae00a..3d003e40aca08b62bd433d4bc663bce8f949ac0d 100644 --- a/res/res_stasis.c +++ b/res/res_stasis.c @@ -470,19 +470,17 @@ static void dtmf_handler(struct app *app, struct ast_channel_blob *obj) app_send(app, msg); } -static void blob_handler(struct app *app, struct ast_channel_blob *blob) -{ - /* To simplify events, we'll only generate on DTMF end */ - if (strcmp(ast_channel_blob_json_type(blob), "dtmf_end") == 0) { - dtmf_handler(app, blob); - } -} - static void sub_handler(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message) { struct app *app = data; + + if (stasis_subscription_final_message(sub, message)) { + ao2_cleanup(data); + return; + } + if (ast_channel_snapshot_type() == stasis_message_type(message)) { RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref); struct ast_channel_snapshot *snapshot = @@ -493,13 +491,12 @@ static void sub_handler(void *data, struct stasis_subscription *sub, return; } app_send(app, msg); - } else if (ast_channel_blob_type() == stasis_message_type(message)) { + } else if (ast_channel_dtmf_end_type() == stasis_message_type(message)) { + /* To simplify events, we'll only generate on DTMF end */ struct ast_channel_blob *blob = stasis_message_data(message); - blob_handler(app, blob); - } - if (stasis_subscription_final_message(sub, message)) { - ao2_cleanup(data); + dtmf_handler(app, blob); } + } /*! diff --git a/tests/test_stasis_channels.c b/tests/test_stasis_channels.c index e3527baf3369923b491442183ab2b14a5fae8f0b..512df435145a1ff3b2475ff369533590f343ba4f 100644 --- a/tests/test_stasis_channels.c +++ b/tests/test_stasis_channels.c @@ -54,6 +54,7 @@ static void safe_channel_release(struct ast_channel *chan) AST_TEST_DEFINE(channel_blob_create) { struct ast_channel_blob *blob; + RAII_VAR(struct stasis_message_type *, type, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release); RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); @@ -70,36 +71,71 @@ AST_TEST_DEFINE(channel_blob_create) break; } + type = stasis_message_type_create("test-type"); chan = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, 0, "TEST/Alice"); json = ast_json_pack("{s: s}", - "type", "test"); - bad_json = ast_json_pack("{s: s}", - "bad_key", "test"); + "foo", "bar"); /* Off nominal creation */ - ast_test_validate(test, NULL == ast_channel_blob_create(NULL, bad_json)); - ast_test_validate(test, NULL == ast_channel_blob_create(chan, bad_json)); + ast_test_validate(test, NULL == ast_channel_blob_create(chan, NULL, json)); /* Test for single channel */ - msg = ast_channel_blob_create(chan, json); + msg = ast_channel_blob_create(chan, type, json); ast_test_validate(test, NULL != msg); blob = stasis_message_data(msg); ast_test_validate(test, NULL != blob); ast_test_validate(test, NULL != blob->snapshot); ast_test_validate(test, NULL != blob->blob); - ast_test_validate(test, 0 == strcmp(ast_channel_blob_json_type(blob), "test")); + ast_test_validate(test, type == stasis_message_type(msg)); ast_test_validate(test, 1 == ao2_ref(msg, 0)); ao2_cleanup(msg); /* Test for global channels */ - msg = ast_channel_blob_create(NULL, json); + msg = ast_channel_blob_create(NULL, type, json); ast_test_validate(test, NULL != msg); blob = stasis_message_data(msg); ast_test_validate(test, NULL != blob); ast_test_validate(test, NULL == blob->snapshot); ast_test_validate(test, NULL != blob->blob); - ast_test_validate(test, 0 == strcmp(ast_channel_blob_json_type(blob), "test")); + ast_test_validate(test, type == stasis_message_type(msg)); + + return AST_TEST_PASS; +} + +AST_TEST_DEFINE(null_blob) +{ + struct ast_channel_blob *blob; + RAII_VAR(struct stasis_message_type *, type, NULL, ao2_cleanup); + RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); + RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release); + RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); + RAII_VAR(struct ast_json *, bad_json, NULL, ast_json_unref); + + switch (cmd) { + case TEST_INIT: + info->name = __func__; + info->category = test_category; + info->summary = "Test creation of ast_channel_blob objects"; + info->description = "Test creation of ast_channel_blob objects"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + type = stasis_message_type_create("test-type"); + chan = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, 0, "TEST/Alice"); + json = ast_json_pack("{s: s}", + "foo", "bar"); + + /* Test for single channel */ + msg = ast_channel_blob_create(chan, type, NULL); + ast_test_validate(test, NULL != msg); + blob = stasis_message_data(msg); + ast_test_validate(test, NULL != blob); + ast_test_validate(test, NULL != blob->snapshot); + ast_test_validate(test, ast_json_null() == blob->blob); + ast_test_validate(test, type == stasis_message_type(msg)); return AST_TEST_PASS; } @@ -122,17 +158,11 @@ AST_TEST_DEFINE(multi_channel_blob_create) } json = ast_json_pack("{s: s}", - "type", "test"); - bad_json = ast_json_pack("{s: s}", - "bad_key", "test"); - - /* Off nominal creation */ - ast_test_validate(test, NULL == ast_multi_channel_blob_create(bad_json)); + "foo", "bar"); /* Test for single channel */ blob = ast_multi_channel_blob_create(json); ast_test_validate(test, NULL != blob); - ast_test_validate(test, 0 == strcmp(ast_multi_channel_blob_get_type(blob), "test")); ast_test_validate(test, NULL != ast_multi_channel_blob_get_json(blob)); return AST_TEST_PASS; @@ -266,6 +296,7 @@ AST_TEST_DEFINE(channel_snapshot_json) static int unload_module(void) { AST_TEST_UNREGISTER(channel_blob_create); + AST_TEST_UNREGISTER(null_blob); AST_TEST_UNREGISTER(multi_channel_blob_create); AST_TEST_UNREGISTER(multi_channel_blob_snapshots); AST_TEST_UNREGISTER(channel_snapshot_json); @@ -276,6 +307,7 @@ static int unload_module(void) static int load_module(void) { AST_TEST_REGISTER(channel_blob_create); + AST_TEST_REGISTER(null_blob); AST_TEST_REGISTER(multi_channel_blob_create); AST_TEST_REGISTER(multi_channel_blob_snapshots); AST_TEST_REGISTER(channel_snapshot_json);