Mon Nov 24 15:34:22 2008

Asterisk developer's documentation


app_dahdibarge.c File Reference

Zap Barge support. More...

#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/app.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/dahdi_compat.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 channel application")
static int careful_write (int fd, unsigned char *data, int len)
static int conf_run (struct ast_channel *chan, int confno, int confflags)
static int exec (struct ast_channel *chan, void *data, int dahdimode)
static int exec_dahdi (struct ast_channel *chan, void *data)
static int exec_zap (struct ast_channel *chan, void *data)
static int load_module (void)
static int unload_module (void)

Variables

static char * dahdi_app = "DAHDIBarge"
static char * dahdi_descrip
static char * dahdi_synopsis = "Barge in (monitor) DAHDI channel"
static char * zap_app = "ZapBarge"
static char * zap_descrip
static char * zap_synopsis = "Barge in (monitor) Zap channel"


Detailed Description

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

Referenced by conf_run().


Function Documentation

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"Barge in on channel application"   
)

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

Definition at line 84 of file app_dahdibarge.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by conf_play(), and conf_run().

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

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

Definition at line 102 of file app_dahdibarge.c.

References 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(), careful_write(), CONF_SIZE, dahdi_chan_name, errno, f, ast_channel::fds, ast_frame::flags, LOG_DEBUG, LOG_WARNING, ast_channel::tech, and ast_channel_tech::type.

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

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

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

Definition at line 271 of file app_dahdibarge.c.

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

Referenced by exec_dahdi(), exec_warn(), exec_zap(), and load_module().

00272 {
00273    int res=-1;
00274    struct ast_module_user *u;
00275    int retrycnt = 0;
00276    int confflags = 0;
00277    int confno = 0;
00278    char confstr[80] = "";
00279 
00280    u = ast_module_user_add(chan);
00281    
00282    if (!ast_strlen_zero(data)) {
00283       if (dahdimode) {
00284          if ((sscanf(data, "DAHDI/%d", &confno) != 1) &&
00285              (sscanf(data, "%d", &confno) != 1)) {
00286             ast_log(LOG_WARNING, "Argument (if specified) must be a channel number, not '%s'\n", (char *) data);
00287             ast_module_user_remove(u);
00288             return 0;
00289          }
00290       } else {
00291          if ((sscanf(data, "Zap/%d", &confno) != 1) &&
00292              (sscanf(data, "%d", &confno) != 1)) {
00293             ast_log(LOG_WARNING, "Argument (if specified) must be a channel number, not '%s'\n", (char *) data);
00294             ast_module_user_remove(u);
00295             return 0;
00296          }
00297       }
00298    }
00299    
00300    if (chan->_state != AST_STATE_UP)
00301       ast_answer(chan);
00302 
00303    while(!confno && (++retrycnt < 4)) {
00304       /* Prompt user for conference number */
00305       confstr[0] = '\0';
00306       res = ast_app_getdata(chan, "conf-getchannel",confstr, sizeof(confstr) - 1, 0);
00307       if (res <0) goto out;
00308       if (sscanf(confstr, "%d", &confno) != 1)
00309          confno = 0;
00310    }
00311    if (confno) {
00312       /* XXX Should prompt user for pin if pin is required XXX */
00313       /* Run the conference */
00314       res = conf_run(chan, confno, confflags);
00315    }
00316 out:
00317    /* Do the conference */
00318    ast_module_user_remove(u);
00319    return res;
00320 }

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

Definition at line 329 of file app_dahdibarge.c.

References ast_module_user::chan, and exec().

Referenced by load_module().

00330 {
00331    return exec(chan, data, 1);
00332 }

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

Definition at line 322 of file app_dahdibarge.c.

References ast_log(), ast_module_user::chan, exec(), and LOG_WARNING.

Referenced by load_module().

00323 {
00324    ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_app, dahdi_app);
00325    
00326    return exec(chan, data, 0);
00327 }

static int load_module ( void   )  [static]

Definition at line 349 of file app_dahdibarge.c.

References ast_register_application(), CHAN_DAHDI_PLUS_ZAP_MODE, dahdi_chan_mode, exec_dahdi(), and exec_zap().

00350 {
00351    int res = 0;
00352 
00353    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
00354       res |= ast_register_application(dahdi_app, exec_dahdi, dahdi_synopsis, dahdi_descrip);
00355    }
00356 
00357    res |= ast_register_application(zap_app, exec_zap, zap_synopsis, zap_descrip);
00358 
00359    return res;
00360 }

static int unload_module ( void   )  [static]

Definition at line 334 of file app_dahdibarge.c.

References ast_module_user_hangup_all, ast_unregister_application(), CHAN_DAHDI_PLUS_ZAP_MODE, and dahdi_chan_mode.

00335 {
00336    int res = 0;
00337 
00338    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
00339       res |= ast_unregister_application(dahdi_app);
00340    }
00341 
00342    res |= ast_unregister_application(zap_app);
00343    
00344    ast_module_user_hangup_all();
00345 
00346    return res;
00347 }


Variable Documentation

char* dahdi_app = "DAHDIBarge" [static]

Definition at line 64 of file app_dahdibarge.c.

Referenced by exec_warn(), load_module(), and unload_module().

char* dahdi_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 70 of file app_dahdibarge.c.

Referenced by load_module().

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

Definition at line 67 of file app_dahdibarge.c.

Referenced by load_module().

char* zap_app = "ZapBarge" [static]

Definition at line 65 of file app_dahdibarge.c.

Referenced by exec_warn(), load_module(), and unload_module().

char* zap_descrip [static]

Initial value:

 
"  ZapBarge([channel]): Barges in on a specified Zaptel\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 76 of file app_dahdibarge.c.

Referenced by load_module().

char* zap_synopsis = "Barge in (monitor) Zap channel" [static]

Definition at line 68 of file app_dahdibarge.c.

Referenced by load_module().


Generated on Mon Nov 24 15:34:22 2008 for Asterisk - the Open Source PBX by  doxygen 1.4.7