Sat Nov 25 00:45:43 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"

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
struct {
   int   alarm
   char *   description
   unsigned int   event_log:1
   enum queue_result   id
   char *   name
   char *   name
   char *   name
   rtpPayloadType   payloadType
   unsigned int   queue_log:1
   char *   subtype
   char *   text
   char *   type
   int   val
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(), 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_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.

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    ast_mutex_lock(&csth.spy.lock);
00333    if (csth.spy.chan) {
00334       csth.spy.status = CHANSPY_DONE;
00335       ast_mutex_lock(&csth.spy.chan->lock);
00336       ast_channel_spy_remove(csth.spy.chan, &csth.spy);
00337       ast_mutex_unlock(&csth.spy.chan->lock);
00338    }
00339    ast_mutex_unlock(&csth.spy.lock);
00340 
00341    if (option_verbose > 1)
00342       ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name);
00343 
00344    ast_channel_spy_free(&csth.spy);
00345 
00346    return running;
00347 }

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

Definition at line 349 of file app_chanspy.c.

References ast_answer(), ast_app_parse_options(), ast_app_separate_args(), ast_clear_flag, ast_config_AST_MONITOR_DIR, AST_FLAG_SPYING, AST_FORMAT_SLINEAR, ast_log(), AST_NAME_STRLEN, ast_set_flag, ast_set_read_format(), ast_set_write_format(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitstream(), ast_flags::flags, ast_channel::language, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_NOTICE, LOG_WARNING, name, OPT_ARG_ARRAY_SIZE, OPT_ARG_GROUP, OPT_ARG_RECORD, OPT_ARG_VOLUME, OPTION_BRIDGED, OPTION_GROUP, OPTION_QUIET, OPTION_RECORD, OPTION_VOLUME, ast_channel::readformat, and ast_channel::writeformat.

Referenced by load_module().

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

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 567 of file app_chanspy.c.

00568 {
00569    return (char *) synopsis;
00570 }

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

References ASTERISK_GPL_KEY.

00580 {
00581    return ASTERISK_GPL_KEY;
00582 }

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

References ast_register_application(), and chanspy_exec().

00563 {
00564    return ast_register_application(app, chanspy_exec, synopsis, desc);
00565 }

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

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

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

00552 {
00553    int res;
00554 
00555    res = ast_unregister_application(app);
00556 
00557    STANDARD_HANGUP_LOCALUSERS;
00558 
00559    return res;
00560 }

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

References STANDARD_USECOUNT.

00573 {
00574    int res;
00575    STANDARD_USECOUNT(res);
00576    return res;
00577 }


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 Sat Nov 25 00:45:43 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.6