Mon Mar 20 08:20:14 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"

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)
int channel_spy (struct ast_channel *chan, struct ast_channel *spyee, int *volfactor, int fd)
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.
ast_channellocal_channel_walk (struct ast_channel *chan)
ast_channellocal_get_channel_begin_name (char *name)
void set_volume (struct ast_channel *chan, struct chanspy_translation_helper *csth)
void * spy_alloc (struct ast_channel *chan, void *data)
int spy_generate (struct ast_channel *chan, void *data, int len, int samples)
void spy_release (struct ast_channel *chan, void *data)
int start_spying (struct ast_channel *chan, struct ast_channel *spychan, struct ast_channel_spy *spy)
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

const char * app = "ChanSpy"
enum { ... }  chanspy_opt_args
enum { ... }  chanspy_opt_flags
const char * chanspy_spy_type = "ChanSpy"
const char * desc
 LOCAL_USER_DECL
ast_generator spygen
 STANDARD_LOCAL_USER
const char * synopsis = "Listen to the audio of an active channel\n"
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 52 of file app_chanspy.c.

Referenced by _while_exec(), chanspy_exec(), and execif_exec().

#define AST_NAME_STRLEN   256
 

Definition at line 51 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 53 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 83 of file app_chanspy.c.

00083      {
00084    OPTION_QUIET    = (1 << 0),   /* Quiet, no announcement */
00085    OPTION_BRIDGED   = (1 << 1),  /* Only look at bridged calls */
00086    OPTION_VOLUME    = (1 << 2),  /* Specify initial volume */
00087    OPTION_GROUP     = (1 << 3),  /* Only look at channels in group */
00088    OPTION_RECORD    = (1 << 4),  /* Record */
00089 } chanspy_opt_flags;

anonymous enum
 

Enumeration values:
OPT_ARG_VOLUME 
OPT_ARG_GROUP 
OPT_ARG_RECORD 
OPT_ARG_ARRAY_SIZE 

Definition at line 91 of file app_chanspy.c.

00091      {
00092    OPT_ARG_VOLUME = 0,
00093    OPT_ARG_GROUP,
00094    OPT_ARG_RECORD,
00095    OPT_ARG_ARRAY_SIZE,
00096 } chanspy_opt_args;


Function Documentation

AST_APP_OPTIONS chanspy_opts   ) 
 

AST_MUTEX_DEFINE_STATIC modlock   ) 
 

int channel_spy struct ast_channel chan,
struct ast_channel spyee,
int *  volfactor,
int  fd
[static]
 

Definition at line 251 of file app_chanspy.c.

References ast_activate_generator(), ast_check_hangup(), ast_deactivate_generator(), 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_TRIGGER_NONE, ast_channel_spy_queue::format, ast_frame::frametype, ast_channel_spy::lock, ast_channel::name, name, option_verbose, ast_channel_spy::read_queue, ast_channel_spy::read_vol_adjustment, set_volume(), chanspy_translation_helper::spy, spygen, start_spying(), stop_spying(), ast_frame::subclass, ast_channel_spy::type, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, chanspy_translation_helper::volfactor, and ast_channel_spy::write_vol_adjustment.

Referenced by chanspy_exec().

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

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

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

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

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 572 of file app_chanspy.c.

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

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

00585 {
00586    return ASTERISK_GPL_KEY;
00587 }

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

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

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

struct ast_channel* local_channel_walk struct ast_channel chan  )  [static]
 

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

00117 {
00118    struct ast_channel *ret;
00119    ast_mutex_lock(&modlock);  
00120    if ((ret = ast_channel_walk_locked(chan))) {
00121       ast_mutex_unlock(&ret->lock);
00122    }
00123    ast_mutex_unlock(&modlock);         
00124    return ret;
00125 }

struct ast_channel* local_get_channel_begin_name char *  name  )  [static]
 

Definition at line 127 of file app_chanspy.c.

References ast_mutex_lock(), ast_mutex_unlock(), local_channel_walk(), name, and ast_channel::name.

Referenced by chanspy_exec().

