Asterisk - The Open Source Telephony Project  18.5.0
Macros | Enumerations | Functions | Variables
res_monitor.c File Reference

PBX channel monitoring. More...

#include "asterisk.h"
#include <sys/stat.h>
#include <libgen.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/monitor.h"
#include "asterisk/app.h"
#include "asterisk/utils.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/beep.h"
Include dependency graph for res_monitor.c:

Go to the source code of this file.

Macros

#define AST_API_MODULE
 
#define LOCK_IF_NEEDED(lock, needed)
 
#define UNLOCK_IF_NEEDED(lock, needed)
 

Enumerations

enum  {
  MON_FLAG_BRIDGED = (1 << 0), MON_FLAG_MIX = (1 << 1), MON_FLAG_DROP_IN = (1 << 2), MON_FLAG_DROP_OUT = (1 << 3),
  MON_FLAG_BEEP = (1 << 4)
}
 
enum  { OPT_ARG_BEEP_INTERVAL, OPT_ARG_ARRAY_SIZE }
 
enum  MONITOR_PAUSING_ACTION { MONITOR_ACTION_PAUSE, MONITOR_ACTION_UNPAUSE }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
int AST_OPTIONAL_API_NAME() ast_monitor_change_fname (struct ast_channel *chan, const char *fname_base, int need_lock)
 Change monitored filename of channel. More...
 
int AST_OPTIONAL_API_NAME() ast_monitor_pause (struct ast_channel *chan)
 Pause monitoring of channel. More...
 
static int ast_monitor_set_state (struct ast_channel *chan, int state)
 Change state of monitored channel. More...
 
void AST_OPTIONAL_API_NAME() ast_monitor_setjoinfiles (struct ast_channel *chan, int turnon)
 
int AST_OPTIONAL_API_NAME() ast_monitor_start (struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock, int stream_action, const char *beep_id)
 Start monitoring a channel. More...
 
int AST_OPTIONAL_API_NAME() ast_monitor_stop (struct ast_channel *chan, int need_lock)
 Stop monitoring channel. More...
 
int AST_OPTIONAL_API_NAME() ast_monitor_unpause (struct ast_channel *chan)
 Unpause monitoring of channel. More...
 
static int change_monitor_action (struct mansession *s, const struct message *m)
 Change filename of a monitored channel by manager connection. More...
 
static int change_monitor_exec (struct ast_channel *chan, const char *data)
 Wrapper function. More...
 
static int do_pause_or_unpause (struct mansession *s, const struct message *m, int action)
 
static const char * get_soxmix_format (const char *format)
 Get audio format. More...
 
static int load_module (void)
 
static int pause_monitor_action (struct mansession *s, const struct message *m)
 
static int pause_monitor_exec (struct ast_channel *chan, const char *data)
 Wrapper for ast_monitor_pause. More...
 
static int start_monitor_action (struct mansession *s, const struct message *m)
 Start monitoring a channel by manager connection. More...
 
static int start_monitor_exec (struct ast_channel *chan, const char *data)
 Start monitor. More...
 
static int stop_monitor_action (struct mansession *s, const struct message *m)
 Stop monitoring a channel by manager connection. More...
 
static int stop_monitor_exec (struct ast_channel *chan, const char *data)
 Wrapper function. More...
 
static int unload_module (void)
 
static int unpause_monitor_action (struct mansession *s, const struct message *m)
 
static int unpause_monitor_exec (struct ast_channel *chan, const char *data)
 Wrapper for ast_monitor_unpause. More...
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Call Monitoring Resource" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_DEPRECATED, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, .optional_modules = "func_periodic_hook", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const struct ast_app_option monitor_opts [128] = { [ 'b' ] = { .flag = MON_FLAG_BRIDGED }, [ 'm' ] = { .flag = MON_FLAG_MIX }, [ 'i' ] = { .flag = MON_FLAG_DROP_IN }, [ 'o' ] = { .flag = MON_FLAG_DROP_OUT }, [ 'B' ] = { .flag = MON_FLAG_BEEP , .arg_index = OPT_ARG_BEEP_INTERVAL + 1 }, }
 
static ast_mutex_t monitorlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static unsigned long seq = 0
 

Detailed Description

PBX channel monitoring.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file res_monitor.c.

Macro Definition Documentation

◆ AST_API_MODULE

#define AST_API_MODULE

Definition at line 47 of file res_monitor.c.

◆ LOCK_IF_NEEDED

#define LOCK_IF_NEEDED (   lock,
  needed 
)
Value:
do { \
if (needed) \
ast_channel_lock(lock); \
} while(0)
ast_mutex_t lock
Definition: app_meetme.c:1091

Definition at line 263 of file res_monitor.c.

Referenced by ast_monitor_change_fname(), ast_monitor_set_state(), ast_monitor_start(), and ast_monitor_stop().

◆ UNLOCK_IF_NEEDED

#define UNLOCK_IF_NEEDED (   lock,
  needed 
)
Value:
do { \
if (needed) \
ast_channel_unlock(lock); \
} while (0)
ast_mutex_t lock
Definition: app_meetme.c:1091

Definition at line 268 of file res_monitor.c.

Referenced by ast_monitor_change_fname(), ast_monitor_set_state(), ast_monitor_start(), and ast_monitor_stop().

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
MON_FLAG_BRIDGED 
MON_FLAG_MIX 
MON_FLAG_DROP_IN 
MON_FLAG_DROP_OUT 
MON_FLAG_BEEP 

Definition at line 665 of file res_monitor.c.

665  {
666  MON_FLAG_BRIDGED = (1 << 0),
667  MON_FLAG_MIX = (1 << 1),
668  MON_FLAG_DROP_IN = (1 << 2),
669  MON_FLAG_DROP_OUT = (1 << 3),
670  MON_FLAG_BEEP = (1 << 4),
671 };

◆ anonymous enum

anonymous enum
Enumerator
OPT_ARG_BEEP_INTERVAL 
OPT_ARG_ARRAY_SIZE 

Definition at line 673 of file res_monitor.c.

673  {
675  OPT_ARG_ARRAY_SIZE, /* Always last element of the enum */
676 };

