Asterisk - The Open Source Telephony Project  18.5.0
Data Structures
stasis_app_recording.h File Reference

Stasis Application Recording API. See StasisApplication API" for detailed documentation. More...

#include "asterisk/app.h"
#include "asterisk/stasis_app.h"
Include dependency graph for stasis_app_recording.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  stasis_app_recording_options
 

Functions

const char * stasis_app_stored_recording_get_file (struct stasis_app_stored_recording *recording)
 Returns the filename for this recording, for use with streamfile. More...
 
const char * stasis_app_stored_recording_get_filename (struct stasis_app_stored_recording *recording)
 Returns the full filename, with extension, for this recording. More...
 
const char * stasis_app_stored_recording_get_extension (struct stasis_app_stored_recording *recording)
 Returns the extension for this recording. More...
 
struct ast_jsonstasis_app_stored_recording_to_json (struct stasis_app_stored_recording *recording)
 Convert stored recording info to JSON. More...
 
struct ao2_containerstasis_app_stored_recording_find_all (void)
 Find all stored recordings on disk. More...
 
struct stasis_app_stored_recordingstasis_app_stored_recording_find_by_name (const char *name)
 Creates a stored recording object, with the given name. More...
 
int stasis_app_stored_recording_copy (struct stasis_app_stored_recording *src_recording, const char *dst, struct stasis_app_stored_recording **dst_recording)
 Copy a recording. More...
 
int stasis_app_stored_recording_delete (struct stasis_app_stored_recording *recording)
 Delete a recording from disk. More...
 
#define STASIS_APP_RECORDING_TERMINATE_INVALID   0
 
#define STASIS_APP_RECORDING_TERMINATE_NONE   -1
 
#define STASIS_APP_RECORDING_TERMINATE_ANY   -2
 
enum  stasis_app_recording_state {
  STASIS_APP_RECORDING_STATE_QUEUED, STASIS_APP_RECORDING_STATE_RECORDING, STASIS_APP_RECORDING_STATE_PAUSED, STASIS_APP_RECORDING_STATE_COMPLETE,
  STASIS_APP_RECORDING_STATE_FAILED, STASIS_APP_RECORDING_STATE_CANCELED, STASIS_APP_RECORDING_STATE_MAX
}
 
enum  stasis_app_recording_media_operation {
  STASIS_APP_RECORDING_CANCEL, STASIS_APP_RECORDING_STOP, STASIS_APP_RECORDING_PAUSE, STASIS_APP_RECORDING_UNPAUSE,
  STASIS_APP_RECORDING_MUTE, STASIS_APP_RECORDING_UNMUTE, STASIS_APP_RECORDING_OPER_MAX
}
 
enum  stasis_app_recording_oper_results { STASIS_APP_RECORDING_OPER_OK, STASIS_APP_RECORDING_OPER_FAILED, STASIS_APP_RECORDING_OPER_NOT_RECORDING }
 Possible results from a recording operation. More...
 
struct stasis_app_recording_optionsstasis_app_recording_options_create (const char *name, const char *format)
 Allocate a recording options object. More...
 
char stasis_app_recording_termination_parse (const char *str)
 Parse a string into the recording termination enum. More...
 
enum ast_record_if_exists stasis_app_recording_if_exists_parse (const char *str)
 Parse a string into the if_exists enum. More...
 
struct stasis_app_recordingstasis_app_control_record (struct stasis_app_control *control, struct stasis_app_recording_options *options)
 Record media from a channel. More...
 
enum stasis_app_recording_state stasis_app_recording_get_state (struct stasis_app_recording *recording)
 Gets the current state of a recording operation. More...
 
const char * stasis_app_recording_get_name (struct stasis_app_recording *recording)
 Gets the unique name of a recording object. More...
 
struct stasis_app_recordingstasis_app_recording_find_by_name (const char *name)
 Finds the recording object with the given name. More...
 
struct ast_jsonstasis_app_recording_to_json (const struct stasis_app_recording *recording)
 Construct a JSON model of a recording. More...
 
enum stasis_app_recording_oper_results stasis_app_recording_operation (struct stasis_app_recording *recording, enum stasis_app_recording_media_operation operation)
 Controls the media for a given recording operation. More...
 
struct stasis_message_typestasis_app_recording_snapshot_type (void)
 Message type for recording updates. The data is an ast_channel_blob. More...
 

Detailed Description