00128 {
00129    struct ast_channel *chan, *ret = NULL;
00130    ast_mutex_lock(&modlock);
00131    chan = local_channel_walk(NULL);
00132    while (chan) {
00133       if (!strncmp(chan->name, name, strlen(name))) {
00134          ret = chan;
00135          break;
00136       }
00137       chan = local_channel_walk(chan);
00138    }
00139    ast_mutex_unlock(&modlock);
00140    
00141    return ret;
00142 }

void set_volume struct ast_channel chan,
struct chanspy_translation_helper csth
[static]
 

Definition at line 243 of file app_chanspy.c.

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

Referenced by channel_spy().

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

void* spy_alloc struct ast_channel chan,
void *  data
[static]
 

Definition at line 144 of file app_chanspy.c.

00145 {
00146    /* just store the data pointer in the channel structure */
00147    return data;
00148 }

int spy_generate struct ast_channel chan,
void *  data,
int  len,
int  samples
[static]
 

Definition at line 155 of file app_chanspy.c.

References ast_channel_spy_read_frame(), ast_frfree(), ast_mutex_lock(), ast_mutex_unlock(), ast_write(), ast_frame::data, ast_frame::datalen, chanspy_translation_helper::fd, ast_channel_spy::lock, and chanspy_translation_helper::spy.

00156 {
00157    struct chanspy_translation_helper *csth = data;
00158    struct ast_frame *f;
00159       
00160    if (csth->spy.status != CHANSPY_RUNNING)
00161       /* Channel is already gone more than likely */
00162       return -1;
00163 
00164    ast_mutex_lock(&csth->spy.lock);
00165    f = ast_channel_spy_read_frame(&csth->spy, samples);
00166    ast_mutex_unlock(&csth->spy.lock);
00167       
00168    if (!f)
00169       return 0;
00170       
00171    if (ast_write(chan, f)) {
00172       ast_frfree(f);
00173       return -1;
00174    }
00175 
00176    if (csth->fd)
00177       write(csth->fd, f->data, f->datalen);
00178 
00179    ast_frfree(f);
00180 
00181    return 0;
00182 }

void spy_release struct ast_channel chan,
void *  data
[static]
 

Definition at line 150 of file app_chanspy.c.

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

int start_spying struct ast_channel chan,
struct ast_channel spychan,
struct ast_channel_spy spy
[static]
 

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

00192 {
00193    int res;
00194    struct ast_channel *peer;
00195 
00196    ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan->name, chan->name);
00197 
00198    ast_mutex_lock(&chan->lock);
00199    res = ast_channel_spy_add(chan, spy);
00200    ast_mutex_unlock(&chan->lock);
00201 
00202    if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan))) {
00203       ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);  
00204    }
00205 
00206    return res;
00207 }

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

Definition at line 209 of file app_chanspy.c.

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

Referenced by channel_spy().

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

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

References app, and ast_unregister_application().

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

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

References STANDARD_USECOUNT.

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


Variable Documentation

const char* app = "ChanSpy" [static]
 

Definition at line 56 of file app_chanspy.c.

Referenced by load_module(), and unload_module().

enum { ... } chanspy_opt_args
 

enum { ... } chanspy_opt_flags
 

const char* chanspy_spy_type = "ChanSpy" [static]
 

Definition at line 81 of file app_chanspy.c.

const char* desc [static]
 

Definition at line 57 of file app_chanspy.c.

Referenced by load_module().

LOCAL_USER_DECL
 

Definition at line 107 of file app_chanspy.c.

struct ast_generator spygen [static]
 

Initial value:

 {
   .alloc = spy_alloc,
   .release = spy_release,
   .generate = spy_generate, 
}

Definition at line 185 of file app_chanspy.c.

Referenced by channel_spy().

STANDARD_LOCAL_USER
 

Definition at line 106 of file app_chanspy.c.

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

Definition at line 55 of file app_chanspy.c.

Referenced by load_module().

signed char volfactor_map[] [static]
 

Definition at line 227 of file app_chanspy.c.

Referenced by set_volume().


Generated on Mon Mar 20 08:20:14 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1