◆ MONITOR_PAUSING_ACTION

Enumerator
MONITOR_ACTION_PAUSE 
MONITOR_ACTION_UNPAUSE 

Definition at line 932 of file res_monitor.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1015 of file res_monitor.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1015 of file res_monitor.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1015 of file res_monitor.c.

◆ ast_monitor_change_fname()

int AST_OPTIONAL_API_NAME() ast_monitor_change_fname ( struct ast_channel chan,
const char *  fname_base,
int  need_lock 
)

Change monitored filename of channel.

Parameters
chan
fname_basenew filename
need_lock
Return values
0on success.
-1on failure.
Note
We cannot just compare filenames, due to symlinks, relative paths, and other possible filesystem issues. We could use realpath(3), but its use is discouraged. However, if we try to create the same file from two different paths, the second will fail, and so we have our notification that the filenames point to the same path.

Remember, also, that we're using the basename of the file (i.e. the file without the format suffix), so it does not already exist and we aren't interfering with the recording itself.

Definition at line 590 of file res_monitor.c.

References ast_channel_monitor(), ast_channel_name(), ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_debug, ast_log, ast_mkdir(), ast_strdupa, ast_strlen_zero, doexit, errno, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, LOCK_IF_NEEDED, LOG_ERROR, LOG_WARNING, name, and UNLOCK_IF_NEEDED.

Referenced by __stub__ast_monitor_stop(), change_monitor_action(), change_monitor_exec(), start_monitor_action(), and start_monitor_exec().

591 {
592  if (ast_strlen_zero(fname_base)) {
593  ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", ast_channel_name(chan));
594  return -1;
595  }
596 
597  LOCK_IF_NEEDED(chan, need_lock);
598 
599  if (ast_channel_monitor(chan)) {
600  int directory = strchr(fname_base, '/') ? 1 : 0;
601  const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR;
602  const char *absolute_suffix = *fname_base == '/' ? "" : "/";
603  char tmpstring[sizeof(ast_channel_monitor(chan)->filename_base)] = "";
604  int i, fd[2] = { -1, -1 }, doexit = 0;
605 
606  /* before continuing, see if we're trying to rename the file to itself... */
607  snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", absolute, absolute_suffix, fname_base);
608 
609  /* try creating the directory just in case it doesn't exist */
610  if (directory) {
611  char *name = ast_strdupa(tmpstring);
612  ast_mkdir(dirname(name), 0777);
613  }
614 
615  /*!
616  * \note We cannot just compare filenames, due to symlinks, relative
617  * paths, and other possible filesystem issues. We could use
618  * realpath(3), but its use is discouraged. However, if we try to
619  * create the same file from two different paths, the second will
620  * fail, and so we have our notification that the filenames point to
621  * the same path.
622  *
623  * Remember, also, that we're using the basename of the file (i.e.
624  * the file without the format suffix), so it does not already exist
625  * and we aren't interfering with the recording itself.
626  */
627  ast_debug(2, "comparing tmpstring %s to filename_base %s\n", tmpstring, ast_channel_monitor(chan)->filename_base);
628 
629  if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 ||
630  (fd[1] = open(ast_channel_monitor(chan)->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) {
631  if (fd[0] < 0) {
632  ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno));
633  } else {
634  ast_debug(2, "No need to rename monitor filename to itself\n");
635  }
636  doexit = 1;
637  }
638 
639  /* Cleanup temporary files */
640  for (i = 0; i < 2; i++) {
641  if (fd[i] >= 0) {
642  while (close(fd[i]) < 0 && errno == EINTR);
643  }
644  }
645  unlink(tmpstring);
646  /* if previous monitor file existed in a subdirectory, the directory will not be removed */
647  unlink(ast_channel_monitor(chan)->filename_base);
648 
649  if (doexit) {
650  UNLOCK_IF_NEEDED(chan, need_lock);
651  return 0;
652  }
653 
654  ast_copy_string(ast_channel_monitor(chan)->filename_base, tmpstring, sizeof(ast_channel_monitor(chan)->filename_base));
656  } else {
657  ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", ast_channel_name(chan), fname_base);
658  }
659 
660  UNLOCK_IF_NEEDED(chan, need_lock);
661 
662  return 0;
663 }
#define UNLOCK_IF_NEEDED(lock, needed)
Definition: res_monitor.c:268
#define LOG_WARNING
Definition: logger.h:274
char filename_base[FILENAME_MAX]
Definition: channel.h:4244
#define LOCK_IF_NEEDED(lock, needed)
Definition: res_monitor.c:263
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define LOG_ERROR
Definition: logger.h:285
int errno
static const char name[]
Definition: cdr_mysql.c:74
const char * ast_config_AST_MONITOR_DIR
Definition: options.c:155
static int doexit
Definition: main/db.c:112
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_channel_monitor * ast_channel_monitor(const struct ast_channel *chan)
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: main/utils.c:2231

◆ ast_monitor_pause()

int AST_OPTIONAL_API_NAME() ast_monitor_pause ( struct ast_channel chan)

Pause monitoring of channel.

Definition at line 559 of file res_monitor.c.

References AST_MONITOR_PAUSED, and ast_monitor_set_state().

Referenced by __stub__ast_monitor_setjoinfiles(), do_pause_or_unpause(), and pause_monitor_exec().

560 {
562 }
static int ast_monitor_set_state(struct ast_channel *chan, int state)
Change state of monitored channel.
Definition: res_monitor.c:282

◆ ast_monitor_set_state()

static int ast_monitor_set_state ( struct ast_channel chan,
int  state 
)
static

Change state of monitored channel.

Parameters
chan
statemonitor state
Return values
0on success.
-1on failure.

Definition at line 282 of file res_monitor.c.

References ast_channel_monitor(), LOCK_IF_NEEDED, state, ast_channel_monitor::state, and UNLOCK_IF_NEEDED.

Referenced by ast_monitor_pause(), ast_monitor_start(), and ast_monitor_unpause().

