#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/chanspy.h"
#include "asterisk/features.h"
#include "asterisk/options.h"
#include "asterisk/app.h"
#include "asterisk/utils.h"
#include "asterisk/say.h"
#include "asterisk/pbx.h"
#include "asterisk/translate.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
Include dependency graph for app_chanspy.c:

Go to the source code of this file.
Data Structures | |
| struct | chanspy_translation_helper |
Defines | |
| #define | ALL_DONE(u, ret) LOCAL_USER_REMOVE(u); return ret; |
| #define | AST_NAME_STRLEN 256 |
| #define | get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0 |
Enumerations | |
| enum | { OPTION_QUIET = (1 << 0), OPTION_BRIDGED = (1 << 1), OPTION_VOLUME = (1 << 2), OPTION_GROUP = (1 << 3), OPTION_RECORD = (1 << 4) } |
| enum | { OPT_ARG_VOLUME = 0, OPT_ARG_GROUP, OPT_ARG_RECORD, OPT_ARG_ARRAY_SIZE } |
Functions | |
| AST_APP_OPTIONS (chanspy_opts,{AST_APP_OPTION('q', OPTION_QUIET), AST_APP_OPTION('b', OPTION_BRIDGED), AST_APP_OPTION_ARG('v', OPTION_VOLUME, OPT_ARG_VOLUME), AST_APP_OPTION_ARG('g', OPTION_GROUP, OPT_ARG_GROUP), AST_APP_OPTION_ARG('r', OPTION_RECORD, OPT_ARG_RECORD),}) | |
| AST_MUTEX_DEFINE_STATIC (modlock) | |
| static int | channel_spy (struct ast_channel *chan, struct ast_channel *spyee, int *volfactor, int fd) |
| static int | chanspy_exec (struct ast_channel *chan, void *data) |
| char * | description (void) |
| Provides a description of the module. | |
| char * | key () |
| Returns the ASTERISK_GPL_KEY. | |
| int | load_module (void) |
| Initialize the module. | |
| static struct ast_channel * | local_channel_walk (struct ast_channel *chan) |
| static struct ast_channel * | local_get_channel_begin_name (char *name) |
| static void | set_volume (struct ast_channel *chan, struct chanspy_translation_helper *csth) |
| static void * | spy_alloc (struct ast_channel *chan, void *data) |
| static int | spy_generate (struct ast_channel *chan, void *data, int len, int samples) |
| static void | spy_release (struct ast_channel *chan, void *data) |
| static int | start_spying (struct ast_channel *chan, struct ast_channel *spychan, struct ast_channel_spy *spy) |
| int | unload_module (void) |
| Cleanup all module structures, sockets, etc. | |
| int | usecount (void) |
| Provides a usecount. | |
Variables | |
| static const char * | app = "ChanSpy" |
| enum { ... } | chanspy_opt_args |
| enum { ... } | chanspy_opt_flags |
| static const char * | chanspy_spy_type = "ChanSpy" |
| static const char * | desc |
| LOCAL_USER_DECL | |
| static struct ast_generator | spygen |
| STANDARD_LOCAL_USER | |
| static const char * | synopsis = "Listen to the audio of an active channel" |
| static signed char | volfactor_map [] |
Definition in file app_chanspy.c.
| #define ALL_DONE | ( | u, | |||
| ret | ) | LOCAL_USER_REMOVE(u); return ret; |
Definition at line 53 of file app_chanspy.c.
Referenced by _while_exec(), chanspy_exec(), and execif_exec().
| #define AST_NAME_STRLEN 256 |
| #define get_volfactor | ( | x | ) | x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0 |
| anonymous enum |
Definition at line 84 of file app_chanspy.c.
00084 { 00085 OPTION_QUIET = (1 << 0), /* Quiet, no announcement */ 00086 OPTION_BRIDGED = (1 << 1), /* Only look at bridged calls */ 00087 OPTION_VOLUME = (1 << 2), /* Specify initial volume */ 00088 OPTION_GROUP = (1 << 3), /* Only look at channels in group */ 00089 OPTION_RECORD = (1 << 4), /* Record */ 00090 } chanspy_opt_flags;
| anonymous enum |
Definition at line 92 of file app_chanspy.c.
00092 { 00093 OPT_ARG_VOLUME = 0, 00094 OPT_ARG_GROUP, 00095 OPT_ARG_RECORD, 00096 OPT_ARG_ARRAY_SIZE, 00097 } chanspy_opt_args;
| AST_APP_OPTIONS | ( | chanspy_opts | ) |
| AST_MUTEX_DEFINE_STATIC | ( | modlock | ) |
| static int channel_spy | ( | struct ast_channel * | chan, | |
| struct ast_channel * | spyee, | |||
| int * | volfactor, | |||
| int | fd | |||
| ) | [static] |
Definition at line 237 of file app_chanspy.c.
References ast_activate_generator(), ast_channel_spy_free(), ast_channel_spy_remove(), ast_check_hangup(), ast_clear_flag, ast_deactivate_generator(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, ast_frfree(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_set_flag, ast_strdupa, ast_strlen_zero(), ast_verbose(), ast_waitfor(), CHANSPY_DONE, CHANSPY_FORMAT_AUDIO, CHANSPY_MIXAUDIO, CHANSPY_READ_VOLADJUST, CHANSPY_RUNNING, CHANSPY_TRIGGER_NONE, CHANSPY_WRITE_VOLADJUST, ast_frame::frametype, ast_channel::name, name, option_verbose, set_volume(), spygen, start_spying(), ast_frame::subclass, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.
Referenced by chanspy_exec().
00238 { 00239 struct chanspy_translation_helper csth; 00240 int running = 0, res = 0, x = 0; 00241 char inp[24] = "", *name = NULL; 00242 struct ast_frame *f = NULL; 00243 00244 if ((chan && ast_check_hangup(chan)) || (spyee && ast_check_hangup(spyee))) 00245 return 0; 00246 00247 name = ast_strdupa(spyee->name); 00248 if (option_verbose > 1) 00249 ast_verbose(VERBOSE_PREFIX_2 "Spying on channel %s\n", name); 00250 00251 memset(&csth, 0, sizeof(csth)); 00252 ast_set_flag(&csth.spy, CHANSPY_FORMAT_AUDIO); 00253 ast_set_flag(&csth.spy, CHANSPY_TRIGGER_NONE); 00254 ast_set_flag(&csth.spy, CHANSPY_MIXAUDIO); 00255 csth.spy.type = chanspy_spy_type; 00256 csth.spy.status = CHANSPY_RUNNING; 00257 csth.spy.read_queue.format = AST_FORMAT_SLINEAR; 00258 csth.spy.write_queue.format = AST_FORMAT_SLINEAR; 00259 ast_mutex_init(&csth.spy.lock); 00260 csth.volfactor = *volfactor; 00261 set_volume(chan, &csth); 00262 if (csth.volfactor) { 00263 ast_set_flag(&csth.spy, CHANSPY_READ_VOLADJUST); 00264 csth.spy.read_vol_adjustment = csth.volfactor; 00265 ast_set_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST); 00266 csth.spy.write_vol_adjustment = csth.volfactor; 00267 } 00268 csth.fd = fd; 00269 00270 if (start_spying(spyee, chan, &csth.spy)) { 00271 ast_channel_spy_free(&csth.spy); 00272 return 0; 00273 } 00274 00275 ast_activate_generator(chan, &spygen, &csth); 00276 00277 while (csth.spy.status == CHANSPY_RUNNING && 00278 (res = ast_waitfor(chan, -1) > -1)) { 00279 00280 /* Read in frame from channel, break out if no frame */ 00281 if (!(f = ast_read(chan))) 00282 break; 00283 00284 /* Now if this is DTMF then we have to handle it as such, otherwise just skip it */ 00285 res = 0; 00286 if (f->frametype == AST_FRAME_DTMF) 00287 res = f->subclass; 00288 ast_frfree(f); 00289 if (!res) 00290 continue; 00291 00292 if (x == sizeof(inp)) 00293 x = 0; 00294 00295 if (res < 0) { 00296 running = -1; 00297 break; 00298 } 00299 00300 /* Process DTMF digits */ 00301 if (res == '#') { 00302 if (!ast_strlen_zero(inp)) { 00303 running = x ? atoi(inp) : -1; 00304 break; 00305 } else { 00306 (*volfactor)++; 00307 if (*volfactor > 4) 00308 *volfactor = -1; 00309 if (option_verbose > 2) 00310 ast_verbose(VERBOSE_PREFIX_3 "Setting spy volume on %s to %d\n", chan->name, *volfactor); 00311 csth.volfactor = *volfactor; 00312 set_volume(chan, &csth); 00313 if (csth.volfactor) { 00314 ast_set_flag(&csth.spy, CHANSPY_READ_VOLADJUST); 00315 csth.spy.read_vol_adjustment = csth.volfactor; 00316 ast_set_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST); 00317 csth.spy.write_vol_adjustment = csth.volfactor; 00318 } else { 00319 ast_clear_flag(&csth.spy, CHANSPY_READ_VOLADJUST); 00320 ast_clear_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST); 00321 } 00322 } 00323 } else if (res == '*') { 00324 break; 00325 } else if (res >= 48 && res <= 57) { 00326 inp[x++] = res; 00327 } 00328 } 00329 00330 ast_deactivate_generator(chan); 00331 00332 csth.spy.status = CHANSPY_DONE; 00333 00334 ast_mutex_lock(&csth.spy.lock); 00335 if (csth.spy.chan) { 00336 ast_mutex_lock(&csth.spy.chan->lock); 00337 ast_channel_spy_remove(csth.spy.chan, &csth.spy); 00338 ast_mutex_unlock(&csth.spy.chan->lock); 00339 } 00340 ast_mutex_unlock(&csth.spy.lock); 00341 00342 if (option_verbose > 1) 00343 ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name); 00344 00345 ast_channel_spy_free(&csth.spy); 00346 00347 return running; 00348 }
| static int chanspy_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 350 of file app_chanspy.c.
References ALL_DONE, ast_answer(), ast_app_parse_options(), ast_app_separate_args(), ast_bridged_channel(), ast_channel_setoption(), ast_check_hangup(), ast_clear_flag, ast_config_AST_MONITOR_DIR, ast_fileexists(), AST_FLAG_SPYING, AST_FLAGS_ALL, AST_FORMAT_SLINEAR, ast_log(), AST_NAME_STRLEN, AST_OPTION_TXGAIN, ast_say_character_str(), ast_say_digits(), ast_set_flag, ast_set_read_format(), ast_set_write_format(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), ast_waitstream(), channel_spy(), ast_flags::flags, group, ast_channel::language, local_channel_walk(), local_get_channel_begin_name(), LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::name, name, OPT_ARG_ARRAY_SIZE, OPT_ARG_GROUP, OPT_ARG_RECORD, OPT_ARG_VOLUME, OPTION_BRIDGED, OPTION_GROUP, OPTION_QUIET, OPTION_RECORD, OPTION_VOLUME, pbx_builtin_getvar_helper(), ast_channel::readformat, and ast_channel::writeformat.
Referenced by load_module().
00351 { 00352 struct localuser *u; 00353 struct ast_channel *peer=NULL, *prev=NULL; 00354 char name[AST_NAME_STRLEN], 00355 peer_name[AST_NAME_STRLEN + 5], 00356 *args, 00357 *ptr = NULL, 00358 *options = NULL, 00359 *spec = NULL, 00360 *argv[5], 00361 *mygroup = NULL, 00362 *recbase = NULL; 00363 int res = -1, 00364 volfactor = 0, 00365 silent = 0, 00366 argc = 0, 00367 bronly = 0, 00368 chosen = 0, 00369 count=0, 00370 waitms = 100, 00371 num = 0, 00372 oldrf = 0, 00373 oldwf = 0, 00374 fd = 0; 00375 struct ast_flags flags; 00376 signed char zero_volume = 0; 00377 00378 if (!(args = ast_strdupa((char *)data))) { 00379 ast_log(LOG_ERROR, "Out of memory!\n"); 00380 return -1; 00381 } 00382 00383 LOCAL_USER_ADD(u); 00384 00385 oldrf = chan->readformat; 00386 oldwf = chan->writeformat; 00387 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 00388 ast_log(LOG_ERROR, "Could Not Set Read Format.\n"); 00389 LOCAL_USER_REMOVE(u); 00390 return -1; 00391 } 00392 00393 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 00394 ast_log(LOG_ERROR, "Could Not Set Write Format.\n"); 00395 LOCAL_USER_REMOVE(u); 00396 return -1; 00397 } 00398 00399 ast_answer(chan); 00400 00401 ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */ 00402 00403 if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) { 00404 spec = argv[0]; 00405 if ( argc > 1) { 00406 options = argv[1]; 00407 } 00408 if (ast_strlen_zero(spec) || !strcmp(spec, "all")) { 00409 spec = NULL; 00410 } 00411 } 00412 00413 if (options) { 00414 char *opts[OPT_ARG_ARRAY_SIZE]; 00415 ast_app_parse_options(chanspy_opts, &flags, opts, options); 00416 if (ast_test_flag(&flags, OPTION_GROUP)) { 00417 mygroup = opts[OPT_ARG_GROUP]; 00418 } 00419 if (ast_test_flag(&flags, OPTION_RECORD)) { 00420 if (!(recbase = opts[OPT_ARG_RECORD])) { 00421 recbase = "chanspy"; 00422 } 00423 } 00424 silent = ast_test_flag(&flags, OPTION_QUIET); 00425 bronly = ast_test_flag(&flags, OPTION_BRIDGED); 00426 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) { 00427 int vol; 00428 00429 if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4)) 00430 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n"); 00431 else 00432 volfactor = vol; 00433 } 00434 } 00435 else 00436 ast_clear_flag(&flags, AST_FLAGS_ALL); 00437 00438 if (recbase) { 00439 char filename[512]; 00440 snprintf(filename,sizeof(filename),"%s/%s.%d.raw",ast_config_AST_MONITOR_DIR, recbase, (int)time(NULL)); 00441 if ((fd = open(filename, O_CREAT | O_WRONLY, O_TRUNC, 0644)) <= 0) { 00442 ast_log(LOG_WARNING, "Cannot open %s for recording\n", filename); 00443 fd = 0; 00444 } 00445 } 00446 00447 for(;;) { 00448 if (!silent) { 00449 res = ast_streamfile(chan, "beep", chan->language); 00450 if (!res) 00451 res = ast_waitstream(chan, ""); 00452 if (res < 0) { 00453 ast_clear_flag(chan, AST_FLAG_SPYING); 00454 break; 00455 } 00456 } 00457 00458 count = 0; 00459 res = ast_waitfordigit(chan, waitms); 00460 if (res < 0) { 00461 ast_clear_flag(chan, AST_FLAG_SPYING); 00462 break; 00463 } 00464 00465 peer = local_channel_walk(NULL); 00466 prev=NULL; 00467 while(peer) { 00468 if (peer != chan) { 00469 char *group = NULL; 00470 int igrp = 1; 00471 00472 if (peer == prev && !chosen) { 00473 break; 00474 } 00475 chosen = 0; 00476 group = pbx_builtin_getvar_helper(peer, "SPYGROUP"); 00477 if (mygroup) { 00478 if (!group || strcmp(mygroup, group)) { 00479 igrp = 0; 00480 } 00481 } 00482 00483 if (igrp && (!spec || ((strlen(spec) <= strlen(peer->name) && 00484 !strncasecmp(peer->name, spec, strlen(spec)))))) { 00485 if (peer && (!bronly || ast_bridged_channel(peer)) && 00486 !ast_check_hangup(peer) && !ast_test_flag(peer, AST_FLAG_SPYING)) { 00487 int x = 0; 00488 strncpy(peer_name, "spy-", 5); 00489 strncpy(peer_name + strlen(peer_name), peer->name, AST_NAME_STRLEN); 00490 ptr = strchr(peer_name, '/'); 00491 *ptr = '\0'; 00492 ptr++; 00493 for (x = 0 ; x < strlen(peer_name) ; x++) { 00494 if (peer_name[x] == '/') { 00495 break; 00496 } 00497 peer_name[x] = tolower(peer_name[x]); 00498 } 00499 00500 if (!silent) { 00501 if (ast_fileexists(peer_name, NULL, NULL) != -1) { 00502 res = ast_streamfile(chan, peer_name, chan->language); 00503 if (!res) 00504 res = ast_waitstream(chan, ""); 00505 if (res) 00506 break; 00507 } else 00508 res = ast_say_character_str(chan, peer_name, "", chan->language); 00509 if ((num=atoi(ptr))) 00510 ast_say_digits(chan, atoi(ptr), "", chan->language); 00511 } 00512 count++; 00513 prev = peer; 00514 res = channel_spy(chan, peer, &volfactor, fd); 00515 if (res == -1) { 00516 break; 00517 } else if (res > 1 && spec) { 00518 snprintf(name, AST_NAME_STRLEN, "%s/%d", spec, res); 00519 if ((peer = local_get_channel_begin_name(name))) { 00520 chosen = 1; 00521 } 00522 continue; 00523 } 00524 } 00525 } 00526 } 00527 if ((peer = local_channel_walk(peer)) == NULL) { 00528 break; 00529 } 00530 } 00531 waitms = count ? 100 : 5000; 00532 } 00533 00534 00535 if (fd > 0) { 00536 close(fd); 00537 } 00538 00539 if (oldrf && ast_set_read_format(chan, oldrf) < 0) { 00540 ast_log(LOG_ERROR, "Could Not Set Read Format.\n"); 00541 } 00542 00543 if (oldwf && ast_set_write_format(chan, oldwf) < 0) { 00544 ast_log(LOG_ERROR, "Could Not Set Write Format.\n"); 00545 } 00546 00547 ast_clear_flag(chan, AST_FLAG_SPYING); 00548 00549 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0); 00550 00551 ALL_DONE(u, res); 00552 }
| char* description | ( | void | ) |
Provides a description of the module.
Definition at line 570 of file app_chanspy.c.
00571 { 00572 return (char *) synopsis; 00573 }
| char* key | ( | void | ) |
Returns the ASTERISK_GPL_KEY.
This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 582 of file app_chanspy.c.
References ASTERISK_GPL_KEY.
00583 { 00584 return ASTERISK_GPL_KEY; 00585 }
| int load_module | ( | void | ) |
Initialize the module.
TE STUFF END
Definition at line 565 of file app_chanspy.c.
References ast_register_application(), and chanspy_exec().
00566 { 00567 return ast_register_application(app, chanspy_exec, synopsis, desc); 00568 }
| static struct ast_channel* local_channel_walk | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 117 of file app_chanspy.c.
References ast_channel_walk_locked(), ast_mutex_lock(), ast_mutex_unlock(), and ast_channel::lock.
Referenced by chanspy_exec(), and local_get_channel_begin_name().
00118 { 00119 struct ast_channel *ret; 00120 ast_mutex_lock(&modlock); 00121 if ((ret = ast_channel_walk_locked(chan))) { 00122 ast_mutex_unlock(&ret->lock); 00123 } 00124 ast_mutex_unlock(&modlock); 00125 return ret; 00126 }
| static struct ast_channel* local_get_channel_begin_name | ( | char * | name | ) | [static] |
Definition at line 128 of file app_chanspy.c.
References ast_mutex_lock(), ast_mutex_unlock(), local_channel_walk(), and ast_channel::name.
Referenced by chanspy_exec().
00129 { 00130 struct ast_channel *chan, *ret = NULL; 00131 ast_mutex_lock(&modlock); 00132 chan = local_channel_walk(NULL); 00133 while (chan) { 00134 if (!strncmp(chan->name, name, strlen(name)) && strncmp(chan->name, "Zap/pseudo", 10)) { 00135 ret = chan; 00136 break; 00137 } 00138 chan = local_channel_walk(chan); 00139 } 00140 ast_mutex_unlock(&modlock); 00141 00142 return ret; 00143 }
| static void set_volume | ( | struct ast_channel * | chan, | |
| struct chanspy_translation_helper * | csth | |||
| ) | [static] |
Definition at line 229 of file app_chanspy.c.
References ast_channel_setoption(), AST_OPTION_TXGAIN, and chanspy_translation_helper::volfactor.
Referenced by channel_spy().
00230 { 00231 signed char volume_adjust = volfactor_map[csth->volfactor + 4]; 00232 00233 if (!ast_channel_setoption(chan, AST_OPTION_TXGAIN, &volume_adjust, sizeof(volume_adjust), 0)) 00234 csth->volfactor = 0; 00235 }
| static void* spy_alloc | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 145 of file app_chanspy.c.
00146 { 00147 /* just store the data pointer in the channel structure */ 00148 return data; 00149 }
| static int spy_generate | ( | struct ast_channel * | chan, | |
| void * | data, | |||
| int | len, | |||
| int | samples | |||
| ) | [static] |
Definition at line 156 of file app_chanspy.c.
References ast_channel_spy_read_frame(), ast_frfree(), ast_mutex_lock(), ast_mutex_unlock(), ast_write(), CHANSPY_RUNNING, ast_frame::data, ast_frame::datalen, chanspy_translation_helper::fd, ast_channel_spy::lock, chanspy_translation_helper::spy, and ast_channel_spy::status.
00157 { 00158 struct chanspy_translation_helper *csth = data; 00159 struct ast_frame *f; 00160 00161 if (csth->spy.status != CHANSPY_RUNNING) 00162 /* Channel is already gone more than likely */ 00163 return -1; 00164 00165 ast_mutex_lock(&csth->spy.lock); 00166 f = ast_channel_spy_read_frame(&csth->spy, samples); 00167 ast_mutex_unlock(&csth->spy.lock); 00168 00169 if (!f) 00170 return 0; 00171 00172 if (ast_write(chan, f)) { 00173 ast_frfree(f); 00174 return -1; 00175 } 00176 00177 if (csth->fd) 00178 write(csth->fd, f->data, f->datalen); 00179 00180 ast_frfree(f); 00181 00182 return 0; 00183 }
| static void spy_release | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
| static int start_spying | ( | struct ast_channel * | chan, | |
| struct ast_channel * | spychan, | |||
| struct ast_channel_spy * | spy | |||
| ) | [static] |
Definition at line 192 of file app_chanspy.c.
References ast_bridged_channel(), ast_channel_spy_add(), AST_FLAG_NBRIDGE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_softhangup(), AST_SOFTHANGUP_UNBRIDGE, ast_test_flag, ast_channel::lock, LOG_NOTICE, and ast_channel::name.
Referenced by channel_spy().
00193 { 00194 int res; 00195 struct ast_channel *peer; 00196 00197 ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan->name, chan->name); 00198 00199 ast_mutex_lock(&chan->lock); 00200 res = ast_channel_spy_add(chan, spy); 00201 ast_mutex_unlock(&chan->lock); 00202 00203 if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan))) { 00204 ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE); 00205 } 00206 00207 return res; 00208 }
| int unload_module | ( | void | ) |
Cleanup all module structures, sockets, etc.
This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 554 of file app_chanspy.c.
References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.
00555 { 00556 int res; 00557 00558 res = ast_unregister_application(app); 00559 00560 STANDARD_HANGUP_LOCALUSERS; 00561 00562 return res; 00563 }
| int usecount | ( | void | ) |
Provides a usecount.
This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 575 of file app_chanspy.c.
References STANDARD_USECOUNT.
00576 { 00577 int res; 00578 STANDARD_USECOUNT(res); 00579 return res; 00580 }
const char* app = "ChanSpy" [static] |
Definition at line 57 of file app_chanspy.c.
| enum { ... } chanspy_opt_args |
| enum { ... } chanspy_opt_flags |
const char* chanspy_spy_type = "ChanSpy" [static] |
Definition at line 82 of file app_chanspy.c.
const char* desc [static] |
Definition at line 58 of file app_chanspy.c.
Definition at line 108 of file app_chanspy.c.
struct ast_generator spygen [static] |
Initial value:
{
.alloc = spy_alloc,
.release = spy_release,
.generate = spy_generate,
}
Definition at line 186 of file app_chanspy.c.
Referenced by channel_spy().
Definition at line 107 of file app_chanspy.c.
Definition at line 56 of file app_chanspy.c.
signed char volfactor_map[] [static] |
Definition at line 213 of file app_chanspy.c.
1.5.1