Thu Apr 28 2011 17:15:27

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, 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
__MODULE_INFO_SECTION 
__mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Barge in on DAHDI channel application" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
static 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 75 of file app_dahdibarge.c.

Referenced by conf_run().


Function Documentation

static void __reg_module ( void  ) [static]

Definition at line 308 of file app_dahdibarge.c.

static void __unreg_module ( void  ) [static]

Definition at line 308 of file app_dahdibarge.c.

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

Definition at line 77 of file app_dahdibarge.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by conf_run().

{
   int res;
   while(len) {
      res = write(fd, data, len);
      if (res < 1) {
         if (errno != EAGAIN) {
            ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno));
            return -1;
         } else
            return 0;
      }
      len -= res;
      data += res;
   }
   return 0;
}
static int conf_exec ( struct ast_channel chan,
void *  data 
) [static]

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

{
   int res = -1;
   int retrycnt = 0;
   int confflags = 0;
   int confno = 0;
   char confnostr[80] = "";
   
   if (!ast_strlen_zero(data)) {
      if ((sscanf(data, "DAHDI/%30d", &confno) != 1) &&
          (sscanf(data, "%30d", &confno) != 1)) {
         ast_log(LOG_WARNING, "DAHDIBarge Argument (if specified) must be a channel number, not '%s'\n", (char *)data);
         return 0;
      }
   }
   
   if (chan->_state != AST_STATE_UP)
      ast_answer(chan);

   while(!confno && (++retrycnt < 4)) {
      /* Prompt user for conference number */
      confnostr[0] = '\0';
      res = ast_app_getdata(chan, "conf-getchannel",confnostr, sizeof(confnostr) - 1, 0);
      if (res <0) goto out;
      if (sscanf(confnostr, "%30d", &confno) != 1)
         confno = 0;
   }
   if (confno) {
      /* XXX Should prompt user for pin if pin is required XXX */
      /* Run the conference */
      res = conf_run(chan, confno, confflags);
   }
out:
   /* Do the conference */
   return res;
}
static int conf_run ( struct ast_channel chan,
int  confno,
int  confflags 
) [static]

Definition at line 95 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(), CONF_SIZE, ast_frame::data, ast_frame::datalen, errno, f, ast_channel::fds, ast_frame::flags, ast_frame::frametype, 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.

Referenced by conf_exec().

{
   int fd;
   struct dahdi_confinfo dahdic;
   struct ast_frame *f;
   struct ast_channel *c;
   struct ast_frame fr;
   int outfd;
   int ms;
   int nfds;
   int res;
   int flags;
   int retrydahdi;
   int origfd;
   int ret = -1;

   struct dahdi_bufferinfo bi;
   char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
   char *buf = __buf + AST_FRIENDLY_OFFSET;

   /* Set it into U-law mode (write) */
   if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) {
      ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name);
      goto outrun;
   }

   /* Set it into U-law mode (read) */
   if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) {
      ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name);
      goto outrun;
   }
   ast_indicate(chan, -1);
   retrydahdi = strcasecmp(chan->tech->type, "DAHDI");
dahdiretry:
   origfd = chan->fds[0];
   if (retrydahdi) {
      fd = open("/dev/dahdi/pseudo", O_RDWR);
      if (fd < 0) {
         ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
         goto outrun;
      }
      /* Make non-blocking */
      flags = fcntl(fd, F_GETFL);
      if (flags < 0) {
         ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno));
         close(fd);
         goto outrun;
      }
      if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
         ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno));
         close(fd);
         goto outrun;
      }
      /* Setup buffering information */
      memset(&bi, 0, sizeof(bi));
      bi.bufsize = CONF_SIZE;
      bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
      bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
      bi.numbufs = 4;
      if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) {
         ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno));
         close(fd);
         goto outrun;
      }
      nfds = 1;
   } else {
      /* XXX Make sure we're not running on a pseudo channel XXX */
      fd = chan->fds[0];
      nfds = 0;
   }
   memset(&dahdic, 0, sizeof(dahdic));
   /* Check to see if we're in a conference... */
   dahdic.chan = 0;  
   if (ioctl(fd, DAHDI_GETCONF, &dahdic)) {
      ast_log(LOG_WARNING, "Error getting conference\n");
      close(fd);
      goto outrun;
   }
   if (dahdic.confmode) {
      /* Whoa, already in a conference...  Retry... */
      if (!retrydahdi) {
         ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n");
         retrydahdi = 1;
         goto dahdiretry;
      }
   }
   memset(&dahdic, 0, sizeof(dahdic));
   /* Add us to the conference */
   dahdic.chan = 0;  
   dahdic.confno = confno;
   dahdic.confmode = DAHDI_CONF_MONITORBOTH;

   if (ioctl(fd, DAHDI_SETCONF, &dahdic)) {
      ast_log(LOG_WARNING, "Error setting conference\n");
      close(fd);
      goto outrun;
   }
   ast_debug(1, "Placed channel %s in DAHDI channel %d monitor\n", chan->name, confno);

   for(;;) {
      outfd = -1;
      ms = -1;
      c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
      if (c) {
         if (c->fds[0] != origfd) {
            if (retrydahdi) {
               /* Kill old pseudo */
               close(fd);
            }
            ast_debug(1, "Ooh, something swapped out under us, starting over\n");
            retrydahdi = 0;
            goto dahdiretry;
         }
         f = ast_read(c);
         if (!f) 
            break;
         if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
            ret = 0;
            ast_frfree(f);
            break;
         } else if (fd != chan->fds[0]) {
            if (f->frametype == AST_FRAME_VOICE) {
               if (f->subclass == AST_FORMAT_ULAW) {
                  /* Carefully write */
                  careful_write(fd, f->data.ptr, f->datalen);
               } else
                  ast_log(LOG_WARNING, "Huh?  Got a non-ulaw (%d) frame in the conference\n", f->subclass);
            }
         }
         ast_frfree(f);
      } else if (outfd > -1) {
         res = read(outfd, buf, CONF_SIZE);
         if (res > 0) {
            memset(&fr, 0, sizeof(fr));
            fr.frametype = AST_FRAME_VOICE;
            fr.subclass = AST_FORMAT_ULAW;
            fr.datalen = res;
            fr.samples = res;
            fr.data.ptr = buf;
            fr.offset = AST_FRIENDLY_OFFSET;
            if (ast_write(chan, &fr) < 0) {
               ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
               /* break; */
            }
         } else 
            ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno));
      }
   }
   if (fd != chan->fds[0])
      close(fd);
   else {
      /* Take out of conference */
      /* Add us to the conference */
      dahdic.chan = 0;  
      dahdic.confno = 0;
      dahdic.confmode = 0;
      if (ioctl(fd, DAHDI_SETCONF, &dahdic)) {
         ast_log(LOG_WARNING, "Error setting conference\n");
      }
   }

outrun:

   return ret;
}
static int unload_module ( void  ) [static]

Definition at line 298 of file app_dahdibarge.c.

References ast_unregister_application().


Variable Documentation

struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Barge in on DAHDI channel application" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 308 of file app_dahdibarge.c.

char* app = "DAHDIBarge" [static]

Definition at line 73 of file app_dahdibarge.c.

Definition at line 308 of file app_dahdibarge.c.