283 {
284  LOCK_IF_NEEDED(chan, 1);
285  if (!ast_channel_monitor(chan)) {
286  UNLOCK_IF_NEEDED(chan, 1);
287  return -1;
288  }
290  UNLOCK_IF_NEEDED(chan, 1);
291  return 0;
292 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
#define UNLOCK_IF_NEEDED(lock, needed)
Definition: res_monitor.c:268
#define LOCK_IF_NEEDED(lock, needed)
Definition: res_monitor.c:263
enum AST_MONITORING_STATE state
Definition: channel.h:4249
struct ast_channel_monitor * ast_channel_monitor(const struct ast_channel *chan)

◆ ast_monitor_setjoinfiles()

void AST_OPTIONAL_API_NAME() ast_monitor_setjoinfiles ( struct ast_channel chan,
int  turnon 
)

Definition at line 926 of file res_monitor.c.

References ast_channel_monitor(), and ast_channel_monitor::joinfiles.

Referenced by __stub__ast_monitor_change_fname(), start_automonitor(), start_monitor_action(), start_monitor_exec(), and try_calling().

927 {
928  if (ast_channel_monitor(chan))
929  ast_channel_monitor(chan)->joinfiles = turnon;
930 }
struct ast_channel_monitor * ast_channel_monitor(const struct ast_channel *chan)

◆ ast_monitor_start()

int AST_OPTIONAL_API_NAME() ast_monitor_start ( struct ast_channel chan,
const char *  format_spec,
const char *  fname_base,
int  need_lock,
int  stream_action,
const char *  beep_id 
)

Start monitoring a channel.

Parameters
chanast_channel struct to record
format_specfile format to use for recording
fname_basefilename base to record to
need_lockwhether to lock the channel mutex
stream_actionwhether to record the input and/or output streams. X_REC_IN | X_REC_OUT is most often used Creates the file to record, if no format is specified it assumes WAV It also sets channel variable __MONITORED=yes
Return values
0on success
-1on failure

Definition at line 305 of file res_monitor.c.

References ao2_cleanup, ast_calloc, ast_channel_blob_create_from_cache(), ast_channel_insmpl_set(), ast_channel_monitor(), ast_channel_monitor_set(), ast_channel_monitor_start_type(), ast_channel_name(), ast_channel_outsmpl_set(), ast_channel_topic(), ast_channel_uniqueid(), ast_closestream(), ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_debug, AST_FILE_MODE, ast_filedelete(), ast_fileexists(), ast_free, ast_log, ast_mkdir(), AST_MONITOR_RUNNING, ast_monitor_set_state(), ast_monitor_stop(), ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_strdupa, ast_strlen_zero, ast_writefile(), ast_channel_monitor::beep_id, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, FILENAME_MAX, ast_channel_monitor::format, LOCK_IF_NEEDED, LOG_WARNING, monitor, monitorlock, name, NULL, pbx_builtin_setvar_helper(), RAII_VAR, ast_channel_monitor::read_filename, ast_channel_monitor::read_stream, seq, stasis_publish(), ast_channel_monitor::stop, UNLOCK_IF_NEEDED, ast_channel_monitor::write_filename, ast_channel_monitor::write_stream, X_REC_IN, and X_REC_OUT.

Referenced by start_automonitor(), start_monitor_action(), start_monitor_exec(), and try_calling().

308 {
309  int res = 0;
311 
312  LOCK_IF_NEEDED(chan, need_lock);
313 
314  if (!(ast_channel_monitor(chan))) {
316  char *channel_name, *p;
317 
318  /* Create monitoring directory if needed */
320 
321  if (!(monitor = ast_calloc(1, sizeof(*monitor)))) {
322  UNLOCK_IF_NEEDED(chan, need_lock);
323  return -1;
324  }
325 
326  if (!ast_strlen_zero(beep_id)) {
327  ast_copy_string(monitor->beep_id, beep_id, sizeof(monitor->beep_id));
328  }
329 
330  /* Determine file names */
331  if (!ast_strlen_zero(fname_base)) {
332  int directory = strchr(fname_base, '/') ? 1 : 0;
333  const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR;
334  const char *absolute_suffix = *fname_base == '/' ? "" : "/";
335 
336  snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in",
337  absolute, absolute_suffix, fname_base);
338  snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out",
339  absolute, absolute_suffix, fname_base);
340  snprintf(monitor->filename_base, FILENAME_MAX, "%s%s%s",
341  absolute, absolute_suffix, fname_base);
342 
343  /* try creating the directory just in case it doesn't exist */
344  if (directory) {
345  char *name = ast_strdupa(monitor->filename_base);
346  ast_mkdir(dirname(name), 0777);
347  }
348  } else {
350  snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%lu",
352  snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%lu",
354  seq++;
356 
357  /* Replace all '/' chars from the channel name with '-' chars. */
358  channel_name = ast_strdupa(ast_channel_name(chan));
359  for (p = channel_name; (p = strchr(p, '/')); ) {
360  *p = '-';
361  }
362 
363  snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s",
364  ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name);
365  monitor->filename_changed = 1;
366  }
367 
368  monitor->stop = ast_monitor_stop;
369 
370  /* Determine file format */
371  if (!ast_strlen_zero(format_spec)) {
372  monitor->format = ast_strdup(format_spec);
373  } else {
374  monitor->format = ast_strdup("wav");
375  }
376 
377  /* open files */
378  if (stream_action & X_REC_IN) {
379  if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0)
380  ast_filedelete(monitor->read_filename, NULL);
381  if (!(monitor->read_stream = ast_writefile(monitor->read_filename,
382  monitor->format, NULL,
383  O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {
384  ast_log(LOG_WARNING, "Could not create file %s\n",
385  monitor->read_filename);
386  ast_free(monitor);
387  UNLOCK_IF_NEEDED(chan, need_lock);
388  return -1;
389  }
390  } else
391  monitor->read_stream = NULL;
392 
393  if (stream_action & X_REC_OUT) {
394  if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) {
396  }
397  if (!(monitor->write_stream = ast_writefile(monitor->write_filename,
398  monitor->format, NULL,
399  O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {
400  ast_log(LOG_WARNING, "Could not create file %s\n",
401  monitor->write_filename);
402  if (monitor->read_stream) {
403  ast_closestream(monitor->read_stream);
404  }
405  ast_free(monitor);
406  UNLOCK_IF_NEEDED(chan, need_lock);
407  return -1;
408  }
409  } else
410  monitor->write_stream = NULL;
411 
412  ast_channel_insmpl_set(chan, 0);
413  ast_channel_outsmpl_set(chan, 0);
414  ast_channel_monitor_set(chan, monitor);
416  /* so we know this call has been monitored in case we need to bill for it or something */
417  pbx_builtin_setvar_helper(chan, "__MONITORED","true");
418 
421  NULL);
422  if (message) {
424  }
425  } else {
426  ast_debug(1,"Cannot start monitoring %s, already monitored\n", ast_channel_name(chan));
427  res = -1;
428  }
429 
430  UNLOCK_IF_NEEDED(chan, need_lock);
431 
432  return res;
433 }
#define FILENAME_MAX
#define X_REC_IN
Definition: monitor.h:30
char read_filename[FILENAME_MAX]
Definition: channel.h:4242
static int ast_monitor_set_state(struct ast_channel *chan, int state)
Change state of monitored channel.
Definition: res_monitor.c:282
void ast_channel_insmpl_set(struct ast_channel *chan, unsigned long value)
int(* stop)(struct ast_channel *chan, int need_lock)
Definition: channel.h:4250
#define UNLOCK_IF_NEEDED(lock, needed)
Definition: res_monitor.c:268
#define LOG_WARNING
Definition: logger.h:274
static ast_mutex_t monitorlock
Definition: res_monitor.c:261
char filename_base[FILENAME_MAX]
Definition: channel.h:4244
#define LOCK_IF_NEEDED(lock, needed)
Definition: res_monitor.c:263
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
struct stasis_message_type * ast_channel_monitor_start_type(void)
Message type for starting monitor on a channel.
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:1098
char write_filename[FILENAME_MAX]
Definition: channel.h:4243
#define AST_FILE_MODE
Definition: asterisk.h:32
#define X_REC_OUT
Definition: monitor.h:31
#define ast_strlen_zero(foo)
Definition: strings.h:52
#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
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
static unsigned int monitor
Definition: chan_phone.c:116
struct ast_filestream * ast_writefile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
Starts writing a file.
Definition: file.c:1361
struct ast_filestream * read_stream
Definition: channel.h:4240
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
const char * ast_config_AST_MONITOR_DIR
Definition: options.c:155
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct ast_filestream * write_stream
Definition: channel.h:4241
int ast_closestream(struct ast_filestream *f)
Closes a stream.
Definition: file.c:1068
struct stasis_message * ast_channel_blob_create_from_cache(const char *uniqueid, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
int AST_OPTIONAL_API_NAME() ast_monitor_stop(struct ast_channel *chan, int need_lock)
Stop monitoring channel.
Definition: res_monitor.c:461
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
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 unsigned long seq
Definition: res_monitor.c:273
struct ast_channel_monitor * ast_channel_monitor(const struct ast_channel *chan)
void ast_channel_outsmpl_set(struct ast_channel *chan, unsigned long value)
char beep_id[64]
Definition: channel.h:4245
void ast_channel_monitor_set(struct ast_channel *chan, struct ast_channel_monitor *value)
#define ast_mutex_unlock(a)
Definition: lock.h:188
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: main/utils.c:2231

◆ ast_monitor_stop()

int AST_OPTIONAL_API_NAME() ast_monitor_stop ( struct ast_channel chan,
int  need_lock 
)

Stop monitoring channel.

Parameters
chan
need_lockStop the recording, close any open streams, mix in/out channels if required
Returns
Always 0

Definition at line 461 of file res_monitor.c.

References ao2_cleanup, ast_beep_stop(), ast_channel_blob_create_from_cache(), ast_channel_monitor(), ast_channel_monitor_set(), ast_channel_monitor_stop_type(), ast_channel_topic(), ast_channel_uniqueid(), ast_closestream(), ast_debug, ast_filedelete(), ast_fileexists(), ast_filerename(), ast_free, ast_log, ast_safe_system(), ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_strlen_zero, execute(), ast_channel_monitor::filename_base, format, ast_channel_monitor::format, get_soxmix_format(), LOCK_IF_NEEDED, LOG_WARNING, NULL, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), RAII_VAR, stasis_publish(), tmp(), UNLOCK_IF_NEEDED, and write_stream().

Referenced by __stub__ast_monitor_start(), ast_monitor_start(), stop_monitor_action(), and stop_monitor_exec().

462 {
463  int delfiles = 0;
465 
466  LOCK_IF_NEEDED(chan, need_lock);
467 
468  if (ast_channel_monitor(chan)) {
469  RAII_VAR(struct ast_str *, tmp, ast_str_create(1024), ast_free);
470 
471  if (ast_channel_monitor(chan)->read_stream) {
473  }
474  if (ast_channel_monitor(chan)->write_stream) {
476  }
477 
480  ast_str_set(&tmp, 0, "%s-in", ast_channel_monitor(chan)->filename_base);
481  if (ast_fileexists(ast_str_buffer(tmp), NULL, NULL) > 0) {
483  }
485  } else {
486  ast_log(LOG_WARNING, "File %s not found\n", ast_channel_monitor(chan)->read_filename);
487  }
488 
490  ast_str_set(&tmp, 0, "%s-out", ast_channel_monitor(chan)->filename_base);
491  if (ast_fileexists(ast_str_buffer(tmp), NULL, NULL) > 0) {
493  }
495  } else {
496  ast_log(LOG_WARNING, "File %s not found\n", ast_channel_monitor(chan)->write_filename);
497  }
498  }
499 
501  const char *format = !strcasecmp(ast_channel_monitor(chan)->format,"wav49") ? "WAV" : ast_channel_monitor(chan)->format;
502  char *fname_base = ast_channel_monitor(chan)->filename_base;
503  const char *execute, *execute_args;
504  /* at this point, fname_base really is the full path */
505 
506  /* Set the execute application */
507  execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC");
508  if (ast_strlen_zero(execute)) {
509 #ifdef HAVE_SOXMIX
510  execute = "nice -n 19 soxmix";
511 #else
512  execute = "nice -n 19 sox -m";
513 #endif
514  format = get_soxmix_format(format);
515  delfiles = 1;
516  }
517  execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");
518  if (ast_strlen_zero(execute_args)) {
519  execute_args = "";
520  }
521 
522  ast_str_set(&tmp, 0, delfiles ? "( " : "");
523  ast_str_append(&tmp, 0, "%s \"%s-in.%s\" \"%s-out.%s\" \"%s.%s\" %s &",
524  execute, fname_base, format, fname_base, format, fname_base, format,execute_args);
525  if (delfiles) {
526  /* remove legs when done mixing */
527  ast_str_append(&tmp, 0, "& rm -f \"%s-\"* ) &", fname_base);
528  }
529  ast_debug(1,"monitor executing %s\n", ast_str_buffer(tmp));
530  if (ast_safe_system(ast_str_buffer(tmp)) == -1)
531  ast_log(LOG_WARNING, "Execute of %s failed.\n", ast_str_buffer(tmp));
532  }
533 
536  }
537 
538  ast_free(ast_channel_monitor(chan)->format);
541 
544  NULL);
545  if (message) {
547  }
548  pbx_builtin_setvar_helper(chan, "MONITORED", NULL);
549  }
550  pbx_builtin_setvar_helper(chan, "AUTO_MONITOR", NULL);
551 
552  UNLOCK_IF_NEEDED(chan, need_lock);
553 
554  return 0;
555 }
char read_filename[FILENAME_MAX]
Definition: channel.h:4242
static SQLHSTMT execute(struct odbc_obj *obj, void *data, int silent)
Common execution function for SQL queries.
Definition: func_odbc.c:454
#define UNLOCK_IF_NEEDED(lock, needed)
Definition: res_monitor.c:268
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static int tmp()
Definition: bt_open.c:389
char filename_base[FILENAME_MAX]
Definition: channel.h:4244
static void write_stream(struct ogg_vorbis_desc *s, FILE *f)
Write out any pending encoded data.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
int AST_OPTIONAL_API_NAME() ast_beep_stop(struct ast_channel *chan, const char *beep_id)
#define LOCK_IF_NEEDED(lock, needed)
Definition: res_monitor.c:263
#define NULL
Definition: resample.c:96
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:1098
char write_filename[FILENAME_MAX]
Definition: channel.h:4243
static const char * get_soxmix_format(const char *format)
Get audio format.
Definition: res_monitor.c:442
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#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
struct stasis_message_type * ast_channel_monitor_stop_type(void)
Message type for stopping monitor on a channel.
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
struct ast_filestream * read_stream
Definition: channel.h:4240
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
#define ast_free(a)
Definition: astmm.h:182
int ast_closestream(struct ast_filestream *f)
Closes a stream.
Definition: file.c:1068
struct stasis_message * ast_channel_blob_create_from_cache(const char *uniqueid, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1086
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
Definition: file.c:1103
struct ast_channel_monitor * ast_channel_monitor(const struct ast_channel *chan)
static snd_pcm_format_t format
Definition: chan_alsa.c:102
char beep_id[64]
Definition: channel.h:4245
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
void ast_channel_monitor_set(struct ast_channel *chan, struct ast_channel_monitor *value)

◆ ast_monitor_unpause()

int AST_OPTIONAL_API_NAME() ast_monitor_unpause ( struct ast_channel chan)

Unpause monitoring of channel.

Definition at line 565 of file res_monitor.c.

References AST_MONITOR_RUNNING, and ast_monitor_set_state().

Referenced by __stub__ast_monitor_pause(), do_pause_or_unpause(), and unpause_monitor_exec().

566 {
568 }
static int ast_monitor_set_state(struct ast_channel *chan, int state)
Change state of monitored channel.
Definition: res_monitor.c:282

◆ change_monitor_action()

static int change_monitor_action ( struct mansession s,
const struct message m 
)
static

Change filename of a monitored channel by manager connection.

Definition at line 892 of file res_monitor.c.

References AMI_SUCCESS, ast_channel_get_by_name(), ast_channel_unref, ast_monitor_change_fname(), ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), c, name, and NULL.

