Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:19 2009

## Asterisk developer's documentation

# 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"`

Include dependency graph for app_zapbarge.c:

Go to the source code of this file.

## Defines

#define | CONF_SIZE 160

## Functions

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)
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

static char * | app = "ZapBarge"
static char * | descrip
| LOCAL_USER_DECL
| STANDARD_LOCAL_USER
static char * | synopsis = "Barge in (monitor) Zap channel"
static 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

static 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 }

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

Definition at line 263 of file app_zapbarge.c.

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

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

static 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_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, 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             ast_frfree(f);
    00216             break;
    00217          } else if (fd != chan->fds[0]) {
    00218             if (f->frametype == AST_FRAME_VOICE) {
    00219                if (f->subclass == AST_FORMAT_ULAW) {
    00220                   /* Carefully write */
    00221                   careful_write(fd, f->data, f->datalen);
    00222                } else
    00223                   ast_log(LOG_WARNING, "Huh?  Got a non-ulaw (%d) frame in the conference\n", f->subclass);
    00224             }
    00225          }
    00226          ast_frfree(f);
    00227       } else if (outfd > -1) {
    00228          res = read(outfd, buf, CONF_SIZE);
    00229          if (res > 0) {
    00230             memset(&fr, 0, sizeof(fr));
    00231             fr.frametype = AST_FRAME_VOICE;
    00232             fr.subclass = AST_FORMAT_ULAW;
    00233             fr.datalen = res;
    00234             fr.samples = res;
    00235             fr.data = buf;
    00236             fr.offset = AST_FRIENDLY_OFFSET;
    00237             if (ast_write(chan, &fr) < 0) {
    00238                ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
    00239                /* break; */
    00240             }
    00241          } else
    00242             ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno));
    00243       }
    00244    }
    00245    if (fd != chan->fds[0])
    00246       close(fd);
    00247    else {
    00248       /* Take out of conference */
    00249       /* Add us to the conference */
    00250       ztc.chan = 0;
    00251       ztc.confno = 0;
    00252       ztc.confmode = 0;
    00253       if (ioctl(fd, ZT_SETCONF, &ztc)) {
    00254          ast_log(LOG_WARNING, "Error setting conference\n");
    00255       }
    00256    }
    00257
    00258 outrun:
    00259
    00260    return ret;
    00261 }

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 321 of file app_zapbarge.c.

    00322 {
    00323    return tdesc;
    00324 }

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

References ASTERISK_GPL_KEY.

    00334 {
    00335    return ASTERISK_GPL_KEY;
    00336 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

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.

TE STUFF END

Definition at line 316 of file app_zapbarge.c.

References ast_register_application(), and conf_exec().

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

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

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

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

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

References STANDARD_USECOUNT.

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

## Variable Documentation

char* app = "ZapBarge"`[static]`

Definition at line 61 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 65 of file app_zapbarge.c.

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.

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

Definition at line 59 of file app_zapbarge.c.