Sat Apr 26 2014 22:01:45

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_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,
const char *  data 
) [static]

Definition at line 264 of file app_dahdibarge.c.

References 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 (ast_channel_state(chan) != 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 98 of file app_dahdibarge.c.

References ast_channel_fd(), ast_channel_name(), ast_channel_tech(), 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_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, and 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_by_id(chan, AST_FORMAT_ULAW) < 0) {
      ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", ast_channel_name(chan));
      goto outrun;
   }

   /* Set it into U-law mode (read) */
   if (ast_set_read_format_by_id(chan, AST_FORMAT_ULAW) < 0) {
      ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", ast_channel_name(chan));
      goto outrun;
   }
   ast_indicate(chan, -1);
   retrydahdi = strcasecmp(ast_channel_tech(chan)->type, "DAHDI");
dahdiretry:
   origfd = ast_channel_fd(chan, 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 = ast_channel_fd(chan, 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", ast_channel_name(chan), confno);

   for(;;) {
      outfd = -1;
      ms = -1;
      c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
      if (c) {
         if (ast_channel_fd(c, 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.integer == '#')) {
            ret = 0;
            ast_frfree(f);
            break;
         } else if (fd != ast_channel_fd(chan, 0)) {
            if (f->frametype == AST_FRAME_VOICE) {
               if (f->subclass.format.id == AST_FORMAT_ULAW) {
                  /* Carefully write */
                  careful_write(fd, f->data.ptr, f->datalen);
               } else
                  ast_log(LOG_WARNING, "Huh?  Got a non-ulaw (%s) frame in the conference\n", ast_getformatname(&f->subclass.format));
            }
         }
         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;
            ast_format_set(&fr.subclass.format, AST_FORMAT_ULAW, 0);
            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 != ast_channel_fd(chan, 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 301 of file app_dahdibarge.c.

References ast_unregister_application().


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.