Referenced by load_module().

893 {
894  struct ast_channel *c = NULL;
895  const char *name = astman_get_header(m, "Channel");
896  const char *fname = astman_get_header(m, "File");
897 
898  if (ast_strlen_zero(name)) {
899  astman_send_error(s, m, "No channel specified");
900  return AMI_SUCCESS;
901  }
902 
903  if (ast_strlen_zero(fname)) {
904  astman_send_error(s, m, "No filename specified");
905  return AMI_SUCCESS;
906  }
907 
908  if (!(c = ast_channel_get_by_name(name))) {
909  astman_send_error(s, m, "No such channel");
910  return AMI_SUCCESS;
911  }
912 
913  if (ast_monitor_change_fname(c, fname, 1)) {
914  c = ast_channel_unref(c);
915  astman_send_error(s, m, "Could not change monitored filename of channel");
916  return AMI_SUCCESS;
917  }
918 
919  c = ast_channel_unref(c);
920 
921  astman_send_ack(s, m, "Changed monitor filename");
922 
923  return AMI_SUCCESS;
924 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
static struct test_val c
#define NULL
Definition: resample.c:96
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
int AST_OPTIONAL_API_NAME() ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, int need_lock)
Change monitored filename of channel.
Definition: res_monitor.c:590
static const char name[]
Definition: cdr_mysql.c:74
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
#define AMI_SUCCESS
Definition: manager.h:65