Stasis Application Recording API. See StasisApplication API" for detailed documentation.

Author
David M. Lee, II [email protected][email protected]digi[email protected]um.co[email protected]m
Since
12

Definition in file stasis_app_recording.h.

Macro Definition Documentation

◆ STASIS_APP_RECORDING_TERMINATE_ANY

#define STASIS_APP_RECORDING_TERMINATE_ANY   -2

Definition at line 174 of file stasis_app_recording.h.

Referenced by record_file(), and stasis_app_recording_termination_parse().

◆ STASIS_APP_RECORDING_TERMINATE_INVALID

#define STASIS_APP_RECORDING_TERMINATE_INVALID   0

◆ STASIS_APP_RECORDING_TERMINATE_NONE

#define STASIS_APP_RECORDING_TERMINATE_NONE   -1

Definition at line 173 of file stasis_app_recording.h.

Referenced by record_file(), and stasis_app_recording_termination_parse().

Enumeration Type Documentation

◆ stasis_app_recording_media_operation

Valid operation for controlling a recording.

Enumerator
STASIS_APP_RECORDING_CANCEL 

Stop the recording, deleting the media file(s)

STASIS_APP_RECORDING_STOP 

Stop the recording.

STASIS_APP_RECORDING_PAUSE 

Pause the recording

STASIS_APP_RECORDING_UNPAUSE 

Unpause the recording

STASIS_APP_RECORDING_MUTE 

Mute the recording (record silence)

STASIS_APP_RECORDING_UNMUTE 

Unmute the recording

STASIS_APP_RECORDING_OPER_MAX 

Sentinel

Definition at line 155 of file stasis_app_recording.h.

155  {
156  /*! Stop the recording, deleting the media file(s) */
158  /*! Stop the recording. */
160  /*! Pause the recording */
162  /*! Unpause the recording */
164  /*! Mute the recording (record silence) */
166  /*! Unmute the recording */
168  /*! Sentinel */
170 };

◆ stasis_app_recording_oper_results

Possible results from a recording operation.

Enumerator
STASIS_APP_RECORDING_OPER_OK 

Operation completed successfully.

STASIS_APP_RECORDING_OPER_FAILED 

Operation failed.

STASIS_APP_RECORDING_OPER_NOT_RECORDING 

Operation failed b/c recording is not in session.

Definition at line 292 of file stasis_app_recording.h.

292  {
293  /*! Operation completed successfully. */
295  /*! Operation failed. */
297  /*! Operation failed b/c recording is not in session. */
299 };

◆ stasis_app_recording_state

State of a recording operation

Enumerator
STASIS_APP_RECORDING_STATE_QUEUED 

The recording has not started yet

STASIS_APP_RECORDING_STATE_RECORDING 

The media is currently recording

STASIS_APP_RECORDING_STATE_PAUSED 

The media is currently paused

STASIS_APP_RECORDING_STATE_COMPLETE 

The media has stopped recording

STASIS_APP_RECORDING_STATE_FAILED 

The media has stopped recording, with error

STASIS_APP_RECORDING_STATE_CANCELED 

The media has stopped recording, discard the recording file

STASIS_APP_RECORDING_STATE_MAX 

Sentinel

Definition at line 137 of file stasis_app_recording.h.

137  {
138  /*! The recording has not started yet */
140  /*! The media is currently recording */
142  /*! The media is currently paused */
144  /*! The media has stopped recording */
146  /*! The media has stopped recording, with error */
148  /*! The media has stopped recording, discard the recording file */
150  /*! Sentinel */
152 };

Function Documentation

◆ stasis_app_control_record()

struct stasis_app_recording* stasis_app_control_record ( struct stasis_app_control control,
struct stasis_app_recording_options options 
)

Record media from a channel.

A reference to the options object may be kept, so it MUST NOT be modified after calling this function.

On error, errno is set to indicate the failure reason.

  • EINVAL: Invalid input.
  • EEXIST: A recording with that name is in session.
  • ENOMEM: Out of memory.
Parameters
controlControl for res_stasis.
optionsRecording options.
Returns
Recording control object.
NULL on error.

Definition at line 370 of file res_stasis_recording.c.

