Sat Feb 11 06:33:36 2012

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"

Include dependency graph for app_dahdibarge.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, const char *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_LOAD_ORDER , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static const char app [] = "DAHDIBarge"
static struct ast_module_infoast_module_info = &__mod_info


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 78 of file app_dahdibarge.c.

Referenced by conf_run().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 311 of file app_dahdibarge.c.

static void __unreg_module ( void   )  [static]

Definition at line 311 of file app_dahdibarge.c.

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

Definition at line 80 of file app_dahdibarge.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by conf_play(), and conf_run().

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

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

Definition at line 264 of file app_dahdibarge.c.

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

Referenced by load_module().

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

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

Definition at line 98 of file app_dahdibarge.c.

References ast_channel_name(), ast_debug, ast_format_set(), AST_FORMAT_ULAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_indicate(), ast_log(), ast_read(), ast_set_read_format_by_id(), ast_set_write_format_by_id(), ast_waitfor_nandfds(), ast_write(), careful_write(), CONF_SIZE, ast_frame::data, ast_frame::datalen, errno, f, ast_channel::fds, ast_frame::flags, ast_frame_subclass::format, ast_frame::frametype, ast_format::id, ast_frame_subclass::integer, LOG_WARNING, ast_frame::offset, ast_frame::ptr, ast_frame::samples, ast_frame::subclass, ast_channel::tech, and ast_channel_tech::type.

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

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

static int load_module ( void   )  [static]

static int unload_module ( void   )  [static]

Definition at line 301 of file app_dahdibarge.c.

References ast_unregister_application().

00302 {
00303    return ast_unregister_application(app);
00304 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 311 of file app_dahdibarge.c.

const char app[] = "DAHDIBarge" [static]

Definition at line 76 of file app_dahdibarge.c.

Definition at line 311 of file app_dahdibarge.c.


Generated on Sat Feb 11 06:33:37 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6