◆ change_monitor_exec()

static int change_monitor_exec ( struct ast_channel chan,
const char *  data 
)
static

Wrapper function.

See also
ast_monitor_change_fname

Definition at line 802 of file res_monitor.c.

References ast_monitor_change_fname().

Referenced by load_module().

803 {
804  return ast_monitor_change_fname(chan, data, 1);
805 }
const char * data
int AST_OPTIONAL_API_NAME() ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, int need_lock)
Change monitored filename of channel.
Definition: res_monitor.c:590

◆ do_pause_or_unpause()

static int do_pause_or_unpause ( struct mansession s,
const struct message m,
int  action 
)
static

Definition at line 938 of file res_monitor.c.

References AMI_SUCCESS, ast_channel_get_by_name(), ast_channel_unref, ast_monitor_pause(), ast_monitor_unpause(), ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), c, MONITOR_ACTION_PAUSE, name, and NULL.

Referenced by pause_monitor_action(), and unpause_monitor_action().

939 {
940  struct ast_channel *c = NULL;
941  const char *name = astman_get_header(m, "Channel");
942 
943  if (ast_strlen_zero(name)) {
944  astman_send_error(s, m, "No channel specified");
945  return AMI_SUCCESS;
946  }
947 
948  if (!(c = ast_channel_get_by_name(name))) {
949  astman_send_error(s, m, "No such channel");
950  return AMI_SUCCESS;
951  }
952 
953  if (action == MONITOR_ACTION_PAUSE) {
955  } else {
957  }
958 
959  c = ast_channel_unref(c);
960 
961  astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel"));
962 
963  return AMI_SUCCESS;
964 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
static struct test_val c
#define NULL
Definition: resample.c:96
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
static const char name[]
Definition: cdr_mysql.c:74
int AST_OPTIONAL_API_NAME() ast_monitor_unpause(struct ast_channel *chan)
Unpause monitoring of channel.
Definition: res_monitor.c:565
int AST_OPTIONAL_API_NAME() ast_monitor_pause(struct ast_channel *chan)
Pause monitoring of channel.
Definition: res_monitor.c:559
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
#define AMI_SUCCESS
Definition: manager.h:65

◆ get_soxmix_format()

static const char* get_soxmix_format ( const char *  format)
static

Get audio format.

Parameters
formatrecording format. The file format extensions that Asterisk uses are not all the same as that which soxmix expects. This function ensures that the format used as the extension on the filename is something soxmix will understand.

Definition at line 442 of file res_monitor.c.

References format.

Referenced by ast_monitor_stop().

443 {
444  const char *res = format;
445 
446  if (!strcasecmp(format,"ulaw"))
447  res = "ul";
448  if (!strcasecmp(format,"alaw"))
449  res = "al";
450 
451  return res;
452 }
static snd_pcm_format_t format
Definition: chan_alsa.c:102

◆ load_module()

static int load_module ( void  )
static

Definition at line 976 of file res_monitor.c.

References ast_manager_register_xml, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, change_monitor_action(), change_monitor_exec(), EVENT_FLAG_CALL, pause_monitor_action(), pause_monitor_exec(), start_monitor_action(), start_monitor_exec(), stop_monitor_action(), stop_monitor_exec(), unpause_monitor_action(), and unpause_monitor_exec().

Referenced by unload_module().

977 {
988 
990 }
static int unpause_monitor_exec(struct ast_channel *chan, const char *data)
Wrapper for ast_monitor_unpause.
Definition: res_monitor.c:577
static int change_monitor_exec(struct ast_channel *chan, const char *data)
Wrapper function.
Definition: res_monitor.c:802
static int start_monitor_action(struct mansession *s, const struct message *m)
Start monitoring a channel by manager connection.
Definition: res_monitor.c:808
static int pause_monitor_action(struct mansession *s, const struct message *m)
Definition: res_monitor.c:966
#define EVENT_FLAG_CALL
Definition: manager.h:72
static int unpause_monitor_action(struct mansession *s, const struct message *m)
Definition: res_monitor.c:971
static int stop_monitor_action(struct mansession *s, const struct message *m)
Stop monitoring a channel by manager connection.
Definition: res_monitor.c:861
static int change_monitor_action(struct mansession *s, const struct message *m)
Change filename of a monitored channel by manager connection.
Definition: res_monitor.c:892
static int stop_monitor_exec(struct ast_channel *chan, const char *data)
Wrapper function.
Definition: res_monitor.c:796
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
static int start_monitor_exec(struct ast_channel *chan, const char *data)
Start monitor.
Definition: res_monitor.c:693
static int pause_monitor_exec(struct ast_channel *chan, const char *data)
Wrapper for ast_monitor_pause.
Definition: res_monitor.c:571
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ pause_monitor_action()

static int pause_monitor_action ( struct mansession s,
const struct message m 
)
static

Definition at line 966 of file res_monitor.c.

References do_pause_or_unpause(), and MONITOR_ACTION_PAUSE.

Referenced by load_module().

967 {
969 }
static int do_pause_or_unpause(struct mansession *s, const struct message *m, int action)
Definition: res_monitor.c:938

◆ pause_monitor_exec()

static int pause_monitor_exec ( struct ast_channel chan,
const char *  data 
)
static

Wrapper for ast_monitor_pause.

Definition at line 571 of file res_monitor.c.

References ast_monitor_pause().

Referenced by load_module().

572 {
573  return ast_monitor_pause(chan);
574 }
int AST_OPTIONAL_API_NAME() ast_monitor_pause(struct ast_channel *chan)
Pause monitoring of channel.
Definition: res_monitor.c:559

◆ start_monitor_action()

static int start_monitor_action ( struct mansession s,
const struct message m 
)
static

Start monitoring a channel by manager connection.

Definition at line 808 of file res_monitor.c.

References AMI_SUCCESS, ast_channel_get_by_name(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_monitor_change_fname(), ast_monitor_setjoinfiles(), ast_monitor_start(), ast_strdupa, ast_strlen_zero, ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), c, d, format, name, NULL, X_REC_IN, and X_REC_OUT.

Referenced by load_module().

809 {
810  struct ast_channel *c = NULL;
811  const char *name = astman_get_header(m, "Channel");
812  const char *fname = astman_get_header(m, "File");
813  const char *format = astman_get_header(m, "Format");
814  const char *mix = astman_get_header(m, "Mix");
815  char *d;
816 
817  if (ast_strlen_zero(name)) {
818  astman_send_error(s, m, "No channel specified");
819  return AMI_SUCCESS;
820  }
821 
822  if (!(c = ast_channel_get_by_name(name))) {
823  astman_send_error(s, m, "No such channel");
824  return AMI_SUCCESS;
825  }
826 
827  if (ast_strlen_zero(fname)) {
828  /* No filename specified, default to the channel name. */
829  ast_channel_lock(c);
830  fname = ast_strdupa(ast_channel_name(c));
832 
833  /* Replace all '/' chars from the channel name with '-' chars. */
834  for (d = (char *) fname; (d = strchr(d, '/')); ) {
835  *d = '-';
836  }
837  }
838 
839  if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT, NULL)) {
840  if (ast_monitor_change_fname(c, fname, 1)) {
841  astman_send_error(s, m, "Could not start monitoring channel");
842  c = ast_channel_unref(c);
843  return AMI_SUCCESS;
844  }
845  }
846 
847  if (ast_true(mix)) {
848  ast_channel_lock(c);
851  }
852 
853  c = ast_channel_unref(c);
854 
855  astman_send_ack(s, m, "Started monitoring channel");
856 
857  return AMI_SUCCESS;
858 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define X_REC_IN
Definition: monitor.h:30
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
static struct test_val d
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
static struct test_val c
#define NULL
Definition: resample.c:96
#define X_REC_OUT
Definition: monitor.h:31
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
int AST_OPTIONAL_API_NAME() ast_monitor_start(struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock, int stream_action, const char *beep_id)
Start monitoring a channel.
Definition: res_monitor.c:305
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
int AST_OPTIONAL_API_NAME() ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, int need_lock)
Change monitored filename of channel.
Definition: res_monitor.c:590
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static const char name[]
Definition: cdr_mysql.c:74
void AST_OPTIONAL_API_NAME() ast_monitor_setjoinfiles(struct ast_channel *chan, int turnon)
Definition: res_monitor.c:926
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#define AMI_SUCCESS
Definition: manager.h:65