References stasis_app_recording::absolute_name, ao2_alloc, ao2_bump, ao2_cleanup, ao2_find, ao2_link, ao2_ref, ast_asprintf, ast_config_AST_RECORDING_DIR, ast_debug, ast_fileexists(), ast_log, AST_RECORD_IF_EXISTS_FAIL, ast_safe_mkdir(), ast_strlen_zero, stasis_app_recording::control, stasis_app_recording::duration, stasis_app_recording::energy_only, errno, stasis_app_recording_options::format, stasis_app_recording_options::if_exists, lock, LOG_WARNING, stasis_app_recording_options::max_duration_seconds, stasis_app_recording_options::max_silence_seconds, stasis_app_recording_options::name, NULL, OBJ_KEY, OBJ_NOLOCK, stasis_app_recording::options, RAII_VAR, record_file(), recording_cleanup(), recording_dtor(), SCOPED_AO2LOCK, stasis_app_control_get_channel_id(), stasis_app_control_register_add_rule(), STASIS_APP_RECORDING_STATE_QUEUED, stasis_app_send_command_async(), stasis_app_recording::state, and stasis_app_recording::total.

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

373 {
374  struct stasis_app_recording *recording;
375  char *last_slash;
376 
377  errno = 0;
378 
379  if (options == NULL ||
380  ast_strlen_zero(options->name) ||
381  ast_strlen_zero(options->format) ||
382  options->max_silence_seconds < 0 ||
383  options->max_duration_seconds < 0) {
384  errno = EINVAL;
385  return NULL;
386  }
387 
388  ast_debug(3, "%s: Sending record(%s.%s) command\n",
389  stasis_app_control_get_channel_id(control), options->name,
390  options->format);
391 
392  recording = ao2_alloc(sizeof(*recording), recording_dtor);
393  if (!recording) {
394  errno = ENOMEM;
395  return NULL;
396  }
397  recording->duration.total = -1;
398  recording->duration.energy_only = -1;
399 
400  ast_asprintf(&recording->absolute_name, "%s/%s",
402 
403  if (recording->absolute_name == NULL) {
404  errno = ENOMEM;
405  ao2_ref(recording, -1);
406  return NULL;
407  }
408 
409  if ((last_slash = strrchr(recording->absolute_name, '/'))) {
410  *last_slash = '\0';
412  recording->absolute_name, 0777) != 0) {
413  /* errno set by ast_mkdir */
414  ao2_ref(recording, -1);
415  return NULL;
416  }
417  *last_slash = '/';
418  }
419 
420  ao2_ref(options, +1);
421  recording->options = options;
422  ao2_ref(control, +1);
423  recording->control = control;
425 
426  if ((recording->options->if_exists == AST_RECORD_IF_EXISTS_FAIL) &&
427  (ast_fileexists(recording->absolute_name, NULL, NULL))) {
428  ast_log(LOG_WARNING, "Recording file '%s' already exists and ifExists option is failure.\n",
429  recording->absolute_name);
430  errno = EEXIST;
431  ao2_ref(recording, -1);
432  return NULL;
433  }
434 
435  {
436  RAII_VAR(struct stasis_app_recording *, old_recording, NULL,
437  ao2_cleanup);
438 
440 
441  old_recording = ao2_find(recordings, options->name,
442  OBJ_KEY | OBJ_NOLOCK);
443  if (old_recording) {
445  "Recording %s already in progress\n",
446  recording->options->name);
447  errno = EEXIST;
448  ao2_ref(recording, -1);
449  return NULL;
450  }
451  ao2_link(recordings, recording);
452  }
453 
455 
457 
458  return recording;
459 }
enum stasis_app_recording_state state
#define OBJ_KEY
Definition: astobj2.h:1155
struct stasis_app_control * control
#define LOG_WARNING
Definition: logger.h:274
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define NULL
Definition: resample.c:96
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_bump(obj)
Definition: astobj2.h:491
void stasis_app_control_register_add_rule(struct stasis_app_control *control, struct stasis_app_control_rule *rule)
Registers an add channel to bridge rule.
Definition: control.c:217
static struct stasis_app_control_rule rule_recording
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void recording_dtor(void *obj)
int stasis_app_send_command_async(struct stasis_app_control *control, stasis_app_command_cb command, void *data, command_data_destructor_fn data_destructor)
Asynchronous version of stasis_app_send_command().
Definition: control.c:904
struct stasis_app_recording_options * options
const char * stasis_app_control_get_channel_id(const struct stasis_app_control *control)
Returns the uniqueid of the channel associated with this control.
Definition: control.c:1430
int errno
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
struct stasis_app_recording::@498 duration
int ast_safe_mkdir(const char *base_path, const char *path, int mode)
Recursively create directory path, but only if it resolves within the given base_path.
Definition: main/utils.c:2336
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int record_file(struct stasis_app_control *control, struct ast_channel *chan, void *data)
const char * ast_config_AST_RECORDING_DIR
Definition: options.c:156
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
enum ast_record_if_exists if_exists
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1086
static void recording_cleanup(void *data)
static struct test_options options
static struct ao2_container * recordings
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ stasis_app_recording_find_by_name()

