Wed Oct 28 15:47:59 2009

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"
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_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(), ast_channel_spy::chan, CHANSPY_DONE, CHANSPY_FORMAT_AUDIO, CHANSPY_MIXAUDIO, CHANSPY_READ_VOLADJUST, CHANSPY_RUNNING, CHANSPY_TRIGGER_NONE, CHANSPY_WRITE_VOLADJUST, chanspy_translation_helper::fd, ast_channel_spy_queue::format, ast_frame::frametype, ast_channel::lock, 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, start_spying(), ast_channel_spy::status, ast_frame::subclass, ast_channel_spy::type, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, chanspy_translation_helper::volfactor, ast_channel_spy::write_queue, and ast_channel_spy::write_vol_adjustment.

Referenced by chanspy_exec().

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

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

Definition at line 350 of file app_chanspy.c.

References ALL_DONE, ast_answer(), ast_app_parse_options(), ast_app_separate_args(), ast_bridged_channel(), ast_channel_setoption(), ast_check_hangup(), ast_clear_flag, ast_config_AST_MONITOR_DIR, ast_fileexists(), AST_FLAG_SPYING, AST_FLAGS_ALL, AST_FORMAT_SLINEAR, ast_log(), AST_NAME_STRLEN, AST_OPTION_TXGAIN, ast_say_character_str(), ast_say_digits(), ast_set_flag, ast_set_read_format(), ast_set_write_format(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), ast_waitstream(), channel_spy(), group, ast_channel::language, local_channel_walk(), local_get_channel_begin_name(), LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::name, name, OPT_ARG_ARRAY_SIZE, OPT_ARG_GROUP, OPT_ARG_RECORD, OPT_ARG_VOLUME, OPTION_BRIDGED, OPTION_GROUP, OPTION_QUIET, OPTION_RECORD, OPTION_VOLUME, pbx_builtin_getvar_helper(), ast_channel::readformat, and ast_channel::writeformat.

Referenced by load_module().

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

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 570 of file app_chanspy.c.

00571 {
00572    return (char *) synopsis;
00573 }

char* key ( void   ) 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 582 of file app_chanspy.c.

References ASTERISK_GPL_KEY.

00583 {
00584    return ASTERISK_GPL_KEY;
00585 }

int load_module ( void   ) 

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.
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.
TE STUFF END

Definition at line 565 of file app_chanspy.c.

References ast_register_application(), and chanspy_exec().

00566 {
00567    return ast_register_application(app, chanspy_exec, synopsis, desc);
00568 }

static struct ast_channel* local_channel_walk ( struct ast_channel chan  )  [static, read]

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, read]

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

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

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

int usecount ( void   ) 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 575 of file app_chanspy.c.

References STANDARD_USECOUNT.

00576 {
00577    int res;
00578    STANDARD_USECOUNT(res);
00579    return res;
00580 }


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.

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.

Definition at line 107 of file app_chanspy.c.

const char* synopsis = "Listen to the audio of an active channel" [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 Wed Oct 28 15:47:59 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6