Sun Aug 6 15:03:04 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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.

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)
static void stop_spying (struct ast_channel *chan, 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
 

Enumeration values:
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
 

Enumeration values:
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 252 of file app_chanspy.c.

References ast_activate_generator(), ast_check_hangup(), ast_deactivate_generator(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, ast_frfree(), ast_mutex_destroy(), ast_mutex_init(), ast_read(), ast_set_flag, ast_strdupa, ast_strlen_zero(), ast_verbose(), ast_waitfor(), CHANSPY_FORMAT_AUDIO, CHANSPY_MIXAUDIO, CHANSPY_RUNNING, chanspy_spy_type, CHANSPY_TRIGGER_NONE, ast_frame::frametype, ast_channel_spy::lock, ast_channel::name, name, option_verbose, ast_channel_spy::read_vol_adjustment, set_volume(), chanspy_translation_helper::spy, start_spying(), ast_channel_spy::status, stop_spying(), ast_frame::subclass, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, chanspy_translation_helper::volfactor, and ast_channel_spy::write_vol_adjustment.

Referenced by chanspy_exec().

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

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

Definition at line 355 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(), group, ast_channel::language, local_channel_walk(), local_get_channel_begin_name(), LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_NOTICE, LOG_WARNING, name, OPT_ARG_ARRAY_SIZE, 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().

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

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 573 of file app_chanspy.c.

References synopsis.

00574 {
00575    return (char *) synopsis;
00576 }

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 585 of file app_chanspy.c.

References ASTERISK_GPL_KEY.

00586 {
00587    return ASTERISK_GPL_KEY;
00588 }

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 568 of file app_chanspy.c.

References app, ast_register_application(), chanspy_exec(), desc, and synopsis.

00569 {
00570    return ast_register_application(app, chanspy_exec, synopsis, desc);
00571 }

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))) {
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 244 of file app_chanspy.c.

References ast_channel_setoption(), AST_OPTION_TXGAIN, and chanspy_translation_helper::volfactor.

Referenced by channel_spy().

00245 {
00246    signed char volume_adjust = volfactor_map[csth->volfactor + 4];
00247 
00248    if (!ast_channel_setoption(chan, AST_OPTION_TXGAIN, &volume_adjust, sizeof(volume_adjust), 0))
00249       csth->volfactor = 0;
00250 }

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 }

static void stop_spying struct ast_channel chan,
struct ast_channel_spy spy
[static]
 

Definition at line 210 of file app_chanspy.c.

References ast_channel_spy_remove(), ast_mutex_lock(), ast_mutex_unlock(), CHANSPY_DONE, ast_channel::lock, and ast_channel_spy::status.

Referenced by channel_spy().

00211 {
00212    /* If our status has changed to DONE, then the channel we're spying on is gone....
00213       DON'T TOUCH IT!!!  RUN AWAY!!! */
00214    if (spy->status == CHANSPY_DONE)
00215       return;
00216 
00217    if (!chan)
00218       return;
00219 
00220    ast_mutex_lock(&chan->lock);
00221    ast_channel_spy_remove(chan, spy);
00222    ast_mutex_unlock(&chan->lock);
00223 };

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 557 of file app_chanspy.c.

References app, ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

00558 {
00559    int res;
00560 
00561    res = ast_unregister_application(app);
00562 
00563    STANDARD_HANGUP_LOCALUSERS;
00564 
00565    return res;
00566 }

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 578 of file app_chanspy.c.

References STANDARD_USECOUNT.

00579 {
00580    int res;
00581    STANDARD_USECOUNT(res);
00582    return res;
00583 }


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.

Referenced by channel_spy().

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.

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 228 of file app_chanspy.c.


Generated on Sun Aug 6 15:03:06 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.2