Channel monitoring. More...
#include "asterisk/channel.h"
Go to the source code of this file.
Data Structures | |
struct | ast_channel_monitor |
Enumerations | |
enum | AST_MONITORING_STATE { AST_MONITOR_RUNNING, AST_MONITOR_PAUSED } |
Functions | |
int | ast_monitor_change_fname (struct ast_channel *chan, const char *fname_base, int need_lock) |
int | ast_monitor_pause (struct ast_channel *chan) |
void | ast_monitor_setjoinfiles (struct ast_channel *chan, int turnon) |
int | ast_monitor_start (struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock) |
int | ast_monitor_stop (struct ast_channel *chan, int need_lock) |
int | ast_monitor_unpause (struct ast_channel *chan) |
Channel monitoring.
Definition in file monitor.h.
enum AST_MONITORING_STATE |
Definition at line 28 of file monitor.h.
00028 { 00029 AST_MONITOR_RUNNING, 00030 AST_MONITOR_PAUSED 00031 };
int ast_monitor_change_fname | ( | struct ast_channel * | chan, | |
const char * | fname_base, | |||
int | need_lock | |||
) |
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 371 of file res_monitor.c.
References ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_log(), ast_safe_system(), ast_strlen_zero(), errno, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, free, LOCK_IF_NEEDED, LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_channel::monitor, name, option_debug, strdup, and UNLOCK_IF_NEEDED.
Referenced by change_monitor_action(), change_monitor_exec(), start_monitor_action(), and start_monitor_exec().
00372 { 00373 char tmp[256]; 00374 if (ast_strlen_zero(fname_base)) { 00375 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name); 00376 return -1; 00377 } 00378 00379 LOCK_IF_NEEDED(chan, need_lock); 00380 00381 if (chan->monitor) { 00382 int directory = strchr(fname_base, '/') ? 1 : 0; 00383 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; 00384 const char *absolute_suffix = *fname_base == '/' ? "" : "/"; 00385 char tmpstring[sizeof(chan->monitor->filename_base)] = ""; 00386 int i, fd[2] = { -1, -1 }, doexit = 0; 00387 00388 /* before continuing, see if we're trying to rename the file to itself... */ 00389 snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", absolute, absolute_suffix, fname_base); 00390 00391 /* try creating the directory just in case it doesn't exist */ 00392 if (directory) { 00393 char *name = strdup(fname_base); 00394 snprintf(tmp, sizeof(tmp), "mkdir -p \"%s%s%s\"", absolute, absolute_suffix, dirname(name)); 00395 free(name); 00396 ast_safe_system(tmp); 00397 } 00398 00399 /*!\note We cannot just compare filenames, due to symlinks, relative 00400 * paths, and other possible filesystem issues. We could use 00401 * realpath(3), but its use is discouraged. However, if we try to 00402 * create the same file from two different paths, the second will 00403 * fail, and so we have our notification that the filenames point to 00404 * the same path. 00405 * 00406 * Remember, also, that we're using the basename of the file (i.e. 00407 * the file without the format suffix), so it does not already exist 00408 * and we aren't interfering with the recording itself. 00409 */ 00410 if (option_debug > 2) { 00411 ast_log(LOG_DEBUG, "comparing tmpstring %s to filename_base %s\n", tmpstring, chan->monitor->filename_base); 00412 } 00413 if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 || 00414 (fd[1] = open(chan->monitor->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) { 00415 if (fd[0] < 0) { 00416 ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno)); 00417 } else { 00418 if (option_debug > 2) { 00419 ast_log(LOG_DEBUG, "No need to rename monitor filename to itself\n"); 00420 } 00421 } 00422 doexit = 1; 00423 } 00424 00425 /* Cleanup temporary files */ 00426 for (i = 0; i < 2; i++) { 00427 if (fd[i] >= 0) { 00428 while (close(fd[i]) < 0 && errno == EINTR); 00429 } 00430 } 00431 unlink(tmpstring); 00432 /* if previous monitor file existed in a subdirectory, the directory will not be removed */ 00433 unlink(chan->monitor->filename_base); 00434 00435 if (doexit) { 00436 UNLOCK_IF_NEEDED(chan, need_lock); 00437 return 0; 00438 } 00439 00440 ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base)); 00441 chan->monitor->filename_changed = 1; 00442 } else { 00443 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base); 00444 } 00445 00446 UNLOCK_IF_NEEDED(chan, need_lock); 00447 00448 return 0; 00449 }
int ast_monitor_pause | ( | struct ast_channel * | chan | ) |
Definition at line 349 of file res_monitor.c.
References AST_MONITOR_PAUSED, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and pause_monitor_exec().
00350 { 00351 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED); 00352 }
void ast_monitor_setjoinfiles | ( | struct ast_channel * | chan, | |
int | turnon | |||
) |
Definition at line 652 of file res_monitor.c.
References ast_channel_monitor::joinfiles, and ast_channel::monitor.
Referenced by __agent_start_monitoring(), start_monitor_action(), start_monitor_exec(), and try_calling().
int ast_monitor_start | ( | struct ast_channel * | chan, | |
const char * | format_spec, | |||
const char * | fname_base, | |||
int | need_lock | |||
) |
Definition at line 132 of file res_monitor.c.
References ast_calloc, ast_closestream(), ast_config_AST_MONITOR_DIR, ast_filedelete(), ast_fileexists(), ast_log(), AST_MONITOR_RUNNING, ast_monitor_set_state(), ast_monitor_stop(), ast_mutex_lock, ast_mutex_unlock, ast_safe_system(), ast_strdupa, ast_strlen_zero(), ast_writefile(), errno, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, FILENAME_MAX, ast_channel_monitor::format, free, LOCK_IF_NEEDED, LOG_DEBUG, LOG_WARNING, monitor, ast_channel::monitor, monitorlock, name, pbx_builtin_setvar_helper(), ast_channel_monitor::read_filename, ast_channel_monitor::read_stream, ast_channel_monitor::stop, strdup, UNLOCK_IF_NEEDED, ast_channel_monitor::write_filename, and ast_channel_monitor::write_stream.
Referenced by __agent_start_monitoring(), start_monitor_action(), start_monitor_exec(), and try_calling().
00134 { 00135 int res = 0; 00136 char tmp[256]; 00137 00138 LOCK_IF_NEEDED(chan, need_lock); 00139 00140 if (!(chan->monitor)) { 00141 struct ast_channel_monitor *monitor; 00142 char *channel_name, *p; 00143 00144 /* Create monitoring directory if needed */ 00145 if (mkdir(ast_config_AST_MONITOR_DIR, 0770) < 0) { 00146 if (errno != EEXIST) { 00147 ast_log(LOG_WARNING, "Unable to create audio monitor directory: %s\n", 00148 strerror(errno)); 00149 } 00150 } 00151 00152 if (!(monitor = ast_calloc(1, sizeof(*monitor)))) { 00153 UNLOCK_IF_NEEDED(chan, need_lock); 00154 return -1; 00155 } 00156 00157 /* Determine file names */ 00158 if (!ast_strlen_zero(fname_base)) { 00159 int directory = strchr(fname_base, '/') ? 1 : 0; 00160 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; 00161 const char *absolute_suffix = *fname_base == '/' ? "" : "/"; 00162 /* try creating the directory just in case it doesn't exist */ 00163 if (directory) { 00164 char *name = strdup(fname_base); 00165 snprintf(tmp, sizeof(tmp), "mkdir -p \"%s%s%s\"", 00166 absolute, absolute_suffix, dirname(name)); 00167 free(name); 00168 ast_safe_system(tmp); 00169 } 00170 snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in", 00171 absolute, absolute_suffix, fname_base); 00172 snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out", 00173 absolute, absolute_suffix, fname_base); 00174 snprintf(monitor->filename_base, FILENAME_MAX, "%s%s%s", 00175 absolute, absolute_suffix, fname_base); 00176 } else { 00177 ast_mutex_lock(&monitorlock); 00178 snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld", 00179 ast_config_AST_MONITOR_DIR, seq); 00180 snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld", 00181 ast_config_AST_MONITOR_DIR, seq); 00182 seq++; 00183 ast_mutex_unlock(&monitorlock); 00184 00185 channel_name = ast_strdupa(chan->name); 00186 while ((p = strchr(channel_name, '/'))) { 00187 *p = '-'; 00188 } 00189 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s", 00190 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name); 00191 monitor->filename_changed = 1; 00192 } 00193 00194 monitor->stop = ast_monitor_stop; 00195 00196 /* Determine file format */ 00197 if (!ast_strlen_zero(format_spec)) { 00198 monitor->format = strdup(format_spec); 00199 } else { 00200 monitor->format = strdup("wav"); 00201 } 00202 00203 /* open files */ 00204 if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) { 00205 ast_filedelete(monitor->read_filename, NULL); 00206 } 00207 if (!(monitor->read_stream = ast_writefile(monitor->read_filename, 00208 monitor->format, NULL, 00209 O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) { 00210 ast_log(LOG_WARNING, "Could not create file %s\n", 00211 monitor->read_filename); 00212 free(monitor); 00213 UNLOCK_IF_NEEDED(chan, need_lock); 00214 return -1; 00215 } 00216 if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) { 00217 ast_filedelete(monitor->write_filename, NULL); 00218 } 00219 if (!(monitor->write_stream = ast_writefile(monitor->write_filename, 00220 monitor->format, NULL, 00221 O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) { 00222 ast_log(LOG_WARNING, "Could not create file %s\n", 00223 monitor->write_filename); 00224 ast_closestream(monitor->read_stream); 00225 free(monitor); 00226 UNLOCK_IF_NEEDED(chan, need_lock); 00227 return -1; 00228 } 00229 chan->monitor = monitor; 00230 ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00231 /* so we know this call has been monitored in case we need to bill for it or something */ 00232 pbx_builtin_setvar_helper(chan, "__MONITORED","true"); 00233 } else { 00234 ast_log(LOG_DEBUG,"Cannot start monitoring %s, already monitored\n", 00235 chan->name); 00236 res = -1; 00237 } 00238 00239 UNLOCK_IF_NEEDED(chan, need_lock); 00240 00241 return res; 00242 }
int ast_monitor_stop | ( | struct ast_channel * | chan, | |
int | need_lock | |||
) |
Definition at line 262 of file res_monitor.c.
References ast_closestream(), ast_copy_string(), ast_filedelete(), ast_fileexists(), ast_filerename(), ast_log(), ast_safe_system(), ast_strlen_zero(), ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, FILENAME_MAX, format, ast_channel_monitor::format, free, get_soxmix_format(), ast_channel_monitor::joinfiles, LOCK_IF_NEEDED, LOG_DEBUG, LOG_WARNING, ast_channel::monitor, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), ast_channel_monitor::read_filename, ast_channel_monitor::read_stream, UNLOCK_IF_NEEDED, ast_channel_monitor::write_filename, and ast_channel_monitor::write_stream.
Referenced by ast_monitor_start(), builtin_automonitor(), stop_monitor_action(), and stop_monitor_exec().
00263 { 00264 int delfiles = 0; 00265 00266 LOCK_IF_NEEDED(chan, need_lock); 00267 00268 if (chan->monitor) { 00269 char filename[ FILENAME_MAX ]; 00270 00271 if (chan->monitor->read_stream) { 00272 ast_closestream(chan->monitor->read_stream); 00273 } 00274 if (chan->monitor->write_stream) { 00275 ast_closestream(chan->monitor->write_stream); 00276 } 00277 00278 if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) { 00279 if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) { 00280 snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base); 00281 if (ast_fileexists(filename, NULL, NULL) > 0) { 00282 ast_filedelete(filename, NULL); 00283 } 00284 ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format); 00285 } else { 00286 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename); 00287 } 00288 00289 if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) { 00290 snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base); 00291 if (ast_fileexists(filename, NULL, NULL) > 0) { 00292 ast_filedelete(filename, NULL); 00293 } 00294 ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format); 00295 } else { 00296 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename); 00297 } 00298 } 00299 00300 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) { 00301 char tmp[1024]; 00302 char tmp2[1024]; 00303 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format; 00304 char *fname_base = chan->monitor->filename_base; 00305 const char *execute, *execute_args; 00306 /* at this point, fname_base really is the full path */ 00307 00308 /* Set the execute application */ 00309 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); 00310 if (ast_strlen_zero(execute)) { 00311 #ifdef HAVE_SOXMIX 00312 execute = "nice -n 19 soxmix"; 00313 #else 00314 execute = "nice -n 19 sox -m"; 00315 #endif 00316 format = get_soxmix_format(format); 00317 delfiles = 1; 00318 } 00319 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); 00320 if (ast_strlen_zero(execute_args)) { 00321 execute_args = ""; 00322 } 00323 00324 snprintf(tmp, sizeof(tmp), "%s \"%s-in.%s\" \"%s-out.%s\" \"%s.%s\" %s &", 00325 execute, fname_base, format, fname_base, format, fname_base, format,execute_args); 00326 if (delfiles) { 00327 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s-\"* ) &",tmp, fname_base); /* remove legs when done mixing */ 00328 ast_copy_string(tmp, tmp2, sizeof(tmp)); 00329 } 00330 ast_log(LOG_DEBUG,"monitor executing %s\n",tmp); 00331 if (ast_safe_system(tmp) == -1) 00332 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp); 00333 } 00334 00335 free(chan->monitor->format); 00336 free(chan->monitor); 00337 chan->monitor = NULL; 00338 pbx_builtin_setvar_helper(chan, "MONITORED", NULL); 00339 } 00340 pbx_builtin_setvar_helper(chan, "AUTO_MONITOR", NULL); 00341 00342 UNLOCK_IF_NEEDED(chan, need_lock); 00343 00344 return 0; 00345 }
int ast_monitor_unpause | ( | struct ast_channel * | chan | ) |
Definition at line 355 of file res_monitor.c.
References AST_MONITOR_RUNNING, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and unpause_monitor_exec().
00356 { 00357 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00358 }