Thu Oct 11 06:47:32 2012

Asterisk developer's documentation


app_dahdiscan.c File Reference

DAHDI Scanner. More...

#include "asterisk.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"
#include "asterisk/options.h"

Include dependency graph for app_dahdiscan.c:

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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
static char * app = "DAHDIScan"
static struct ast_module_infoast_module_info = &__mod_info


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 73 of file app_dahdiscan.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 377 of file app_dahdiscan.c.

static void __unreg_module ( void   )  [static]

Definition at line 377 of file app_dahdiscan.c.

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

Definition at line 82 of file app_dahdiscan.c.

References ast_log(), errno, and LOG_WARNING.

00083 {
00084    int res;
00085    while (len) {
00086       res = write(fd, data, len);
00087       if (res < 1) {
00088          if (errno != EAGAIN) {
00089             ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno));
00090             return -1;
00091          } else {
00092             return 0;
00093          }
00094       }
00095       len -= res;
00096       data += res;
00097    }
00098    return 0;
00099 }

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

Definition at line 290 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(), conf_run(), f, ast_frame::frametype, get_dahdi_channel_locked(), input(), ast_channel::language, ast_channel::name, pbx_builtin_getvar_helper(), ast_frame::subclass, ast_channel::tech, and ast_channel_tech::type.

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

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

Definition at line 101 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(), CONF_SIZE, ast_frame::data, ast_frame::datalen, errno, f, ast_channel::fds, ast_frame::flags, ast_frame::frametype, input(), LOG_WARNING, ast_channel::name, ast_frame::offset, ast_frame::ptr, ast_frame::samples, ast_frame::subclass, ast_channel::tech, and ast_channel_tech::type.

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

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

Definition at line 75 of file app_dahdiscan.c.

References ast_get_channel_by_name_locked(), and name.

Referenced by conf_exec().

00075                                                              {
00076    char name[80];
00077    
00078    snprintf(name, sizeof(name), "DAHDI/%d-1", num);
00079    return ast_get_channel_by_name_locked(name);
00080 }

static int load_module ( void   )  [static]

static int unload_module ( void   )  [static]

Definition at line 367 of file app_dahdiscan.c.

References ast_unregister_application().

00368 {
00369    return ast_unregister_application(app);
00370 }


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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 377 of file app_dahdiscan.c.

char* app = "DAHDIScan" [static]

Definition at line 71 of file app_dahdiscan.c.

Definition at line 377 of file app_dahdiscan.c.


Generated on Thu Oct 11 06:47:32 2012 for Asterisk - the Open Source PBX by  doxygen 1.5.6