Fri Jun 19 12:09:56 2009

Asterisk developer's documentation


app_dahdibarge.c File Reference

DAHDI Barge support. 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/cli.h"
#include "asterisk/say.h"
#include "asterisk/utils.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 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 = "Barge in on DAHDI channel 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, }
static char * app = "DAHDIBarge"
static struct ast_module_infoast_module_info = &__mod_info
static char * descrip
static char * synopsis = "Barge in (monitor) DAHDI channel"


Detailed Description

DAHDI Barge support.

Author:
Mark Spencer <markster@digium.com>
Note:
Special thanks to comphealth.com for sponsoring this GPL application.

Definition in file app_dahdibarge.c.


Define Documentation

#define CONF_SIZE   160

Definition at line 66 of file app_dahdibarge.c.

Referenced by conf_run().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 299 of file app_dahdibarge.c.

static void __unreg_module ( void   )  [static]

Definition at line 299 of file app_dahdibarge.c.

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

Definition at line 68 of file app_dahdibarge.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by conf_play(), and conf_run().

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

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

Definition at line 252 of file app_dahdibarge.c.

References ast_channel::_state, ast_answer(), ast_app_getdata(), ast_log(), AST_STATE_UP, ast_strlen_zero(), chan, conf_run(), and LOG_WARNING.

Referenced by load_module().

00253 {
00254    int res = -1;
00255    int retrycnt = 0;
00256    int confflags = 0;
00257    int confno = 0;
00258    char confnostr[80] = "";
00259    
00260    if (!ast_strlen_zero(data)) {
00261       if ((sscanf(data, "DAHDI/%d", &confno) != 1) &&
00262           (sscanf(data, "%d", &confno) != 1)) {
00263          ast_log(LOG_WARNING, "DAHDIBarge Argument (if specified) must be a channel number, not '%s'\n", (char *)data);
00264          return 0;
00265       }
00266    }
00267    
00268    if (chan->_state != AST_STATE_UP)
00269       ast_answer(chan);
00270 
00271    while(!confno && (++retrycnt < 4)) {
00272       /* Prompt user for conference number */
00273       confnostr[0] = '\0';
00274       res = ast_app_getdata(chan, "conf-getchannel",confnostr, sizeof(confnostr) - 1, 0);
00275       if (res <0) goto out;
00276       if (sscanf(confnostr, "%d", &confno) != 1)
00277          confno = 0;
00278    }
00279    if (confno) {
00280       /* XXX Should prompt user for pin if pin is required XXX */
00281       /* Run the conference */
00282       res = conf_run(chan, confno, confflags);
00283    }
00284 out:
00285    /* Do the conference */
00286    return res;
00287 }

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

Definition at line 86 of file app_dahdibarge.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_waitfor_nandfds(), ast_write(), buf, careful_write(), chan, CONF_SIZE, errno, f, ast_channel::fds, ast_frame::flags, LOG_WARNING, ast_channel::name, ast_channel::tech, and ast_channel_tech::type.

Referenced by conf_exec(), run_station(), sla_station_exec(), and sla_trunk_exec().

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

static int load_module ( void   )  [static]

Definition at line 294 of file app_dahdibarge.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 289 of file app_dahdibarge.c.

References ast_unregister_application().

00290 {
00291    return ast_unregister_application(app);
00292 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Barge in on DAHDI channel 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static]

Definition at line 299 of file app_dahdibarge.c.

char* app = "DAHDIBarge" [static]

Definition at line 55 of file app_dahdibarge.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 299 of file app_dahdibarge.c.

char* descrip [static]

Initial value:

 
"  DAHDIBarge([channel]): Barges in on a specified DAHDI\n"
"channel or prompts if one is not specified.  Returns\n"
"-1 when caller user hangs up and is independent of the\n"
"state of the channel being monitored."

Definition at line 59 of file app_dahdibarge.c.

char* synopsis = "Barge in (monitor) DAHDI channel" [static]

Definition at line 57 of file app_dahdibarge.c.


Generated on Fri Jun 19 12:09:56 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7