struct stasis_app_recording* stasis_app_recording_find_by_name ( const char *  name)

Finds the recording object with the given name.

Parameters
nameName of the recording object to find.
Returns
Associated stasis_app_recording object.
NULL if name not found.

Definition at line 473 of file res_stasis_recording.c.

References ao2_find, and OBJ_KEY.

Referenced by ast_ari_recordings_get_live(), and control_recording().

474 {
475  return ao2_find(recordings, name, OBJ_KEY);
476 }
#define OBJ_KEY
Definition: astobj2.h:1155
static const char name[]
Definition: cdr_mysql.c:74
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static struct ao2_container * recordings

◆ stasis_app_recording_get_name()

const char* stasis_app_recording_get_name ( struct stasis_app_recording recording)

Gets the unique name of a recording object.

Parameters
recordingRecording control object.
Returns
recording's name.
NULL if recording ic NULL

Definition at line 467 of file res_stasis_recording.c.

References stasis_app_recording_options::name, and stasis_app_recording::options.

469 {
470  return recording->options->name;
471 }
struct stasis_app_recording_options * options

◆ stasis_app_recording_get_state()

enum stasis_app_recording_state stasis_app_recording_get_state ( struct stasis_app_recording recording)

Gets the current state of a recording operation.

Parameters
recordingRecording control object.
Returns
The state of the recording object.

Definition at line 461 of file res_stasis_recording.c.

References stasis_app_recording::state.

463 {
464  return recording->state;
465 }
enum stasis_app_recording_state state

◆ stasis_app_recording_if_exists_parse()

enum ast_record_if_exists stasis_app_recording_if_exists_parse ( const char *  str)

Parse a string into the if_exists enum.

Parameters
strString to parse.
Returns
How to handle an existing file.
-1 on error.

Definition at line 194 of file res_stasis_recording.c.

References AST_RECORD_IF_EXISTS_APPEND, AST_RECORD_IF_EXISTS_ERROR, AST_RECORD_IF_EXISTS_FAIL, AST_RECORD_IF_EXISTS_OVERWRITE, and ast_strlen_zero.

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

196 {
197  if (ast_strlen_zero(str)) {
198  /* Default value */
200  }
201 
202  if (strcasecmp(str, "fail") == 0) {
204  }
205 
206  if (strcasecmp(str, "overwrite") == 0) {
208  }
209 
210  if (strcasecmp(str, "append") == 0) {
212  }
213 
215 }
const char * str
Definition: app_jack.c:147
#define ast_strlen_zero(foo)
Definition: strings.h:52

◆ stasis_app_recording_operation()

enum stasis_app_recording_oper_results stasis_app_recording_operation ( struct stasis_app_recording recording,
enum stasis_app_recording_media_operation  operation 
)

Controls the media for a given recording operation.

Parameters
recordingRecording control object.
controlMedia control operation.
Returns
STASIS_APP_RECORDING_OPER_OK on success.
stasis_app_recording_oper_results indicating failure.

Definition at line 590 of file res_stasis_recording.c.

References ast_log, lock, LOG_ERROR, LOG_WARNING, operations, SCOPED_AO2LOCK, STASIS_APP_RECORDING_OPER_FAILED, STASIS_APP_RECORDING_OPER_MAX, STASIS_APP_RECORDING_OPER_NOT_RECORDING, STASIS_APP_RECORDING_OPER_OK, STASIS_APP_RECORDING_STATE_MAX, STASIS_APP_RECORDING_STATE_RECORDING, and stasis_app_recording::state.

Referenced by control_recording().

