[asterisk-commits] dlee: branch dlee/ari-monitor2 r395923 - in /team/dlee/ari-monitor2: include/...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Jul 31 21:35:13 CDT 2013
Author: dlee
Date: Wed Jul 31 21:35:11 2013
New Revision: 395923
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=395923
Log:
Merged ari-monitor work
Added:
team/dlee/ari-monitor2/res/stasis_recording/
- copied from r395922, team/dlee/ari-monitor/res/stasis_recording/
Modified:
team/dlee/ari-monitor2/include/asterisk/stasis_app_recording.h
team/dlee/ari-monitor2/res/Makefile
team/dlee/ari-monitor2/res/ari/resource_channels.c
team/dlee/ari-monitor2/res/ari/resource_channels.h
team/dlee/ari-monitor2/res/res_ari_channels.c
team/dlee/ari-monitor2/res/res_stasis_recording.c
team/dlee/ari-monitor2/rest-api/api-docs/channels.json
Modified: team/dlee/ari-monitor2/include/asterisk/stasis_app_recording.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/include/asterisk/stasis_app_recording.h?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/include/asterisk/stasis_app_recording.h (original)
+++ team/dlee/ari-monitor2/include/asterisk/stasis_app_recording.h Wed Jul 31 21:35:11 2013
@@ -133,6 +133,26 @@
struct stasis_app_recording_options *options);
/*!
+ * \brief Monitor media from a channel.
+ *
+ * A reference to the \a options object may be kept, so it MUST NOT be modified
+ * after calling this function.
+ *
+ * On error, \c errno is set to indicate the failure reason.
+ * - \c EINVAL: Invalid input.
+ * - \c EEXIST: A monitor with that name is in session.
+ * - \c ENOMEM: Out of memory.
+ *
+ * \param control Control for \c res_stasis.
+ * \param options Monitor options.
+ * \return Recording control object.
+ * \return \c NULL on error.
+ */
+struct stasis_app_recording *stasis_app_control_monitor(
+ struct stasis_app_control *control,
+ struct stasis_app_recording_options *options);
+
+/*!
* \brief Gets the current state of a recording operation.
*
* \param recording Recording control object.
Modified: team/dlee/ari-monitor2/res/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/res/Makefile?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/res/Makefile (original)
+++ team/dlee/ari-monitor2/res/Makefile Wed Jul 31 21:35:11 2013
@@ -86,5 +86,9 @@
res_ari_model.so: ari/ari_model_validators.o
ari/ari_model_validators.o: _ASTCFLAGS+=$(call MOD_ASTCFLAGS,res_ari_model)
+res_stasis_recording.so: stasis_recording/monitor.o
+stasis_recording/monitor.o: _ASTCFLAGS+=$(call MOD_ASTCFLAGS,res_stasis_recording)
+
+
# Dependencies for res_ari_*.so are generated, so they're in this file
include ari.make
Modified: team/dlee/ari-monitor2/res/ari/resource_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/res/ari/resource_channels.c?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/res/ari/resource_channels.c (original)
+++ team/dlee/ari-monitor2/res/ari/resource_channels.c Wed Jul 31 21:35:11 2013
@@ -329,71 +329,15 @@
ast_ari_response_created(response, playback_url, json);
}
-void ast_ari_record_channel(struct ast_variable *headers,
- struct ast_record_channel_args *args,
+static void response_from_recording(struct stasis_app_recording *recording,
struct ast_ari_response *response)
{
- 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(char *, uri_encoded_name, 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);
+ const char *name = stasis_app_recording_get_name(recording);
size_t uri_name_maxlen;
- ast_assert(response != NULL);
-
- if (args->max_duration_seconds < 0) {
- ast_ari_response_error(
- response, 400, "Bad Request",
- "max_duration_seconds cannot be negative");
- return;
- }
-
- if (args->max_silence_seconds < 0) {
- ast_ari_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) {
- ast_ari_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) {
- ast_ari_response_error(
- response, 400, "Bad Request",
- "terminateOn invalid");
- return;
- }
-
- if (options->if_exists == -1) {
- ast_ari_response_error(
- response, 400, "Bad Request",
- "ifExists invalid");
- return;
- }
-
- recording = stasis_app_control_record(control, options);
if (recording == NULL) {
switch(errno) {
case EINVAL:
@@ -407,7 +351,7 @@
case EEXIST:
ast_ari_response_error(response, 409, "Conflict",
"Recording '%s' already in progress",
- args->name);
+ name);
break;
case ENOMEM:
ast_ari_response_error(
@@ -431,7 +375,7 @@
return;
}
- uri_name_maxlen = strlen(args->name) * 3;
+ uri_name_maxlen = strlen(name) * 3;
uri_encoded_name = ast_malloc(uri_name_maxlen);
if (!uri_encoded_name) {
ast_ari_response_error(
@@ -439,7 +383,7 @@
"Out of memory");
return;
}
- ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen,
+ ast_uri_encode(name, uri_encoded_name, uri_name_maxlen,
ast_uri_http);
ast_asprintf(&recording_url, "/recordings/live/%s", uri_encoded_name);
@@ -459,6 +403,111 @@
}
ast_ari_response_created(response, recording_url, json);
+}
+
+void ast_ari_monitor_channel(struct ast_variable *headers,
+ struct ast_monitor_channel_args *args,
+ struct ast_ari_response *response)
+{
+ RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+ RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+ RAII_VAR(struct stasis_app_recording_options *, options, NULL,
+ ao2_cleanup);
+
+ ast_assert(response != NULL);
+
+ 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) {
+ ast_ari_response_error(
+ response, 500, "Internal Server Error",
+ "Out of memory");
+ }
+ options->if_exists =
+ stasis_app_recording_if_exists_parse(args->if_exists);
+
+
+ if (options->if_exists == -1) {
+ ast_ari_response_error(
+ response, 400, "Bad Request",
+ "ifExists invalid");
+ return;
+ }
+
+ recording = stasis_app_control_monitor(control, options);
+
+ response_from_recording(recording, response);
+}
+
+void ast_ari_record_channel(struct ast_variable *headers,
+ struct ast_record_channel_args *args,
+ struct ast_ari_response *response)
+{
+ 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(struct stasis_app_recording_options *, options, NULL,
+ ao2_cleanup);
+
+ ast_assert(response != NULL);
+
+ if (args->max_duration_seconds < 0) {
+ ast_ari_response_error(
+ response, 400, "Bad Request",
+ "max_duration_seconds cannot be negative");
+ return;
+ }
+
+ if (args->max_silence_seconds < 0) {
+ ast_ari_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) {
+ ast_ari_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) {
+ ast_ari_response_error(
+ response, 400, "Bad Request",
+ "terminateOn invalid");
+ return;
+ }
+
+ if (options->if_exists == -1) {
+ ast_ari_response_error(
+ response, 400, "Bad Request",
+ "ifExists invalid");
+ return;
+ }
+
+ recording = stasis_app_control_record(control, options);
+
+ response_from_recording(recording, response);
}
void ast_ari_get_channel(struct ast_variable *headers,
Modified: team/dlee/ari-monitor2/res/ari/resource_channels.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/res/ari/resource_channels.h?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/res/ari/resource_channels.h (original)
+++ team/dlee/ari-monitor2/res/ari/resource_channels.h Wed Jul 31 21:35:11 2013
@@ -265,6 +265,27 @@
* \param[out] response HTTP response
*/
void ast_ari_play_on_channel(struct ast_variable *headers, struct ast_play_on_channel_args *args, struct ast_ari_response *response);
+/*! \brief Argument struct for ast_ari_monitor_channel() */
+struct ast_monitor_channel_args {
+ /*! \brief Channel's id */
+ const char *channel_id;
+ /*! \brief Recording's filename */
+ const char *name;
+ /*! \brief Format to encode audio in */
+ const char *format;
+ /*! \brief Action to take if a recording with the same name already exists. */
+ const char *if_exists;
+};
+/*!
+ * \brief Start a monitor recording.
+ *
+ * Record audio to/from a channel.
+ *
+ * \param headers HTTP headers
+ * \param args Swagger parameters
+ * \param[out] response HTTP response
+ */
+void ast_ari_monitor_channel(struct ast_variable *headers, struct ast_monitor_channel_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_record_channel() */
struct ast_record_channel_args {
/*! \brief Channel's id */
Modified: team/dlee/ari-monitor2/res/res_ari_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/res/res_ari_channels.c?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/res/res_ari_channels.c (original)
+++ team/dlee/ari-monitor2/res/res_ari_channels.c Wed Jul 31 21:35:11 2013
@@ -901,22 +901,22 @@
#endif /* AST_DEVMODE */
}
/*!
- * \brief Parameter parsing callback for /channels/{channelId}/record.
- * \param get_params GET parameters in the HTTP request.
- * \param path_vars Path variables extracted from the request.
- * \param headers HTTP headers.
- * \param[out] response Response to the HTTP request.
- */
-static void ast_ari_record_channel_cb(
- struct ast_variable *get_params, struct ast_variable *path_vars,
- struct ast_variable *headers, struct ast_ari_response *response)
-{
-#if defined(AST_DEVMODE)
- int is_valid;
- int code;
-#endif /* AST_DEVMODE */
-
- struct ast_record_channel_args args = {};
+ * \brief Parameter parsing callback for /channels/{channelId}/monitor.
+ * \param get_params GET parameters in the HTTP request.
+ * \param path_vars Path variables extracted from the request.
+ * \param headers HTTP headers.
+ * \param[out] response Response to the HTTP request.
+ */
+static void ast_ari_monitor_channel_cb(
+ struct ast_variable *get_params, struct ast_variable *path_vars,
+ struct ast_variable *headers, struct ast_ari_response *response)
+{
+#if defined(AST_DEVMODE)
+ int is_valid;
+ int code;
+#endif /* AST_DEVMODE */
+
+ struct ast_monitor_channel_args args = {};
struct ast_variable *i;
for (i = get_params; i; i = i->next) {
@@ -926,6 +926,75 @@
if (strcmp(i->name, "format") == 0) {
args.format = (i->value);
} else
+ if (strcmp(i->name, "ifExists") == 0) {
+ args.if_exists = (i->value);
+ } else
+ {}
+ }
+ for (i = path_vars; i; i = i->next) {
+ if (strcmp(i->name, "channelId") == 0) {
+ args.channel_id = (i->value);
+ } else
+ {}
+ }
+ ast_ari_monitor_channel(headers, &args, response);
+#if defined(AST_DEVMODE)
+ code = response->response_code;
+
+ switch (code) {
+ case 0: /* Implementation is still a stub, or the code wasn't set */
+ is_valid = response->message == NULL;
+ break;
+ case 500: /* Internal Server Error */
+ case 501: /* Not Implemented */
+ case 400: /* Invalid parameters */
+ case 404: /* Channel not found */
+ case 409: /* Channel is not in a Stasis application; the channel is currently bridged with other channels; A recording with the same name is currently in progress. */
+ is_valid = 1;
+ break;
+ default:
+ if (200 <= code && code <= 299) {
+ is_valid = ast_ari_validate_live_recording(
+ response->message);
+ } else {
+ ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/monitor\n", code);
+ is_valid = 0;
+ }
+ }
+
+ if (!is_valid) {
+ ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/monitor\n");
+ ast_ari_response_error(response, 500,
+ "Internal Server Error", "Response validation failed");
+ }
+#endif /* AST_DEVMODE */
+}
+/*!
+ * \brief Parameter parsing callback for /channels/{channelId}/record.
+ * \param get_params GET parameters in the HTTP request.
+ * \param path_vars Path variables extracted from the request.
+ * \param headers HTTP headers.
+ * \param[out] response Response to the HTTP request.
+ */
+static void ast_ari_record_channel_cb(
+ struct ast_variable *get_params, struct ast_variable *path_vars,
+ struct ast_variable *headers, struct ast_ari_response *response)
+{
+#if defined(AST_DEVMODE)
+ int is_valid;
+ int code;
+#endif /* AST_DEVMODE */
+
+ struct ast_record_channel_args args = {};
+ struct ast_variable *i;
+
+ for (i = get_params; i; i = i->next) {
+ if (strcmp(i->name, "name") == 0) {
+ args.name = (i->value);
+ } else
+ if (strcmp(i->name, "format") == 0) {
+ args.format = (i->value);
+ } else
if (strcmp(i->name, "maxDurationSeconds") == 0) {
args.max_duration_seconds = atoi(i->value);
} else
@@ -1200,6 +1269,15 @@
.children = { }
};
/*! \brief REST handler for /api-docs/channels.{format} */
+static struct stasis_rest_handlers channels_channelId_monitor = {
+ .path_segment = "monitor",
+ .callbacks = {
+ [AST_HTTP_POST] = ast_ari_monitor_channel_cb,
+ },
+ .num_children = 0,
+ .children = { }
+};
+/*! \brief REST handler for /api-docs/channels.{format} */
static struct stasis_rest_handlers channels_channelId_record = {
.path_segment = "record",
.callbacks = {
@@ -1226,8 +1304,8 @@
[AST_HTTP_GET] = ast_ari_get_channel_cb,
[AST_HTTP_DELETE] = ast_ari_delete_channel_cb,
},
- .num_children = 12,
- .children = { &channels_channelId_dial,&channels_channelId_continue,&channels_channelId_answer,&channels_channelId_mute,&channels_channelId_unmute,&channels_channelId_hold,&channels_channelId_unhold,&channels_channelId_mohstart,&channels_channelId_mohstop,&channels_channelId_play,&channels_channelId_record,&channels_channelId_variable, }
+ .num_children = 13,
+ .children = { &channels_channelId_dial,&channels_channelId_continue,&channels_channelId_answer,&channels_channelId_mute,&channels_channelId_unmute,&channels_channelId_hold,&channels_channelId_unhold,&channels_channelId_mohstart,&channels_channelId_mohstop,&channels_channelId_play,&channels_channelId_monitor,&channels_channelId_record,&channels_channelId_variable, }
};
/*! \brief REST handler for /api-docs/channels.{format} */
static struct stasis_rest_handlers channels = {
Modified: team/dlee/ari-monitor2/res/res_stasis_recording.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/res/res_stasis_recording.c?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/res/res_stasis_recording.c (original)
+++ team/dlee/ari-monitor2/res/res_stasis_recording.c Wed Jul 31 21:35:11 2013
@@ -32,13 +32,13 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-#include "asterisk/dsp.h"
#include "asterisk/file.h"
#include "asterisk/module.h"
#include "asterisk/paths.h"
#include "asterisk/stasis_app_impl.h"
#include "asterisk/stasis_app_recording.h"
#include "asterisk/stasis_channels.h"
+#include "stasis_recording/recording.h"
/*! Number of hash buckets for recording container. Keep it prime! */
#define RECORDING_BUCKETS 127
@@ -53,18 +53,6 @@
/*! Container of all current recordings */
static struct ao2_container *recordings;
-
-struct stasis_app_recording {
- /*! Recording options. */
- struct stasis_app_recording_options *options;
- /*! Absolute path (minus extension) of the recording */
- char *absolute_name;
- /*! Control object for the channel we're playing back to */
- struct stasis_app_control *control;
-
- /*! Current state of the recording. */
- enum stasis_app_recording_state state;
-};
static int recording_hash(const void *obj, int flags)
{
@@ -177,7 +165,7 @@
return -1;
}
-static void recording_publish(struct stasis_app_recording *recording)
+void recording_publish(struct stasis_app_recording *recording)
{
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
@@ -290,7 +278,7 @@
ao2_cleanup(recording->options);
}
-struct stasis_app_recording *stasis_app_control_record(
+struct stasis_app_recording *recording_create(
struct stasis_app_control *control,
struct stasis_app_recording_options *options)
{
@@ -359,6 +347,21 @@
ao2_link(recordings, recording);
}
+ ao2_ref(recording, +1);
+ return recording;
+}
+
+struct stasis_app_recording *stasis_app_control_record(
+ struct stasis_app_control *control,
+ struct stasis_app_recording_options *options)
+{
+ RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
+
+ recording = recording_create(control, options);
+ if (!recording) {
+ return NULL;
+ }
+
/* A ref is kept in the recordings container; no need to bump */
stasis_app_send_command_async(control, record_file, recording);
Modified: team/dlee/ari-monitor2/rest-api/api-docs/channels.json
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/rest-api/api-docs/channels.json?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/rest-api/api-docs/channels.json (original)
+++ team/dlee/ari-monitor2/rest-api/api-docs/channels.json Wed Jul 31 21:35:11 2013
@@ -597,6 +597,76 @@
{
"code": 409,
"reason": "Channel not in a Stasis application"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "path": "/channels/{channelId}/monitor",
+ "description": "Starts a monitor recording on a channel",
+ "operations": [
+ {
+ "httpMethod": "POST",
+ "summary": "Start a monitor recording.",
+ "notes": "Record audio to/from a channel.",
+ "nickname": "monitorChannel",
+ "responseClass": "LiveRecording",
+ "parameters": [
+ {
+ "name": "channelId",
+ "description": "Channel's id",
+ "paramType": "path",
+ "required": true,
+ "allowMultiple": false,
+ "dataType": "string"
+ },
+ {
+ "name": "name",
+ "description": "Recording's filename",
+ "paramType": "query",
+ "required": true,
+ "allowMultiple": false,
+ "dataType": "string"
+ },
+ {
+ "name": "format",
+ "description": "Format to encode audio in",
+ "paramType": "query",
+ "required": true,
+ "allowMultiple": true,
+ "dataType": "string"
+ },
+ {
+ "name": "ifExists",
+ "description": "Action to take if a recording with the same name already exists.",
+ "paramType": "query",
+ "required": false,
+ "allowMultiple": false,
+ "dataType": "string",
+ "defaultValue": "fail",
+ "allowableValues": {
+ "valueType": "LIST",
+ "values": [
+ "fail",
+ "overwrite",
+ "append"
+ ]
+ }
+ }
+ ],
+ "errorResponses": [
+ {
+ "code": 400,
+ "reason": "Invalid parameters"
+ },
+ {
+ "code": 404,
+ "reason": "Channel not found"
+ },
+ {
+ "code": 409,
+ "reason": "Channel is not in a Stasis application; the channel is currently bridged with other channels; A recording with the same name is currently in progress."
}
]
}
More information about the asterisk-commits
mailing list