diff options
author | Kinsey Moore <kmoore@digium.com> | 2013-06-10 13:07:11 +0000 |
---|---|---|
committer | Kinsey Moore <kmoore@digium.com> | 2013-06-10 13:07:11 +0000 |
commit | a5bbc790e7ee1417bc03f5c529a73f2604a58cdb (patch) | |
tree | 4ae804770c499e8068bc04c4b896d9a8c0447715 /res/stasis_http/resource_bridges.c | |
parent | 0cec7dcdcd4ce053bfb27849e5bd90b181151182 (diff) |
Stasis-HTTP: Flesh out bridge-related capabilities
This adds support for Stasis applications to receive bridge-related
messages when the application shows interest in a given bridge.
To supplement this work and test it, this also adds support for the
following bridge-related Stasis-HTTP functionality:
* GET stasis/bridges
* GET stasis/bridges/{bridgeId}
* POST stasis/bridges
* DELETE stasis/bridges/{bridgeId}
* POST stasis/bridges/{bridgeId}/addChannel
* POST stasis/bridges/{bridgeId}/removeChannel
Review: https://reviewboard.asterisk.org/r/2572/
(closes issue ASTERISK-21711)
(closes issue ASTERISK-21621)
(closes issue ASTERISK-21622)
(closes issue ASTERISK-21623)
(closes issue ASTERISK-21624)
(closes issue ASTERISK-21625)
(closes issue ASTERISK-21626)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@391199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/stasis_http/resource_bridges.c')
-rw-r--r-- | res/stasis_http/resource_bridges.c | 191 |
1 files changed, 185 insertions, 6 deletions
diff --git a/res/stasis_http/resource_bridges.c b/res/stasis_http/resource_bridges.c index ca48ee725..6dad91116 100644 --- a/res/stasis_http/resource_bridges.c +++ b/res/stasis_http/resource_bridges.c @@ -32,32 +32,211 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "resource_bridges.h" +#include "asterisk/stasis.h" +#include "asterisk/stasis_bridging.h" +#include "asterisk/stasis_app.h" +#include "asterisk/channel.h" +#include "asterisk/bridging.h" + +/*! + * \brief Finds a bridge, filling the response with an error, if appropriate. + * + * \param[out] response Response to fill with an error if control is not found. + * \param bridge_id ID of the bridge to lookup. + * + * \return Bridget. + * \return \c NULL if bridge does not exist. + */ +static struct ast_bridge *find_bridge( + struct stasis_http_response *response, + const char *bridge_id) +{ + RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup); + + ast_assert(response != NULL); + + bridge = stasis_app_bridge_find_by_id(bridge_id); + if (bridge == NULL) { + RAII_VAR(struct ast_bridge_snapshot *, snapshot, + ast_bridge_snapshot_get_latest(bridge_id), ao2_cleanup); + if (!snapshot) { + stasis_http_response_error(response, 404, "Not found", + "Bridge not found"); + return NULL; + } + + stasis_http_response_error(response, 409, "Conflict", + "Bridge not in Stasis application"); + return NULL; + } + + ao2_ref(bridge, +1); + return bridge; +} + +/*! + * \brief Finds the control object for a channel, filling the response with an + * error, if appropriate. + * \param[out] response Response to fill with an error if control is not found. + * \param channel_id ID of the channel to lookup. + * \return Channel control object. + * \return \c NULL if control object does not exist. + */ +static struct stasis_app_control *find_channel_control( + struct stasis_http_response *response, + const char *channel_id) +{ + RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup); + + ast_assert(response != NULL); + + control = stasis_app_control_find_by_channel_id(channel_id); + if (control == NULL) { + stasis_http_response_error(response, 422, "Unprocessable Entity", + "Channel not in Stasis application"); + return NULL; + } + + ao2_ref(control, +1); + return control; +} void stasis_http_add_channel_to_bridge(struct ast_variable *headers, struct ast_add_channel_to_bridge_args *args, struct stasis_http_response *response) { - ast_log(LOG_ERROR, "TODO: stasis_http_add_channel_to_bridge\n"); + RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup); + RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup); + if (!bridge) { + return; + } + + control = find_channel_control(response, args->channel); + if (!control) { + return; + } + + stasis_app_control_add_channel_to_bridge(control, bridge); + stasis_http_response_no_content(response); } + void stasis_http_remove_channel_from_bridge(struct ast_variable *headers, struct ast_remove_channel_from_bridge_args *args, struct stasis_http_response *response) { - ast_log(LOG_ERROR, "TODO: stasis_http_remove_channel_from_bridge\n"); + RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup); + RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup); + if (!bridge) { + return; + } + + control = find_channel_control(response, args->channel); + if (!control) { + return; + } + + /* BUGBUG this should make sure the bridge requested for removal is actually + * the bridge the channel is in. This will be possible once the bridge uniqueid + * is added to the channel snapshot. A 409 response should be issued if the bridge + * uniqueids don't match */ + if (stasis_app_control_remove_channel_from_bridge(control, bridge)) { + stasis_http_response_error(response, 500, "Internal Error", + "Could not remove channel from bridge"); + return; + } + + stasis_http_response_no_content(response); } + void stasis_http_record_bridge(struct ast_variable *headers, struct ast_record_bridge_args *args, struct stasis_http_response *response) { ast_log(LOG_ERROR, "TODO: stasis_http_record_bridge\n"); } + void stasis_http_get_bridge(struct ast_variable *headers, struct ast_get_bridge_args *args, struct stasis_http_response *response) { - ast_log(LOG_ERROR, "TODO: stasis_http_get_bridge\n"); + RAII_VAR(struct ast_bridge_snapshot *, snapshot, ast_bridge_snapshot_get_latest(args->bridge_id), ao2_cleanup); + if (!snapshot) { + stasis_http_response_error( + response, 404, "Not Found", + "Bridge not found"); + return; + } + + stasis_http_response_ok(response, + ast_bridge_snapshot_to_json(snapshot)); } + void stasis_http_delete_bridge(struct ast_variable *headers, struct ast_delete_bridge_args *args, struct stasis_http_response *response) { - ast_log(LOG_ERROR, "TODO: stasis_http_delete_bridge\n"); + RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup); + if (!bridge) { + return; + } + + stasis_app_bridge_destroy(args->bridge_id); + stasis_http_response_no_content(response); } + void stasis_http_get_bridges(struct ast_variable *headers, struct ast_get_bridges_args *args, struct stasis_http_response *response) { - ast_log(LOG_ERROR, "TODO: stasis_http_get_bridges\n"); + RAII_VAR(struct stasis_caching_topic *, caching_topic, NULL, ao2_cleanup); + RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup); + RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); + struct ao2_iterator i; + void *obj; + + caching_topic = ast_bridge_topic_all_cached(); + if (!caching_topic) { + stasis_http_response_error( + response, 500, "Internal Server Error", + "Message bus not initialized"); + return; + } + ao2_ref(caching_topic, +1); + + snapshots = stasis_cache_dump(caching_topic, ast_bridge_snapshot_type()); + if (!snapshots) { + stasis_http_response_alloc_failed(response); + return; + } + + json = ast_json_array_create(); + if (!json) { + stasis_http_response_alloc_failed(response); + return; + } + + i = ao2_iterator_init(snapshots, 0); + while ((obj = ao2_iterator_next(&i))) { + RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup); + struct ast_bridge_snapshot *snapshot = stasis_message_data(msg); + if (ast_json_array_append(json, ast_bridge_snapshot_to_json(snapshot))) { + stasis_http_response_alloc_failed(response); + return; + } + } + ao2_iterator_destroy(&i); + + stasis_http_response_ok(response, ast_json_ref(json)); } + void stasis_http_new_bridge(struct ast_variable *headers, struct ast_new_bridge_args *args, struct stasis_http_response *response) { - ast_log(LOG_ERROR, "TODO: stasis_http_new_bridge\n"); + RAII_VAR(struct ast_bridge *, bridge, stasis_app_bridge_create(args->type), ao2_cleanup); + RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup); + + if (!bridge) { + stasis_http_response_error( + response, 500, "Internal Error", + "Unable to create bridge"); + return; + } + + snapshot = ast_bridge_snapshot_create(bridge); + if (!snapshot) { + stasis_http_response_error( + response, 500, "Internal Error", + "Unable to create snapshot for new bridge"); + return; + } + + stasis_http_response_ok(response, + ast_bridge_snapshot_to_json(snapshot)); } |