593 {
595  SCOPED_AO2LOCK(lock, recording);
596 
597  if ((unsigned int)recording->state >= STASIS_APP_RECORDING_STATE_MAX) {
598  ast_log(LOG_WARNING, "Invalid recording state %u\n",
599  recording->state);
600  return -1;
601  }
602 
603  if ((unsigned int)operation >= STASIS_APP_RECORDING_OPER_MAX) {
604  ast_log(LOG_WARNING, "Invalid recording operation %u\n",
605  operation);
606  return -1;
607  }
608 
609  cb = operations[recording->state][operation];
610 
611  if (!cb) {
612  if (recording->state != STASIS_APP_RECORDING_STATE_RECORDING) {
613  /* So we can be specific in our error message. */
615  } else {
616  /* And, really, all operations should be valid during
617  * recording */
619  "Unhandled operation during recording: %u\n",
620  operation);
622  }
623  }
624 
625  return cb(recording) ?
627 }
enum stasis_app_recording_state state
#define LOG_WARNING
Definition: logger.h:274
recording_operation_cb operations[STASIS_APP_RECORDING_STATE_MAX][STASIS_APP_RECORDING_OPER_MAX]
#define ast_log
Definition: astobj2.c:42
int(* recording_operation_cb)(struct stasis_app_recording *recording)
ast_mutex_t lock
Definition: app_meetme.c:1091
#define LOG_ERROR
Definition: logger.h:285
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602

◆ stasis_app_recording_options_create()

struct stasis_app_recording_options* stasis_app_recording_options_create ( const char *  name,
const char *  format 
)

Allocate a recording options object.

Clean up with ao2_cleanup().

Parameters
nameName of the recording.
formatFormat to record in.
Returns
Newly allocated options object.
NULL on error.

Definition at line 151 of file res_stasis_recording.c.

References ao2_alloc, ao2_cleanup, ao2_ref, ast_string_field_init, ast_string_field_set, NULL, stasis_app_recording::options, RAII_VAR, and recording_options_dtor().

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

153 {
155  ao2_cleanup);
156 
158 
159  if (!options || ast_string_field_init(options, 128)) {
160  return NULL;
161  }
164 
165  ao2_ref(options, +1);
166  return options;
167 }
#define NULL
Definition: resample.c:96
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void recording_options_dtor(void *obj)
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static const char name[]
Definition: cdr_mysql.c:74
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct test_options options
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ stasis_app_recording_snapshot_type()

struct stasis_message_type* stasis_app_recording_snapshot_type ( void  )

Message type for recording updates. The data is an ast_channel_blob.

Referenced by load_module(), recording_publish(), recording_to_json(), and unload_module().

◆ stasis_app_recording_termination_parse()

char stasis_app_recording_termination_parse ( const char *  str)

Parse a string into the recording termination enum.

Parameters
strString to parse.
Returns
DTMF value to terminate on.
STASIS_APP_RECORDING_TERMINATE_NONE to not terminate on DTMF.
STASIS_APP_RECORDING_TERMINATE_ANY to terminate on any DTMF.
STASIS_APP_RECORDING_TERMINATE_INVALID if input was invalid.

Definition at line 169 of file res_stasis_recording.c.

References ast_strlen_zero, STASIS_APP_RECORDING_TERMINATE_ANY, STASIS_APP_RECORDING_TERMINATE_INVALID, and STASIS_APP_RECORDING_TERMINATE_NONE.

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

170 {
171  if (ast_strlen_zero(str)) {
173  }
174 
175  if (strcasecmp(str, "none") == 0) {
177  }
178 
179  if (strcasecmp(str, "any") == 0) {
181  }
182 
183  if (strcasecmp(str, "#") == 0) {
184  return '#';
185  }
186 
187  if (strcasecmp(str, "*") == 0) {
188  return '*';
189  }
190 
192 }
const char * str
Definition: app_jack.c:147
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define STASIS_APP_RECORDING_TERMINATE_ANY
#define STASIS_APP_RECORDING_TERMINATE_INVALID
#define STASIS_APP_RECORDING_TERMINATE_NONE

◆ stasis_app_recording_to_json()

struct ast_json* stasis_app_recording_to_json ( const struct stasis_app_recording recording)

Construct a JSON model of a recording.

Parameters
recordingRecording to conver.
Returns
JSON model.
NULL on error.

Definition at line 478 of file res_stasis_recording.c.

