Mon Mar 20 08:25:49 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

app_zapbarge.c File Reference

Zap Barge support. More...

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <zaptel.h>
#include "asterisk.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"

Go to the source code of this file.

Defines

#define CONF_SIZE   160

Functions

int careful_write (int fd, unsigned char *data, int len)
int conf_exec (struct ast_channel *chan, void *data)
int conf_run (struct ast_channel *chan, int confno, int confflags)
char * description (void)
 Provides a description of the module.
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module (void)
 Initialize the module.
int unload_module (void)
 Cleanup all module structures, sockets, etc.
int usecount (void)
 Provides a usecount.

Variables

char * app = "ZapBarge"
char * descrip
 LOCAL_USER_DECL
 STANDARD_LOCAL_USER
char * synopsis = "Barge in (monitor) Zap channel"
char * tdesc = "Barge in on Zap channel application"


Detailed Description

Zap Barge support.

Definition in file app_zapbarge.c.


Define Documentation

#define CONF_SIZE   160
 

Definition at line 77 of file app_zapbarge.c.


Function Documentation

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

Definition at line 79 of file app_zapbarge.c.

References ast_log(), and LOG_WARNING.

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 }

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

Definition at line 262 of file app_zapbarge.c.

References ast_channel::_state, ast_answer(), ast_app_getdata(), ast_log(), ast_strlen_zero(), conf_run(), LOCAL_USER_ADD, LOCAL_USER_REMOVE, and LOG_WARNING.

Referenced by load_module().

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

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

Definition at line 97 of file app_zapbarge.c.

References AST_FORMAT_ULAW, ast_frfree(), 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, ast_channel::fds, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_frame::offset, ast_frame::samples, ast_frame::subclass, and ast_channel::type.

00098 {
00099    int fd;
00100    struct zt_confinfo ztc;
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 retryzap;
00110    int origfd;
00111    int ret = -1;
00112 
00113    ZT_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    retryzap = strcasecmp(chan->type, "Zap");
00130 zapretry:
00131    origfd = chan->fds[0];
00132    if (retryzap) {
00133       fd = open("/dev/zap/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 = ZT_POLICY_IMMEDIATE;
00154       bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
00155       bi.numbufs = 4;
00156       if (ioctl(fd, ZT_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(&ztc, 0, sizeof(ztc));
00168    /* Check to see if we're in a conference... */
00169    ztc.chan = 0;  
00170    if (ioctl(fd, ZT_GETCONF, &ztc)) {
00171       ast_log(LOG_WARNING, "Error getting conference\n");
00172       close(fd);
00173       goto outrun;
00174    }
00175    if (ztc.confmode) {
00176       /* Whoa, already in a conference...  Retry... */
00177       if (!retryzap) {
00178          ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n");
00179          retryzap = 1;
00180          goto zapretry;
00181       }
00182    }
00183    memset(&ztc, 0, sizeof(ztc));
00184    /* Add us to the conference */
00185    ztc.chan = 0;  
00186    ztc.confno = confno;
00187    ztc.confmode = ZT_CONF_MONITORBOTH;
00188 
00189    if (ioctl(fd, ZT_SETCONF, &ztc)) {
00190       ast_log(LOG_WARNING, "Error setting conference\n");
00191       close(fd);
00192       goto outrun;
00193    }
00194    ast_log(LOG_DEBUG, "Placed channel %s in ZAP 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 (retryzap) {
00203                /* Kill old pseudo */
00204                close(fd);
00205             }
00206             ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n");
00207             retryzap = 0;
00208             goto zapretry;
00209          }
00210          f = ast_read(c);
00211          if (!f) 
00212             break;
00213          if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
00214             ret = 0;
00215             break;
00216          } else if (fd != chan->fds[0]) {
00217             if (f->frametype == AST_FRAME_VOICE) {
00218                if (f->subclass == AST_FORMAT_ULAW) {
00219                   /* Carefully write */
00220                   careful_write(fd, f->data, f->datalen);
00221                } else
00222                   ast_log(LOG_WARNING, "Huh?  Got a non-ulaw (%d) frame in the conference\n", f->subclass);
00223             }
00224          }
00225          ast_frfree(f);
00226       } else if (outfd > -1) {
00227          res = read(outfd, buf, CONF_SIZE);
00228          if (res > 0) {
00229             memset(&fr, 0, sizeof(fr));
00230             fr.frametype = AST_FRAME_VOICE;
00231             fr.subclass = AST_FORMAT_ULAW;
00232             fr.datalen = res;
00233             fr.samples = res;
00234             fr.data = buf;
00235             fr.offset = AST_FRIENDLY_OFFSET;
00236             if (ast_write(chan, &fr) < 0) {
00237                ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
00238                /* break; */
00239             }
00240          } else 
00241             ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno));
00242       }
00243    }
00244    if (fd != chan->fds[0])
00245       close(fd);
00246    else {
00247       /* Take out of conference */
00248       /* Add us to the conference */
00249       ztc.chan = 0;  
00250       ztc.confno = 0;
00251       ztc.confmode = 0;
00252       if (ioctl(fd, ZT_SETCONF, &ztc)) {
00253          ast_log(LOG_WARNING, "Error setting conference\n");
00254       }
00255    }
00256 
00257 outrun:
00258 
00259    return ret;
00260 }

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 320 of file app_zapbarge.c.

00321 {
00322    return tdesc;
00323 }

char* key void   ) 
 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 332 of file app_zapbarge.c.

00333 {
00334    return ASTERISK_GPL_KEY;
00335 }

int load_module void   ) 
 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 315 of file app_zapbarge.c.

References app, ast_register_application(), conf_exec(), descrip, and synopsis.

00316 {
00317    return ast_register_application(app, conf_exec, synopsis, descrip);
00318 }

int unload_module void   ) 
 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 304 of file app_zapbarge.c.

References app, and ast_unregister_application().

00305 {
00306    int res;
00307    
00308    res = ast_unregister_application(app);
00309    
00310    STANDARD_HANGUP_LOCALUSERS;
00311 
00312    return res; 
00313 }

int usecount void   ) 
 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 325 of file app_zapbarge.c.

References STANDARD_USECOUNT.

00326 {
00327    int res;
00328    STANDARD_USECOUNT(res);
00329    return res;
00330 }


Variable Documentation

char* app = "ZapBarge" [static]
 

Definition at line 61 of file app_zapbarge.c.

Referenced by load_module(), and unload_module().

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 65 of file app_zapbarge.c.

Referenced by load_module().

LOCAL_USER_DECL
 

Definition at line 74 of file app_zapbarge.c.

STANDARD_LOCAL_USER
 

Definition at line 72 of file app_zapbarge.c.

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

Definition at line 63 of file app_zapbarge.c.

Referenced by load_module().

char* tdesc = "Barge in on Zap channel application" [static]
 

Definition at line 59 of file app_zapbarge.c.


Generated on Mon Mar 20 08:25:49 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1