summaryrefslogtreecommitdiff
path: root/res/stasis_http
diff options
context:
space:
mode:
authorDavid M. Lee <dlee@digium.com>2013-07-03 17:58:45 +0000
committerDavid M. Lee <dlee@digium.com>2013-07-03 17:58:45 +0000
commita75fd32212c35b41143442bd757387fad636177a (patch)
tree461033acf36f4596d8fc9800a1195e12207b3ea2 /res/stasis_http
parentc4adaf91067559dd5aa90577e181693abade0602 (diff)
ARI - channel recording support
This patch is the first step in adding recording support to the Asterisk REST Interface. Recordings are stored in /var/spool/recording. Since recordings may be destructive (overwriting existing files), the API rejects attempts to escape the recording directory (avoiding issues if someone attempts to record to ../../lib/sounds/greeting, for example). (closes issue ASTERISK-21594) (closes issue ASTERISK-21581) Review: https://reviewboard.asterisk.org/r/2612/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393550 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/stasis_http')
-rw-r--r--res/stasis_http/resource_channels.c136
-rw-r--r--res/stasis_http/resource_channels.h4
-rw-r--r--res/stasis_http/resource_recordings.c26
-rw-r--r--res/stasis_http/resource_recordings.h40
4 files changed, 181 insertions, 25 deletions
diff --git a/res/stasis_http/resource_channels.c b/res/stasis_http/resource_channels.c
index 0fbb75487..8db3b697c 100644
--- a/res/stasis_http/resource_channels.c
+++ b/res/stasis_http/resource_channels.c
@@ -1,4 +1,4 @@
-/* -*- C -*-
+/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2012 - 2013, Digium, Inc.
@@ -39,6 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/callerid.h"
#include "asterisk/stasis_app.h"
#include "asterisk/stasis_app_playback.h"
+#include "asterisk/stasis_app_recording.h"
#include "asterisk/stasis_channels.h"
#include "resource_channels.h"
@@ -249,10 +250,139 @@ void stasis_http_play_on_channel(struct ast_variable *headers,
stasis_http_response_created(response, playback_url, json);
}
-void stasis_http_record_channel(struct ast_variable *headers, struct ast_record_channel_args *args, struct stasis_http_response *response)
+
+void stasis_http_record_channel(struct ast_variable *headers,
+ struct ast_record_channel_args *args,
+ struct stasis_http_response *response)
{
- ast_log(LOG_ERROR, "TODO: stasis_http_record_channel\n");
+ RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+ RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
+ RAII_VAR(char *, recording_url, NULL, ast_free);
+ RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+ RAII_VAR(struct stasis_app_recording_options *, options, NULL,
+ ao2_cleanup);
+ RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
+ size_t uri_name_maxlen;
+
+ ast_assert(response != NULL);
+
+ if (args->max_duration_seconds < 0) {
+ stasis_http_response_error(
+ response, 400, "Bad Request",
+ "max_duration_seconds cannot be negative");
+ return;
+ }
+
+ if (args->max_silence_seconds < 0) {
+ stasis_http_response_error(
+ response, 400, "Bad Request",
+ "max_silence_seconds cannot be negative");
+ return;
+ }
+
+ control = find_control(response, args->channel_id);
+ if (control == NULL) {
+ /* Response filled in by find_control */
+ return;
+ }
+
+ options = stasis_app_recording_options_create(args->name, args->format);
+ if (options == NULL) {
+ stasis_http_response_error(
+ response, 500, "Internal Server Error",
+ "Out of memory");
+ }
+ options->max_silence_seconds = args->max_silence_seconds;
+ options->max_duration_seconds = args->max_duration_seconds;
+ options->terminate_on =
+ stasis_app_recording_termination_parse(args->terminate_on);
+ options->if_exists =
+ stasis_app_recording_if_exists_parse(args->if_exists);
+ options->beep = args->beep;
+
+ if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
+ stasis_http_response_error(
+ response, 400, "Bad Request",
+ "terminateOn invalid");
+ return;
+ }
+
+ if (options->if_exists == -1) {
+ stasis_http_response_error(
+ response, 400, "Bad Request",
+ "ifExists invalid");
+ return;
+ }
+
+ recording = stasis_app_control_record(control, options);
+ if (recording == NULL) {
+ switch(errno) {
+ case EINVAL:
+ /* While the arguments are invalid, we should have
+ * caught them prior to calling record.
+ */
+ stasis_http_response_error(
+ response, 500, "Internal Server Error",
+ "Error parsing request");
+ break;
+ case EEXIST:
+ stasis_http_response_error(response, 409, "Conflict",
+ "Recording '%s' already in progress",
+ args->name);
+ break;
+ case ENOMEM:
+ stasis_http_response_error(
+ response, 500, "Internal Server Error",
+ "Out of memory");
+ break;
+ case EPERM:
+ stasis_http_response_error(
+ response, 400, "Bad Request",
+ "Recording name invalid");
+ break;
+ default:
+ ast_log(LOG_WARNING,
+ "Unrecognized recording error: %s\n",
+ strerror(errno));
+ stasis_http_response_error(
+ response, 500, "Internal Server Error",
+ "Internal Server Error");
+ break;
+ }
+ return;
+ }
+
+ uri_name_maxlen = strlen(args->name) * 3;
+ uri_encoded_name = ast_malloc(uri_name_maxlen);
+ if (!uri_encoded_name) {
+ stasis_http_response_error(
+ response, 500, "Internal Server Error",
+ "Out of memory");
+ return;
+ }
+ ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen,
+ ast_uri_http);
+
+ ast_asprintf(&recording_url, "/recordings/live/%s", uri_encoded_name);
+ if (!recording_url) {
+ stasis_http_response_error(
+ response, 500, "Internal Server Error",
+ "Out of memory");
+ return;
+ }
+
+ json = stasis_app_recording_to_json(recording);
+ if (!json) {
+ stasis_http_response_error(
+ response, 500, "Internal Server Error",
+ "Out of memory");
+ return;
+ }
+
+ stasis_http_response_created(response, recording_url, json);
}
+
void stasis_http_get_channel(struct ast_variable *headers,
struct ast_get_channel_args *args,
struct stasis_http_response *response)
diff --git a/res/stasis_http/resource_channels.h b/res/stasis_http/resource_channels.h
index 57f2a63d2..7e8dc5dbe 100644
--- a/res/stasis_http/resource_channels.h
+++ b/res/stasis_http/resource_channels.h
@@ -247,8 +247,8 @@ struct ast_record_channel_args {
int max_duration_seconds;
/*! \brief Maximum duration of silence, in seconds. 0 for no limit */
int max_silence_seconds;
- /*! \brief If true, and recording already exists, append to recording */
- int append;
+ /*! \brief Action to take if a recording with the same name already exists. */
+ const char *if_exists;
/*! \brief Play beep when recording begins */
int beep;
/*! \brief DTMF input to terminate recording */
diff --git a/res/stasis_http/resource_recordings.c b/res/stasis_http/resource_recordings.c
index 7d31c42aa..d93d59017 100644
--- a/res/stasis_http/resource_recordings.c
+++ b/res/stasis_http/resource_recordings.c
@@ -27,6 +27,7 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/stasis_app_recording.h"
#include "resource_recordings.h"
void stasis_http_get_stored_recordings(struct ast_variable *headers, struct ast_get_stored_recordings_args *args, struct stasis_http_response *response)
@@ -45,10 +46,31 @@ void stasis_http_get_live_recordings(struct ast_variable *headers, struct ast_ge
{
ast_log(LOG_ERROR, "TODO: stasis_http_get_live_recordings\n");
}
-void stasis_http_get_live_recording(struct ast_variable *headers, struct ast_get_live_recording_args *args, struct stasis_http_response *response)
+
+void stasis_http_get_live_recording(struct ast_variable *headers,
+ struct ast_get_live_recording_args *args,
+ struct stasis_http_response *response)
{
- ast_log(LOG_ERROR, "TODO: stasis_http_get_live_recording\n");
+ RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+
+ recording = stasis_app_recording_find_by_name(args->recording_name);
+ if (recording == NULL) {
+ stasis_http_response_error(response, 404, "Not Found",
+ "Recording not found");
+ return;
+ }
+
+ json = stasis_app_recording_to_json(recording);
+ if (json == NULL) {
+ stasis_http_response_error(response, 500,
+ "Internal Server Error", "Error building response");
+ return;
+ }
+
+ stasis_http_response_ok(response, ast_json_ref(json));
}
+
void stasis_http_cancel_recording(struct ast_variable *headers, struct ast_cancel_recording_args *args, struct stasis_http_response *response)
{
ast_log(LOG_ERROR, "TODO: stasis_http_cancel_recording\n");
diff --git a/res/stasis_http/resource_recordings.h b/res/stasis_http/resource_recordings.h
index acccc124b..18a5bfe68 100644
--- a/res/stasis_http/resource_recordings.h
+++ b/res/stasis_http/resource_recordings.h
@@ -52,8 +52,8 @@ struct ast_get_stored_recordings_args {
void stasis_http_get_stored_recordings(struct ast_variable *headers, struct ast_get_stored_recordings_args *args, struct stasis_http_response *response);
/*! \brief Argument struct for stasis_http_get_stored_recording() */
struct ast_get_stored_recording_args {
- /*! \brief Recording's id */
- const char *recording_id;
+ /*! \brief The name of the recording */
+ const char *recording_name;
};
/*!
* \brief Get a stored recording's details.
@@ -65,8 +65,8 @@ struct ast_get_stored_recording_args {
void stasis_http_get_stored_recording(struct ast_variable *headers, struct ast_get_stored_recording_args *args, struct stasis_http_response *response);
/*! \brief Argument struct for stasis_http_delete_stored_recording() */
struct ast_delete_stored_recording_args {
- /*! \brief Recording's id */
- const char *recording_id;
+ /*! \brief The name of the recording */
+ const char *recording_name;
};
/*!
* \brief Delete a stored recording.
@@ -89,8 +89,8 @@ struct ast_get_live_recordings_args {
void stasis_http_get_live_recordings(struct ast_variable *headers, struct ast_get_live_recordings_args *args, struct stasis_http_response *response);
/*! \brief Argument struct for stasis_http_get_live_recording() */
struct ast_get_live_recording_args {
- /*! \brief Recording's id */
- const char *recording_id;
+ /*! \brief The name of the recording */
+ const char *recording_name;
};
/*!
* \brief List live recordings.
@@ -102,8 +102,8 @@ struct ast_get_live_recording_args {
void stasis_http_get_live_recording(struct ast_variable *headers, struct ast_get_live_recording_args *args, struct stasis_http_response *response);
/*! \brief Argument struct for stasis_http_cancel_recording() */
struct ast_cancel_recording_args {
- /*! \brief Recording's id */
- const char *recording_id;
+ /*! \brief The name of the recording */
+ const char *recording_name;
};
/*!
* \brief Stop a live recording and discard it.
@@ -115,8 +115,8 @@ struct ast_cancel_recording_args {
void stasis_http_cancel_recording(struct ast_variable *headers, struct ast_cancel_recording_args *args, struct stasis_http_response *response);
/*! \brief Argument struct for stasis_http_stop_recording() */
struct ast_stop_recording_args {
- /*! \brief Recording's id */
- const char *recording_id;
+ /*! \brief The name of the recording */
+ const char *recording_name;
};
/*!
* \brief Stop a live recording and store it.
@@ -128,12 +128,14 @@ struct ast_stop_recording_args {
void stasis_http_stop_recording(struct ast_variable *headers, struct ast_stop_recording_args *args, struct stasis_http_response *response);
/*! \brief Argument struct for stasis_http_pause_recording() */
struct ast_pause_recording_args {
- /*! \brief Recording's id */
- const char *recording_id;
+ /*! \brief The name of the recording */
+ const char *recording_name;
};
/*!
* \brief Pause a live recording.
*
+ * Pausing a recording suspends silence detection, which will be restarted when the recording is unpaused.
+ *
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
@@ -141,8 +143,8 @@ struct ast_pause_recording_args {
void stasis_http_pause_recording(struct ast_variable *headers, struct ast_pause_recording_args *args, struct stasis_http_response *response);
/*! \brief Argument struct for stasis_http_unpause_recording() */
struct ast_unpause_recording_args {
- /*! \brief Recording's id */
- const char *recording_id;
+ /*! \brief The name of the recording */
+ const char *recording_name;
};
/*!
* \brief Unpause a live recording.
@@ -154,12 +156,14 @@ struct ast_unpause_recording_args {
void stasis_http_unpause_recording(struct ast_variable *headers, struct ast_unpause_recording_args *args, struct stasis_http_response *response);
/*! \brief Argument struct for stasis_http_mute_recording() */
struct ast_mute_recording_args {
- /*! \brief Recording's id */
- const char *recording_id;
+ /*! \brief The name of the recording */
+ const char *recording_name;
};
/*!
* \brief Mute a live recording.
*
+ * Muting a recording suspends silence detection, which will be restarted when the recording is unmuted.
+ *
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
@@ -167,8 +171,8 @@ struct ast_mute_recording_args {
void stasis_http_mute_recording(struct ast_variable *headers, struct ast_mute_recording_args *args, struct stasis_http_response *response);
/*! \brief Argument struct for stasis_http_unmute_recording() */
struct ast_unmute_recording_args {
- /*! \brief Recording's id */
- const char *recording_id;
+ /*! \brief The name of the recording */
+ const char *recording_name;
};
/*!
* \brief Unmute a live recording.