Fri Sep 29 11:12:37 2006

Asterisk developer's documentation


app_chanspy.c File Reference

ChanSpy: Listen in on any channel. More...

#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_channellocal_channel_walk (struct ast_channel *chan)
static struct ast_channellocal_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\n"
static signed char volfactor_map []


Detailed Description

ChanSpy: Listen in on any channel.

Definition in file app_chanspy.c.


Define Documentation

#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

Definition at line 52 of file app_chanspy.c.

Referenced by chanspy_exec().

#define get_volfactor (  )     x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0

Definition at line 54 of file app_chanspy.c.

Referenced by mixmonitor_exec().


Enumeration Type Documentation

anonymous enum

Enumerator:
OPTION_QUIET 
OPTION_BRIDGED 
OPTION_VOLUME 
OPTION_GROUP 
OPTION_RECORD 

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

Enumerator:
OPT_ARG_VOLUME 
OPT_ARG_GROUP 
OPT_ARG_RECORD 
OPT_ARG_ARRAY_SIZE 

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;


Function Documentation

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_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(), ast_channel_spy::chan, CHANSPY_DONE, CHANSPY_FORMAT_AUDIO, CHANSPY_MIXAUDIO, CHANSPY_RUNNING, CHANSPY_TRIGGER_NONE, ast_frame::frametype, ast_channel::lock, ast_channel::name, name, option_verbose, ast_channel_spy::read_vol_adjustment, set_volume(), chanspy_translation_helper::spy, spygen, start_spying(), ast_channel_spy::status, ast_frame::subclass, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, chanspy_translation_helper::volfactor, and ast_channel_spy::write_vol_adjustment.

Referenced by chanspy_exec().

00238 {
00239    struct chanspy_translation_helper csth;
00240    int running, res = 0, x = 0;
00241    char inp[24];
00242    char *name=NULL;
00243    struct ast_frame *f;
00244 
00245    running = (chan && !ast_check_hangup(chan) && spyee && !ast_check_hangup(spyee));
00246 
00247    if (running) {
00248       memset(inp, 0, sizeof(inp));
00249       name = ast_strdupa(spyee->name);
00250       if (option_verbose >= 2)
00251          ast_verbose(VERBOSE_PREFIX_2 "Spying on channel %s\n", name);
00252 
00253       memset(&csth, 0, sizeof(csth));
00254       ast_set_flag(&csth.spy, CHANSPY_FORMAT_AUDIO);
00255       ast_set_flag(&csth.spy, CHANSPY_TRIGGER_NONE);
00256       ast_set_flag(&csth.spy, CHANSPY_MIXAUDIO);
00257       csth.spy.type = chanspy_spy_type;
00258       csth.spy.status = CHANSPY_RUNNING;
00259       csth.spy.read_queue.format = AST_FORMAT_SLINEAR;
00260       csth.spy.write_queue.format = AST_FORMAT_SLINEAR;
00261       ast_mutex_init(&csth.spy.lock);
00262       csth.volfactor = *volfactor;
00263       set_volume(chan, &csth);
00264       csth.spy.read_vol_adjustment = csth.volfactor;
00265       csth.spy.write_vol_adjustment = csth.volfactor;
00266       csth.fd = fd;
00267 
00268       if (start_spying(spyee, chan, &csth.spy))
00269          running = 0;
00270    }
00271 
00272    if (running) {
00273       running = 1;
00274       ast_activate_generator(chan, &spygen, &csth);
00275 
00276       while (csth.spy.status == CHANSPY_RUNNING &&
00277              chan && !ast_check_hangup(chan) &&
00278              spyee &&
00279              !ast_check_hangup(spyee) &&
00280              running == 1 &&
00281              (res = ast_waitfor(chan, -1) > -1)) {
00282          if ((f = ast_read(chan))) {
00283             res = 0;
00284             if (f->frametype == AST_FRAME_DTMF) {
00285                res = f->subclass;
00286             }
00287             ast_frfree(f);
00288             if (!res) {
00289                continue;
00290             }
00291          } else {
00292             break;
00293          }
00294          if (x == sizeof(inp)) {
00295             x = 0;
00296          }
00297          if (res < 0) {
00298             running = -1;
00299          }
00300          if (res == 0) {
00301             continue;
00302          } else if (res == '*') {
00303             running = 0; 
00304          } else if (res == '#') {
00305             if (!ast_strlen_zero(inp)) {
00306                running = x ? atoi(inp) : -1;
00307                break;
00308             } else {
00309                (*volfactor)++;
00310                if (*volfactor > 4) {
00311                   *volfactor = -4;
00312                }
00313                if (option_verbose > 2) {
00314                   ast_verbose(VERBOSE_PREFIX_3 "Setting spy volume on %s to %d\n", chan->name, *volfactor);
00315                }
00316                csth.volfactor = *volfactor;
00317                set_volume(chan, &csth);
00318                csth.spy.read_vol_adjustment = csth.volfactor;
00319                csth.spy.write_vol_adjustment = csth.volfactor;
00320             }
00321          } else if (res >= 48 && res <= 57) {
00322             inp[x++] = res;
00323          }
00324       }
00325       ast_deactivate_generator(chan);
00326 
00327       if (csth.spy.chan) {
00328          csth.spy.status = CHANSPY_DONE;
00329          ast_mutex_lock(&csth.spy.chan->lock);
00330          ast_channel_spy_remove(csth.spy.chan, &csth.spy);
00331          ast_mutex_unlock(&csth.spy.chan->lock);
00332       }
00333 
00334       if (option_verbose >= 2) {
00335          ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name);
00336       }
00337    } else {
00338       running = 0;
00339    }
00340 
00341    ast_channel_spy_free(&csth.spy);
00342 
00343    return running;
00344 }

