Thu Jul 9 13:40:44 2009

Asterisk developer's documentation


app_dahdiscan.c File Reference

DAHDI Scanner. More...

#include "asterisk.h"
#include <sys/ioctl.h>
#include <dahdi/user.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/app.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"

Go to the source code of this file.

Defines

#define CONF_SIZE   160

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int careful_write (int fd, unsigned char *data, int len)
static int conf_exec (struct ast_channel *chan, void *data)
static int conf_run (struct ast_channel *chan, int confno, int confflags)
static struct ast_channelget_dahdi_channel_locked (int num)
static int load_module (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Scan DAHDI channels application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, }
static char * app = "DAHDIScan"
static const struct ast_module_infoast_module_info = &__mod_info
static char * descrip
static char * synopsis = "Scan DAHDI channels to monitor calls"


Detailed Description

DAHDI Scanner.

Author:
Mark Spencer <markster@digium.com>

Definition in file app_dahdiscan.c.


Define Documentation

#define CONF_SIZE   160

Definition at line 65 of file app_dahdiscan.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 363 of file app_dahdiscan.c.

static void __unreg_module ( void   )  [static]

Definition at line 363 of file app_dahdiscan.c.

static int careful_write ( int  fd,
unsigned char *  data,
int  len 
) [static]

Definition at line 74 of file app_dahdiscan.c.

References ast_log(), errno, and LOG_WARNING.

00075 {
00076    int res;
00077    while(len) {
00078       res = write(fd, data, len);
00079       if (res < 1) {
00080          if (errno != EAGAIN) {
00081             ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno));
00082             return -1;
00083          } else
00084             return 0;
00085       }
00086       len -= res;
00087       data += res;
00088    }
00089    return 0;
00090 }

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

Definition at line 280 of file app_dahdiscan.c.

References ast_channel::_state, ast_answer(), ast_channel_unlock, ast_channel_walk_locked(), ast_copy_string(), AST_DIGIT_ANY, AST_FRAME_DTMF, ast_frfree, ast_read(), ast_say_number(), AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_strlen_zero(), ast_verb, ast_waitfor(), chan, conf_run(), f, get_dahdi_channel_locked(), input(), ast_channel::name, pbx_builtin_getvar_helper(), ast_channel::tech, and ast_channel_tech::type.

00281 {
00282    int res=-1;
00283    int confflags = 0;
00284    int confno = 0;
00285    char confstr[80] = "", *tmp = NULL;
00286    struct ast_channel *tempchan = NULL, *lastchan = NULL,*ichan = NULL;
00287    struct ast_frame *f;
00288    char *desired_group;
00289    int input=0,search_group=0;
00290       
00291    if (chan->_state != AST_STATE_UP)
00292       ast_answer(chan);
00293    
00294    desired_group = ast_strdupa(data);
00295    if(!ast_strlen_zero(desired_group)) {
00296       ast_verb(3, "Scanning for group %s\n", desired_group);
00297       search_group = 1;
00298    }
00299 
00300    for (;;) {
00301       if (ast_waitfor(chan, 100) < 0)
00302          break;
00303       
00304       f = ast_read(chan);
00305       if (!f)
00306          break;
00307       if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) {
00308          ast_frfree(f);
00309          break;
00310       }
00311       ast_frfree(f);
00312       ichan = NULL;
00313       if(input) {
00314          ichan = get_dahdi_channel_locked(input);
00315          input = 0;
00316       }
00317       
00318       tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan);
00319       
00320       if ( !tempchan && !lastchan )
00321          break;
00322       
00323       if (tempchan && search_group) {
00324          const char *mygroup;
00325          if((mygroup = pbx_builtin_getvar_helper(tempchan, "GROUP")) && (!strcmp(mygroup, desired_group))) {
00326             ast_verb(3, "Found Matching Channel %s in group %s\n", tempchan->name, desired_group);
00327          } else {
00328             ast_channel_unlock(tempchan);
00329             lastchan = tempchan;
00330             continue;
00331          }
00332       }
00333       if (tempchan && (!strcmp(tempchan->tech->type, "DAHDI")) && (tempchan != chan) ) {
00334          ast_verb(3, "DAHDI channel %s is in-use, monitoring...\n", tempchan->name);
00335          ast_copy_string(confstr, tempchan->name, sizeof(confstr));
00336          ast_channel_unlock(tempchan);
00337          if ((tmp = strchr(confstr,'-'))) {
00338             *tmp = '\0';
00339          }
00340          confno = atoi(strchr(confstr,'/') + 1);
00341          ast_stopstream(chan);
00342          ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL);
00343          res = conf_run(chan, confno, confflags);
00344          if (res<0) break;
00345          input = res;
00346       } else if (tempchan)
00347          ast_channel_unlock(tempchan);
00348       lastchan = tempchan;
00349    }
00350    return res;
00351 }

