summaryrefslogtreecommitdiff
path: root/res/stasis_http
diff options
context:
space:
mode:
authorKinsey Moore <kmoore@digium.com>2013-06-10 13:07:11 +0000
committerKinsey Moore <kmoore@digium.com>2013-06-10 13:07:11 +0000
commita5bbc790e7ee1417bc03f5c529a73f2604a58cdb (patch)
tree4ae804770c499e8068bc04c4b896d9a8c0447715 /res/stasis_http
parent0cec7dcdcd4ce053bfb27849e5bd90b181151182 (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')
-rw-r--r--res/stasis_http/resource_bridges.c191
-rw-r--r--res/stasis_http/resource_bridges.h2
2 files changed, 186 insertions, 7 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));
}
diff --git a/res/stasis_http/resource_bridges.h b/res/stasis_http/resource_bridges.h
index db6db205b..ec1992f26 100644
--- a/res/stasis_http/resource_bridges.h
+++ b/res/stasis_http/resource_bridges.h
@@ -84,7 +84,7 @@ struct ast_delete_bridge_args {
const char *bridge_id;
};
/*!
- * \brief Shut down a bridge bridge.
+ * \brief Shut down a bridge.
*
* If any channels are in this bridge, they will be removed and resume whatever they were doing beforehand.
*