◆ start_monitor_exec()

static int start_monitor_exec ( struct ast_channel chan,
const char *  data 
)
static

Start monitor.

Parameters
chan
dataarguments passed fname|options
Return values
0on success.
-1on failure.

Definition at line 693 of file res_monitor.c.

References args, AST_APP_ARG, ast_app_parse_options(), ast_beep_start(), ast_cdr_setuserfield(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, AST_DECLARE_APP_ARGS, ast_log, ast_monitor_change_fname(), ast_monitor_setjoinfiles(), ast_monitor_start(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, ast_test_flag, format, LOG_ERROR, LOG_WARNING, MON_FLAG_BEEP, MON_FLAG_BRIDGED, MON_FLAG_DROP_IN, MON_FLAG_DROP_OUT, MON_FLAG_MIX, monitor_opts, NULL, OPT_ARG_ARRAY_SIZE, OPT_ARG_BEEP_INTERVAL, options, parse(), pbx_builtin_setvar_helper(), S_OR, tmp(), X_JOIN, X_REC_IN, and X_REC_OUT.

Referenced by load_module().

694 {
695  char *arg;
696  char *options;
697  char *delay;
698  char *urlprefix = NULL;
699  char tmp[256];
700  int stream_action = X_REC_IN | X_REC_OUT;
701  int joinfiles = 0;
702  int res = 0;
703  char *parse;
704  struct ast_flags flags = { 0 };
705  char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
706  char beep_id[64] = "";
709  AST_APP_ARG(fname_base);
710  AST_APP_ARG(options);
711  );
712 
713  /* Parse arguments. */
714  if (ast_strlen_zero(data)) {
715  ast_log(LOG_ERROR, "Monitor requires an argument\n");
716  return 0;
717  }
718 
719  parse = ast_strdupa(data);
720  AST_STANDARD_APP_ARGS(args, parse);
721 
722  if (!ast_strlen_zero(args.options)) {
723  ast_app_parse_options(monitor_opts, &flags, opts, args.options);
724 
725  if (ast_test_flag(&flags, MON_FLAG_MIX)) {
726  stream_action |= X_JOIN;
727  }
728  if (ast_test_flag(&flags, MON_FLAG_DROP_IN)) {
729  stream_action &= ~X_REC_IN;
730  }
731  if (ast_test_flag(&flags, MON_FLAG_DROP_OUT)) {
732  stream_action &= ~X_REC_OUT;
733  }
734  if (ast_test_flag(&flags, MON_FLAG_BEEP)) {
735  const char *interval_str = S_OR(opts[OPT_ARG_BEEP_INTERVAL], "15");
736  unsigned int interval = 15;
737 
738  if (sscanf(interval_str, "%30u", &interval) != 1) {
739  ast_log(LOG_WARNING, "Invalid interval '%s' for periodic beep. Using default of %u\n",
740  interval_str, interval);
741  }
742 
743  if (ast_beep_start(chan, interval, beep_id, sizeof(beep_id))) {
744  ast_log(LOG_WARNING, "Unable to enable periodic beep, please ensure func_periodic_hook is loaded.\n");
745  return -1;
746  }
747  }
748  }
749 
750  arg = strchr(args.format, ':');
751  if (arg) {
752  *arg++ = 0;
753  urlprefix = arg;
754  }
755 
756  if (!ast_strlen_zero(urlprefix) && !ast_strlen_zero(args.fname_base)) {
757  snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base,
758  ((strcmp(args.format, "gsm")) ? "wav" : "gsm"));
759  ast_channel_lock(chan);
761  ast_channel_unlock(chan);
762  }
763  if (ast_test_flag(&flags, MON_FLAG_BRIDGED)) {
764  /* We must remove the "b" option if listed. In principle none of
765  the following could give NULL results, but we check just to
766  be pedantic. Reconstructing with checks for 'm' option does not
767  work if we end up adding more options than 'm' in the future. */
768  delay = ast_strdupa(data);
769  options = strrchr(delay, ',');
770  if (options) {
771  arg = strchr(options, 'b');
772  if (arg) {
773  *arg = 'X';
774  pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay);
775  }
776  }
777  return 0;
778  }
779 
780  res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action, beep_id);
781  if (res < 0)
782  res = ast_monitor_change_fname(chan, args.fname_base, 1);
783 
784  if (stream_action & X_JOIN) {
785  if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT))
786  joinfiles = 1;
787  else
788  ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n");
789  }
790  ast_monitor_setjoinfiles(chan, joinfiles);
791 
792  return res;
793 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define X_REC_IN
Definition: monitor.h:30
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
static const struct ast_app_option monitor_opts[128]
Definition: res_monitor.c:684
static int tmp()
Definition: bt_open.c:389
unsigned int flags
Definition: utils.h:200
const char * args
#define NULL
Definition: resample.c:96
#define X_REC_OUT
Definition: monitor.h:31
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
int AST_OPTIONAL_API_NAME() ast_monitor_start(struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock, int stream_action, const char *beep_id)
Start monitoring a channel.
Definition: res_monitor.c:305
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
int AST_OPTIONAL_API_NAME() ast_beep_start(struct ast_channel *chan, unsigned int interval, char *beep_id, size_t len)
#define LOG_ERROR
Definition: logger.h:285
int AST_OPTIONAL_API_NAME() ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, int need_lock)
Change monitored filename of channel.
Definition: res_monitor.c:590
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define X_JOIN
Definition: monitor.h:32
void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
Set CDR user field for channel (stored in CDR)
Definition: cdr.c:3477
Structure used to handle boolean flags.
Definition: utils.h:199
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
void AST_OPTIONAL_API_NAME() ast_monitor_setjoinfiles(struct ast_channel *chan, int turnon)
Definition: res_monitor.c:926
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_name(const struct ast_channel *chan)
static struct test_options options
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ stop_monitor_action()