static int conf_run ( struct ast_channel chan,
int  confno,
int  confflags 
) [static]

Definition at line 92 of file app_dahdiscan.c.

References ast_debug, AST_FORMAT_ULAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_indicate(), ast_log(), ast_read(), ast_set_read_format(), ast_set_write_format(), ast_verb, ast_waitfor_nandfds(), ast_write(), buf, careful_write(), chan, CONF_SIZE, errno, f, ast_channel::fds, ast_frame::flags, input(), LOG_WARNING, ast_channel::name, ast_channel::tech, and ast_channel_tech::type.

00093 {
00094    int fd;
00095    struct dahdi_confinfo dahdic;
00096    struct ast_frame *f;
00097    struct ast_channel *c;
00098    struct ast_frame fr;
00099    int outfd;
00100    int ms;
00101    int nfds;
00102    int res;
00103    int flags;
00104    int retrydahdi;
00105    int origfd;
00106    int ret = -1;
00107    char input[4];
00108    int ic=0;
00109    
00110    struct dahdi_bufferinfo bi;
00111    char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
00112    char *buf = __buf + AST_FRIENDLY_OFFSET;
00113    
00114    /* Set it into U-law mode (write) */
00115    if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) {
00116       ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name);
00117       goto outrun;
00118    }
00119    
00120    /* Set it into U-law mode (read) */
00121    if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) {
00122       ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name);
00123       goto outrun;
00124    }
00125    ast_indicate(chan, -1);
00126    retrydahdi = strcasecmp(chan->tech->type, "DAHDI");
00127  dahdiretry:
00128    origfd = chan->fds[0];
00129    if (retrydahdi) {
00130       fd = open("/dev/dahdi/pseudo", O_RDWR);
00131       if (fd < 0) {
00132          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
00133          goto outrun;
00134       }
00135       /* Make non-blocking */
00136       flags = fcntl(fd, F_GETFL);
00137       if (flags < 0) {
00138          ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno));
00139          close(fd);
00140             goto outrun;
00141       }
00142       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
00143          ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno));
00144          close(fd);
00145          goto outrun;
00146       }
00147       /* Setup buffering information */
00148       memset(&bi, 0, sizeof(bi));
00149       bi.bufsize = CONF_SIZE;
00150       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
00151       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
00152       bi.numbufs = 4;
00153       if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) {
00154          ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno));
00155          close(fd);
00156          goto outrun;
00157       }
00158         nfds = 1;
00159    } else {
00160       /* XXX Make sure we're not running on a pseudo channel XXX */
00161       fd = chan->fds[0];
00162       nfds = 0;
00163    }
00164    memset(&dahdic, 0, sizeof(dahdic));
00165    /* Check to see if we're in a conference... */
00166         dahdic.chan = 0;
00167         if (ioctl(fd, DAHDI_GETCONF, &dahdic)) {
00168          ast_log(LOG_WARNING, "Error getting conference\n");
00169          close(fd);
00170          goto outrun;
00171         }
00172         if (dahdic.confmode) {
00173          /* Whoa, already in a conference...  Retry... */
00174          if (!retrydahdi) {
00175             ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n");
00176             retrydahdi = 1;
00177             goto dahdiretry;
00178          }
00179         }
00180         memset(&dahdic, 0, sizeof(dahdic));
00181         /* Add us to the conference */
00182         dahdic.chan = 0;
00183         dahdic.confno = confno;
00184         dahdic.confmode = DAHDI_CONF_MONITORBOTH;
00185       
00186         if (ioctl(fd, DAHDI_SETCONF, &dahdic)) {
00187                 ast_log(LOG_WARNING, "Error setting conference\n");
00188                 close(fd);
00189                 goto outrun;
00190         }
00191    ast_debug(1, "Placed channel %s in DAHDI channel %d monitor\n", chan->name, confno);
00192       
00193         for(;;) {
00194          outfd = -1;
00195          ms = -1;
00196          c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
00197          if (c) {
00198             if (c->fds[0] != origfd) {
00199                if (retrydahdi) {
00200                   /* Kill old pseudo */
00201                   close(fd);
00202                }
00203                ast_debug(1, "Ooh, something swapped out under us, starting over\n");
00204                retrydahdi = 0;
00205                                 goto dahdiretry;
00206             }
00207             f = ast_read(c);
00208             if (!f)
00209                break;
00210             if(f->frametype == AST_FRAME_DTMF) {
00211                if(f->subclass == '#') {
00212                   ret = 0;
00213                   break;
00214                }
00215                else if (f->subclass == '*') {
00216                   ret = -1;
00217                   break;
00218                   
00219                }
00220                else {
00221                   input[ic++] = f->subclass;
00222                }
00223                if(ic == 3) {
00224                   input[ic++] = '\0';
00225                   ic=0;
00226                   ret = atoi(input);
00227                   ast_verb(3, "DAHDIscan: change channel to %d\n",ret);
00228                   break;
00229                }
00230             }
00231             
00232             if (fd != chan->fds[0]) {
00233                if (f->frametype == AST_FRAME_VOICE) {
00234                   if (f->subclass == AST_FORMAT_ULAW) {
00235                      /* Carefully write */
00236                                                 careful_write(fd, f->data, f->datalen);
00237                   } else
00238                      ast_log(LOG_WARNING, "Huh?  Got a non-ulaw (%d) frame in the conference\n", f->subclass);
00239                }
00240             }
00241             ast_frfree(f);
00242          } else if (outfd > -1) {
00243             res = read(outfd, buf, CONF_SIZE);
00244             if (res > 0) {
00245                memset(&fr, 0, sizeof(fr));
00246                fr.frametype = AST_FRAME_VOICE;
00247                fr.subclass = AST_FORMAT_ULAW;
00248                fr.datalen = res;
00249                fr.samples = res;
00250                fr.data = buf;
00251                fr.offset = AST_FRIENDLY_OFFSET;
00252                if (ast_write(chan, &fr) < 0) {
00253                   ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
00254                   /* break; */
00255                }
00256             } else
00257                ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno));
00258          }
00259         }
00260    if (f)
00261       ast_frfree(f);
00262         if (fd != chan->fds[0])
00263          close(fd);
00264         else {
00265          /* Take out of conference */
00266          /* Add us to the conference */
00267          dahdic.chan = 0;
00268          dahdic.confno = 0;
00269          dahdic.confmode = 0;
00270          if (ioctl(fd, DAHDI_SETCONF, &dahdic)) {
00271             ast_log(LOG_WARNING, "Error setting conference\n");
00272                 }
00273         }
00274       
00275  outrun:
00276       
00277         return ret;
00278 }