References ast_json_integer_create(), ast_json_object_set(), ast_json_pack(), ast_json_ref(), ast_json_unref(), stasis_app_recording::duration, stasis_app_recording::energy_only, stasis_app_recording_options::format, stasis_app_recording_options::name, NULL, stasis_app_recording::options, RAII_VAR, stasis_app_recording::state, state_to_string(), stasis_app_recording_options::target, and stasis_app_recording::total.

Referenced by ast_ari_bridges_record(), ast_ari_channels_record(), ast_ari_recordings_get_live(), and recording_publish().

480 {
481  RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
482 
483  if (recording == NULL) {
484  return NULL;
485  }
486 
487  json = ast_json_pack("{s: s, s: s, s: s, s: s}",
488  "name", recording->options->name,
489  "format", recording->options->format,
490  "state", state_to_string(recording->state),
491  "target_uri", recording->options->target);
492  if (json && recording->duration.total > -1) {
493  ast_json_object_set(json, "duration",
495  }
496  if (json && recording->duration.energy_only > -1) {
497  ast_json_object_set(json, "talking_duration",
499  ast_json_object_set(json, "silence_duration",
500  ast_json_integer_create(recording->duration.total - recording->duration.energy_only));
501  }
502 
503  return ast_json_ref(json);
504 }
enum stasis_app_recording_state state
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
#define NULL
Definition: resample.c:96
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:404
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
struct stasis_app_recording_options * options
struct stasis_app_recording::@498 duration
Abstract JSON element (object, array, string, int, ...).
static const char * state_to_string(enum stasis_app_recording_state state)
struct ast_json * ast_json_integer_create(intmax_t value)
Create a JSON integer.
Definition: json.c:317

◆ stasis_app_stored_recording_copy()

int stasis_app_stored_recording_copy ( struct stasis_app_stored_recording src_recording,
const char *  dst,
struct stasis_app_stored_recording **  dst_recording 
)

Copy a recording.

Parameters
src_recordingThe recording to copy
dstThe destination of the recording to make
dst_recordingIf successful, the stored recording created as a result of the copy
Return values
0on success
Non-zeroon error

Definition at line 389 of file stored.c.

Referenced by ast_ari_recordings_copy_stored().

396 {
397  RAII_VAR(char *, full_path, NULL, ast_free);
398  char *dst_file = ast_strdupa(dst);
399  char *format;
400  char *last_slash;
401  int res;
402 
403  /* Drop the extension if specified, core will do this for us */
404  format = strrchr(dst_file, '.');
405  if (format) {
406  *format = '\0';
407  }
408 
409  /* See if any intermediary directories need to be made */
410  last_slash = strrchr(dst_file, '/');
411  if (last_slash) {
412  RAII_VAR(char *, tmp_path, NULL, ast_free);
413 
414  *last_slash = '\0';
415  if (ast_asprintf(&tmp_path, "%s/%s", ast_config_AST_RECORDING_DIR, dst_file) < 0) {
416  return -1;
417  }
419  tmp_path, 0777) != 0) {
420  /* errno set by ast_mkdir */
421  return -1;
422  }
423  *last_slash = '/';
424  if (ast_asprintf(&full_path, "%s/%s", ast_config_AST_RECORDING_DIR, dst_file) < 0) {
425  return -1;
426  }
427  } else {
428  /* There is no directory portion */
429  if (ast_asprintf(&full_path, "%s/%s", ast_config_AST_RECORDING_DIR, dst_file) < 0) {
430  return -1;
431  }
432  }
433 
434  ast_verb(4, "Copying recording %s to %s (format %s)\n", src_recording->file,
435  full_path, src_recording->format);
436  res = ast_filecopy(src_recording->file, full_path, src_recording->format);
437  if (!res) {
int ast_filecopy(const char *oldname, const char *newname, const char *fmt)
Copies a file.
Definition: file.c:1108
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_free(a)
Definition: astmm.h:182
int ast_safe_mkdir(const char *base_path, const char *path, int mode)
Recursively create directory path, but only if it resolves within the given base_path.
Definition: main/utils.c:2336
const ast_string_field file
Definition: stored.c:41
const char * ast_config_AST_RECORDING_DIR
Definition: options.c:156
const char * format
Definition: stored.c:41
static snd_pcm_format_t format
Definition: chan_alsa.c:102

◆ stasis_app_stored_recording_delete()

int stasis_app_stored_recording_delete ( struct stasis_app_stored_recording recording)

Delete a recording from disk.

Parameters
recordingRecording to delete.
Returns
0 on success.
Non-zero on error.

Definition at line 439 of file stored.c.

Referenced by ast_ari_recordings_delete_stored().

446 {

◆ stasis_app_stored_recording_find_all()

struct ao2_container* stasis_app_stored_recording_find_all ( void  )

Find all stored recordings on disk.

Returns
Container of stasis_app_stored_recording objects.
NULL on error.

Definition at line 290 of file stored.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, ao2_container_alloc_rbtree, ao2_ref, ast_config_AST_RECORDING_DIR, ast_file_read_dirs(), handle_scan_file(), NULL, recording_sort(), and recordings.

Referenced by ast_ari_recordings_list_stored().

294 {
295  struct ao2_container *recordings;
296  int res;
297 
300  if (!recordings) {
301  return NULL;
302  }
303 
305  handle_scan_file, recordings, -1);
306  if (res) {
307  ao2_ref(recordings, -1);
308  return NULL;
#define NULL
Definition: resample.c:96
int ast_file_read_dirs(const char *dir_name, ast_file_on_file on_file, void *obj, int max_depth)
Recursively iterate through files and directories up to max_depth.
Definition: file.c:1231
static int handle_scan_file(const char *dir_name, const char *filename, void *obj)
Definition: stored.c:249
static struct stasis_rest_handlers recordings
REST handler for /api-docs/recordings.json.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Replace objects with duplicate keys in container.
Definition: astobj2.h:1215
const char * ast_config_AST_RECORDING_DIR
Definition: options.c:156
static int recording_sort(const void *obj_left, const void *obj_right, int flags)
Definition: stored.c:219
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1358
Generic container type.

◆ stasis_app_stored_recording_find_by_name()

struct stasis_app_stored_recording* stasis_app_stored_recording_find_by_name ( const char *  name)

Creates a stored recording object, with the given name.

Parameters
nameName of the recording.
Returns
New recording object.
NULL if recording is not found. errno is set to indicate why
  • ENOMEM - out of memeory
  • EACCES - file permissions (or recording is outside the config dir)
  • Any of the error codes for stat(), opendir(), readdir()

Definition at line 310 of file stored.c.

References ao2_cleanup, ast_begins_with(), ast_config_AST_RECORDING_DIR, ast_free, ast_log, ast_std_free(), ast_string_field_build, ast_string_field_set, errno, stasis_app_stored_recording::file, stasis_app_stored_recording::file_with_ext, find_recording(), LOG_WARNING, NULL, RAII_VAR, recording_alloc(), and split_path().

Referenced by ast_ari_recordings_copy_stored(), ast_ari_recordings_delete_stored(), ast_ari_recordings_get_stored(), ast_ari_recordings_get_stored_file(), and play_on_channel().

316 {
317  RAII_VAR(struct stasis_app_stored_recording *, recording, NULL,
318  ao2_cleanup);
319  RAII_VAR(char *, dir, NULL, ast_free);
320  RAII_VAR(char *, file, NULL, ast_free);
321  RAII_VAR(char *, file_with_ext, NULL, ast_free);
322  int res;
323  struct stat file_stat;
324  int prefix_len = strlen(ast_config_AST_RECORDING_DIR);
325 
326  errno = 0;
327 
328  if (!name) {
329  errno = EINVAL;
330  return NULL;
331  }
332 
333  recording = recording_alloc();
334  if (!recording) {
335  return NULL;
336  }
337 
338  res = split_path(name, &dir, &file);
339  if (res != 0) {
340  return NULL;
341  }
342  ast_string_field_build(recording, file, "%s/%s", dir, file);
343 
345  /* It's possible that one or more component of the recording path is
346  * a symbolic link, this would prevent dir from ever matching. */
347  char *real_basedir = realpath(ast_config_AST_RECORDING_DIR, NULL);
348 
349  if (!real_basedir || !ast_begins_with(dir, real_basedir)) {
350  /* Attempt to escape the recording directory */
351  ast_log(LOG_WARNING, "Attempt to access invalid recording directory %s\n",
352  dir);
353  ast_std_free(real_basedir);
354  errno = EACCES;
355 
356  return NULL;
357  }
358 
359  prefix_len = strlen(real_basedir);
360  ast_std_free(real_basedir);
361  }
362 
363  /* The actual name of the recording is file with the config dir
364  * prefix removed.
365  */
366  ast_string_field_set(recording, name, recording->file + prefix_len + 1);
367 
368  file_with_ext = find_recording(dir, file);
369  if (!file_with_ext) {
370  return NULL;
371  }
372  ast_string_field_set(recording, file_with_ext, file_with_ext);
373  recording->format = strrchr(recording->file_with_ext, '.');
374  if (!recording->format) {
375  return NULL;
376  }
377  ++(recording->format);
378 
379  res = stat(file_with_ext, &file_stat);
380  if (res != 0) {
381  return NULL;
382  }
383 
384  if (!S_ISREG(file_stat.st_mode)) {
385  /* Let's not play if it's not a regular file */
386  errno = EACCES;
387  return NULL;
void ast_std_free(void *ptr)
Definition: astmm.c:1766
static char * find_recording(const char *dir_name, const char *file)
Finds a recording in the given directory.
Definition: stored.c:184
static struct stasis_app_stored_recording * recording_alloc(void)
Allocate a recording object.
Definition: stored.c:200
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
static int split_path(const char *path, char **dir, char **file)
Split a path into directory and file, resolving canonical directory.
Definition: stored.c:92
int errno
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:550
const char * ast_config_AST_RECORDING_DIR
Definition: options.c:156
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Definition: strings.h:94
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ stasis_app_stored_recording_get_extension()

const char* stasis_app_stored_recording_get_extension ( struct stasis_app_stored_recording recording)

Returns the extension for this recording.

Since
14.0.0
Parameters
recordingRecording to query.
Returns
The extension associated with this recording.
NULL on error

Definition at line 71 of file stored.c.

References stasis_app_stored_recording::format, and NULL.

Referenced by ast_ari_recordings_get_stored_file().

73 {
74  if (!recording) {
75  return NULL;
76  }
77  return recording->format;
78 }
#define NULL
Definition: resample.c:96
const char * format
Definition: stored.c:41

◆ stasis_app_stored_recording_get_file()

const char* stasis_app_stored_recording_get_file ( struct stasis_app_stored_recording recording)

Returns the filename for this recording, for use with streamfile.

The returned string will be valid until the recording object is freed.

Parameters
recordingRecording to query.
Returns
Absolute path to the recording file, without the extension.
NULL on error.

Definition at line 53 of file stored.c.

References stasis_app_stored_recording::file, and NULL.

Referenced by play_on_channel().

55 {
56  if (!recording) {
57  return NULL;
58  }
59  return recording->file;
60 }
#define NULL
Definition: resample.c:96
const ast_string_field file
Definition: stored.c:41

◆ stasis_app_stored_recording_get_filename()

const char* stasis_app_stored_recording_get_filename ( struct stasis_app_stored_recording recording)

Returns the full filename, with extension, for this recording.

Since
14.0.0
Parameters
recordingRecording to query.
Returns
Absolute path to the recording file, with the extension.
NULL on error

Definition at line 62 of file stored.c.

References stasis_app_stored_recording::file_with_ext, and NULL.

Referenced by ast_ari_recordings_get_stored_file().

64 {
65  if (!recording) {
66  return NULL;
67  }
68  return recording->file_with_ext;
69 }
const ast_string_field file_with_ext
Definition: stored.c:41
#define NULL
Definition: resample.c:96

◆ stasis_app_stored_recording_to_json()

struct ast_json* stasis_app_stored_recording_to_json ( struct stasis_app_stored_recording recording)

Convert stored recording info to JSON.

Parameters
recordingRecording to convert.
Returns
JSON representation.
NULL on error.

Definition at line 446 of file stored.c.

References ast_json_pack(), stasis_app_stored_recording::file_with_ext, stasis_app_stored_recording::format, stasis_app_stored_recording::name, and NULL.

Referenced by ast_ari_recordings_copy_stored(), ast_ari_recordings_get_stored(), and ast_ari_recordings_list_stored().

446 {
447  /* Path was validated when the recording object was created */
448  return unlink(recording->file_with_ext);
449 }
450 
452  struct stasis_app_stored_recording *recording)
453 {
454  if (!recording) {
455  return NULL;
456  }
const ast_string_field file_with_ext
Definition: stored.c:41
#define NULL
Definition: resample.c:96
struct ast_json * stasis_app_stored_recording_to_json(struct stasis_app_stored_recording *recording)
Convert stored recording info to JSON.
Definition: stored.c:446
Abstract JSON element (object, array, string, int, ...).