static int stop_monitor_action ( struct mansession s,
const struct message m 
)
static

Stop monitoring a channel by manager connection.

Definition at line 861 of file res_monitor.c.

References AMI_SUCCESS, ast_channel_get_by_name(), ast_channel_unref, ast_monitor_stop(), ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), c, name, and NULL.

Referenced by load_module().

862 {
863  struct ast_channel *c = NULL;
864  const char *name = astman_get_header(m, "Channel");
865  int res;
866 
867  if (ast_strlen_zero(name)) {
868  astman_send_error(s, m, "No channel specified");
869  return AMI_SUCCESS;
870  }
871 
872  if (!(c = ast_channel_get_by_name(name))) {
873  astman_send_error(s, m, "No such channel");
874  return AMI_SUCCESS;
875  }
876 
877  res = ast_monitor_stop(c, 1);
878 
879  c = ast_channel_unref(c);
880 
881  if (res) {
882  astman_send_error(s, m, "Could not stop monitoring channel");
883  return AMI_SUCCESS;
884  }
885 
886  astman_send_ack(s, m, "Stopped monitoring channel");
887 
888  return AMI_SUCCESS;
889 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
static struct test_val c
#define NULL
Definition: resample.c:96
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
static const char name[]
Definition: cdr_mysql.c:74
int AST_OPTIONAL_API_NAME() ast_monitor_stop(struct ast_channel *chan, int need_lock)
Stop monitoring channel.
Definition: res_monitor.c:461
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
#define AMI_SUCCESS
Definition: manager.h:65

◆ stop_monitor_exec()

static int stop_monitor_exec ( struct ast_channel chan,
const char *  data 
)
static

Wrapper function.

See also
ast_monitor_stop

Definition at line 796 of file res_monitor.c.

References ast_monitor_stop().

Referenced by load_module().

797 {
798  return ast_monitor_stop(chan, 1);
799 }
int AST_OPTIONAL_API_NAME() ast_monitor_stop(struct ast_channel *chan, int need_lock)
Stop monitoring channel.
Definition: res_monitor.c:461

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 992 of file res_monitor.c.

References ast_manager_unregister(), AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CHANNEL_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_DEPRECATED, ast_unregister_application(), ASTERISK_GPL_KEY, and load_module().

993 {
994  ast_unregister_application("Monitor");
995  ast_unregister_application("StopMonitor");
996  ast_unregister_application("ChangeMonitor");
997  ast_unregister_application("PauseMonitor");
998  ast_unregister_application("UnpauseMonitor");
999  ast_manager_unregister("Monitor");
1000  ast_manager_unregister("StopMonitor");
1001  ast_manager_unregister("ChangeMonitor");
1002  ast_manager_unregister("PauseMonitor");
1003  ast_manager_unregister("UnpauseMonitor");
1004 
1005  return 0;
1006 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258

◆ unpause_monitor_action()

static int unpause_monitor_action ( struct mansession s,
const struct message m 
)
static

Definition at line 971 of file res_monitor.c.

References do_pause_or_unpause(), and MONITOR_ACTION_UNPAUSE.

Referenced by load_module().

972 {
974 }
static int do_pause_or_unpause(struct mansession *s, const struct message *m, int action)
Definition: res_monitor.c:938

◆ unpause_monitor_exec()

static int unpause_monitor_exec ( struct ast_channel chan,
const char *  data 
)
static

Wrapper for ast_monitor_unpause.

Definition at line 577 of file res_monitor.c.

References ast_monitor_unpause().

Referenced by load_module().

578 {
579  return ast_monitor_unpause(chan);
580 }
int AST_OPTIONAL_API_NAME() ast_monitor_unpause(struct ast_channel *chan)
Unpause monitoring of channel.
Definition: res_monitor.c:565

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Call Monitoring Resource" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_DEPRECATED, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, .optional_modules = "func_periodic_hook", }
static

Definition at line 1015 of file res_monitor.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1015 of file res_monitor.c.

◆ monitor_opts

const struct ast_app_option monitor_opts[128] = { [ 'b' ] = { .flag = MON_FLAG_BRIDGED }, [ 'm' ] = { .flag = MON_FLAG_MIX }, [ 'i' ] = { .flag = MON_FLAG_DROP_IN }, [ 'o' ] = { .flag = MON_FLAG_DROP_OUT }, [ 'B' ] = { .flag = MON_FLAG_BEEP , .arg_index = OPT_ARG_BEEP_INTERVAL + 1 }, }
static

Definition at line 684 of file res_monitor.c.

Referenced by start_monitor_exec().

◆ monitorlock

ast_mutex_t monitorlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 261 of file res_monitor.c.

Referenced by ast_monitor_start().

◆ seq

unsigned long seq = 0
static

Definition at line 273 of file res_monitor.c.

Referenced by ast_monitor_start().