static struct ast_channel* get_dahdi_channel_locked ( int  num  )  [static]

Definition at line 67 of file app_dahdiscan.c.

References ast_get_channel_by_name_locked(), and name.

Referenced by conf_exec().

00067                                                              {
00068    char name[80];
00069    
00070    snprintf(name, sizeof(name), "DAHDI/%d-1", num);
00071    return ast_get_channel_by_name_locked(name);
00072 }

static int load_module ( void   )  [static]

Definition at line 358 of file app_dahdiscan.c.

References AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_register_application, and conf_exec().

static int unload_module ( void   )  [static]

Definition at line 353 of file app_dahdiscan.c.

References ast_unregister_application().

00354 {
00355    return ast_unregister_application(app);
00356 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Scan DAHDI channels application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } [static]

Definition at line 363 of file app_dahdiscan.c.

char* app = "DAHDIScan" [static]

Definition at line 55 of file app_dahdiscan.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 363 of file app_dahdiscan.c.

char* descrip [static]

Initial value:

"  DAHDIScan([group]) allows a call center manager to monitor DAHDI channels in\n"
"a convenient way.  Use '#' to select the next channel and use '*' to exit\n"
"Limit scanning to a channel GROUP by setting the option group argument.\n"

Definition at line 59 of file app_dahdiscan.c.

char* synopsis = "Scan DAHDI channels to monitor calls" [static]

Definition at line 57 of file app_dahdiscan.c.


Generated on Thu Jul 9 13:40:44 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7