static int chanspy_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 346 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_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().

00347 {
00348    struct localuser *u;
00349    struct ast_channel *peer=NULL, *prev=NULL;
00350    char name[AST_NAME_STRLEN],
00351       peer_name[AST_NAME_STRLEN + 5],
00352       *args,
00353       *ptr = NULL,
00354       *options = NULL,
00355       *spec = NULL,
00356       *argv[5],
00357       *mygroup = NULL,
00358       *recbase = NULL;
00359    int res = -1,
00360       volfactor = 0,
00361       silent = 0,
00362       argc = 0,
00363       bronly = 0,
00364       chosen = 0,
00365       count=0,
00366       waitms = 100,
00367       num = 0,
00368       oldrf = 0,
00369       oldwf = 0,
00370       fd = 0;
00371    struct ast_flags flags;
00372    signed char zero_volume = 0;
00373 
00374    if (!(args = ast_strdupa((char *)data))) {
00375       ast_log(LOG_ERROR, "Out of memory!\n");
00376       return -1;
00377    }
00378 
00379    LOCAL_USER_ADD(u);
00380 
00381    oldrf = chan->readformat;
00382    oldwf = chan->writeformat;
00383    if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
00384       ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
00385       LOCAL_USER_REMOVE(u);
00386       return -1;
00387    }
00388    
00389    if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
00390       ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
00391       LOCAL_USER_REMOVE(u);
00392       return -1;
00393    }
00394 
00395    ast_answer(chan);
00396 
00397    ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
00398 
00399    if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
00400       spec = argv[0];
00401       if ( argc > 1) {
00402          options = argv[1];
00403       }
00404       if (ast_strlen_zero(spec) || !strcmp(spec, "all")) {
00405          spec = NULL;
00406       }
00407    }
00408    
00409    if (options) {
00410       char *opts[OPT_ARG_ARRAY_SIZE];
00411       ast_app_parse_options(chanspy_opts, &flags, opts, options);
00412       if (ast_test_flag(&flags, OPTION_GROUP)) {
00413          mygroup = opts[OPT_ARG_GROUP];
00414       }
00415       if (ast_test_flag(&flags, OPTION_RECORD)) {
00416          if (!(recbase = opts[OPT_ARG_RECORD])) {
00417             recbase = "chanspy";
00418          }
00419       }
00420       silent = ast_test_flag(&flags, OPTION_QUIET);
00421       bronly = ast_test_flag(&flags, OPTION_BRIDGED);
00422       if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
00423          int vol;
00424 
00425          if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
00426             ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
00427          else
00428             volfactor = vol;
00429          }
00430    }
00431 
00432    if (recbase) {
00433       char filename[512];
00434       snprintf(filename,sizeof(filename),"%s/%s.%d.raw",ast_config_AST_MONITOR_DIR, recbase, (int)time(NULL));
00435       if ((fd = open(filename, O_CREAT | O_WRONLY, O_TRUNC, 0644)) <= 0) {
00436          ast_log(LOG_WARNING, "Cannot open %s for recording\n", filename);
00437          fd = 0;
00438       }
00439    }
00440 
00441    for(;;) {
00442       if (!silent) {
00443          res = ast_streamfile(chan, "beep", chan->language);
00444          if (!res)
00445             res = ast_waitstream(chan, "");
00446          if (res < 0) {
00447             ast_clear_flag(chan, AST_FLAG_SPYING);
00448             break;
00449          }
00450       }
00451 
00452       count = 0;
00453       res = ast_waitfordigit(chan, waitms);
00454       if (res < 0) {
00455          ast_clear_flag(chan, AST_FLAG_SPYING);
00456          break;
00457       }
00458             
00459       peer = local_channel_walk(NULL);
00460       prev=NULL;
00461       while(peer) {
00462          if (peer != chan) {
00463             char *group = NULL;
00464             int igrp = 1;
00465 
00466             if (peer == prev && !chosen) {
00467                break;
00468             }
00469             chosen = 0;
00470             group = pbx_builtin_getvar_helper(peer, "SPYGROUP");
00471             if (mygroup) {
00472                if (!group || strcmp(mygroup, group)) {
00473                   igrp = 0;
00474                }
00475             }
00476             
00477             if (igrp && (!spec || ((strlen(spec) <= strlen(peer->name) &&
00478                      !strncasecmp(peer->name, spec, strlen(spec)))))) {
00479                if (peer && (!bronly || ast_bridged_channel(peer)) &&
00480                    !ast_check_hangup(peer) && !ast_test_flag(peer, AST_FLAG_SPYING)) {
00481                   int x = 0;
00482                   strncpy(peer_name, "spy-", 5);
00483                   strncpy(peer_name + strlen(peer_name), peer->name, AST_NAME_STRLEN);
00484                   ptr = strchr(peer_name, '/');
00485                   *ptr = '\0';
00486                   ptr++;
00487                   for (x = 0 ; x < strlen(peer_name) ; x++) {
00488                      if (peer_name[x] == '/') {
00489                         break;
00490                      }
00491                      peer_name[x] = tolower(peer_name[x]);
00492                   }
00493 
00494                   if (!silent) {
00495                      if (ast_fileexists(peer_name, NULL, NULL) != -1) {
00496                         res = ast_streamfile(chan, peer_name, chan->language);
00497                         if (!res)
00498                            res = ast_waitstream(chan, "");
00499                         if (res)
00500                            break;
00501                      } else
00502                         res = ast_say_character_str(chan, peer_name, "", chan->language);
00503                      if ((num=atoi(ptr))) 
00504                         ast_say_digits(chan, atoi(ptr), "", chan->language);
00505                   }
00506                   count++;
00507                   prev = peer;
00508                   res = channel_spy(chan, peer, &volfactor, fd);
00509                   if (res == -1) {
00510                      break;
00511                   } else if (res > 1 && spec) {
00512                      snprintf(name, AST_NAME_STRLEN, "%s/%d", spec, res);
00513                      if ((peer = local_get_channel_begin_name(name))) {
00514                         chosen = 1;
00515                      }
00516                      continue;
00517                   }
00518                }
00519             }
00520          }
00521          if ((peer = local_channel_walk(peer)) == NULL) {
00522             break;
00523          }
00524       }
00525       waitms = count ? 100 : 5000;
00526    }
00527    
00528 
00529    if (fd > 0) {
00530       close(fd);
00531    }
00532 
00533    if (oldrf && ast_set_read_format(chan, oldrf) < 0) {
00534       ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
00535    }
00536    
00537    if (oldwf && ast_set_write_format(chan, oldwf) < 0) {
00538       ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
00539    }
00540 
00541    ast_clear_flag(chan, AST_FLAG_SPYING);
00542 
00543    ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
00544 
00545    ALL_DONE(u, res);
00546 }

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 564 of file app_chanspy.c.

