Sat Apr 12 07:12:33 2008

Asterisk developer's documentation


app_zapbarge.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 <zaptel/zaptel.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 dependency graph for app_zapbarge.c:

Go to the source code of this file.

Defines

#define CONF_SIZE   160

Functions

 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Barge in on Zap channel application")
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 char * app = "ZapBarge"
static char * descrip
static char * 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_zapbarge.c.


Define Documentation

#define CONF_SIZE   160

Definition at line 74 of file app_zapbarge.c.


Function Documentation

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

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

Definition at line 76 of file app_zapbarge.c.

References ast_log(), errno, and LOG_WARNING.

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

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

Definition at line 260 of file app_zapbarge.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(), conf_run(), and LOG_WARNING.

00261 {
00262    int res=-1;
00263    struct ast_module_user *u;
00264    int retrycnt = 0;
00265    int confflags = 0;
00266    int confno = 0;
00267    char confstr[80] = "";
00268 
00269    u = ast_module_user_add(chan);
00270    
00271    if (!ast_strlen_zero(data)) {
00272       if ((sscanf(data, "Zap/%d", &confno) != 1) &&
00273           (sscanf(data, "%d", &confno) != 1)) {
00274          ast_log(LOG_WARNING, "ZapBarge Argument (if specified) must be a channel number, not '%s'\n", (char *)data);
00275          ast_module_user_remove(u);
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       confstr[0] = '\0';
00286       res = ast_app_getdata(chan, "conf-getchannel",confstr, sizeof(confstr) - 1, 0);
00287       if (res <0) goto out;
00288       if (sscanf(confstr, "%d", &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    ast_module_user_remove(u);
00299    return res;
00300 }

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

Definition at line 94 of file app_zapbarge.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, ast_frame::data, ast_frame::datalen, errno, f, ast_channel::fds, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_frame::offset, ast_frame::samples, ast_frame::subclass, ast_channel::tech, and ast_channel_tech::type.

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

static int load_module ( void   )  [static]

Definition at line 313 of file app_zapbarge.c.

References ast_register_application(), and conf_exec().

00314 {
00315    return ast_register_application(app, conf_exec, synopsis, descrip);
00316 }

static int unload_module ( void   )  [static]

Definition at line 302 of file app_zapbarge.c.

References ast_module_user_hangup_all, and ast_unregister_application().

00303 {
00304    int res;
00305    
00306    res = ast_unregister_application(app);
00307    
00308    ast_module_user_hangup_all();
00309 
00310    return res; 
00311 }


Variable Documentation

char* app = "ZapBarge" [static]

Definition at line 63 of file app_zapbarge.c.

char* descrip [static]

Initial value:

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

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

Definition at line 65 of file app_zapbarge.c.


Generated on Sat Apr 12 07:12:33 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.5