Thu Sep 7 01:03:07 2017

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

 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Barge in on DAHDI channel application")
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 const char app [] = "DAHDIBarge"

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

Referenced by conf_run().


Function Documentation

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"Barge in on DAHDI channel application"   
)
static int careful_write ( int  fd,
unsigned char *  data,
int  len 
) [static]

Definition at line 79 of file app_dahdibarge.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by conf_run().

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

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

Definition at line 263 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().

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

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

Definition at line 97 of file app_dahdibarge.c.

References ast_debug, 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(), ast_set_write_format(), ast_waitfor_nandfds(), ast_write(), careful_write(), ast_frame_subclass::codec, CONF_SIZE, ast_frame::data, ast_frame::datalen, errno, f, ast_channel::fds, ast_frame::flags, ast_frame::frametype, 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().

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

static int load_module ( void   )  [static]
static int unload_module ( void   )  [static]

Definition at line 300 of file app_dahdibarge.c.

References ast_unregister_application().

00301 {
00302    return ast_unregister_application(app);
00303 }


Variable Documentation

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

Definition at line 75 of file app_dahdibarge.c.


Generated on 7 Sep 2017 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1