00565 {
00566    return (char *) synopsis;
00567 }

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;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 576 of file app_chanspy.c.

References ASTERISK_GPL_KEY.

00577 {
00578    return ASTERISK_GPL_KEY;
00579 }

int load_module ( void   ) 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 559 of file app_chanspy.c.

References ast_register_application(), and chanspy_exec().

00560 {
00561    return ast_register_application(app, chanspy_exec, synopsis, desc);
00562 }

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]

Definition at line 151 of file app_chanspy.c.

00152 {
00153    /* nothing to do */
00154 }

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).

Returns:
Zero on success, or non-zero on error.

Definition at line 548 of file app_chanspy.c.

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

00549 {
00550    int res;
00551 
00552    res = ast_unregister_application(app);
00553 
00554    STANDARD_HANGUP_LOCALUSERS;
00555 
00556    return res;
00557 }

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.

Returns:
The module's usecount.

Definition at line 569 of file app_chanspy.c.

References STANDARD_USECOUNT.

00570 {
00571    int res;
00572    STANDARD_USECOUNT(res);
00573    return res;
00574 }


Variable Documentation

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.

LOCAL_USER_DECL

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().

STANDARD_LOCAL_USER

Definition at line 107 of file app_chanspy.c.

const char* synopsis = "Listen to the audio of an active channel\n" [static]

Definition at line 56 of file app_chanspy.c.

signed char volfactor_map[] [static]

Definition at line 213 of file app_chanspy.c.


Generated on Fri Sep 29 11:12:38 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7