Wed Aug 7 17:15:33 2019

Asterisk developer's documentation


app_dahdibarge.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * Special thanks to comphealth.com for sponsoring this
00009  * GPL application.
00010  *
00011  * See http://www.asterisk.org for more information about
00012  * the Asterisk project. Please do not directly contact
00013  * any of the maintainers of this project for assistance;
00014  * the project provides a web site, mailing lists and IRC
00015  * channels for your use.
00016  *
00017  * This program is free software, distributed under the terms of
00018  * the GNU General Public License Version 2. See the LICENSE file
00019  * at the top of the source tree.
00020  */
00021 
00022 /*! \file
00023  *
00024  * \brief DAHDI Barge support
00025  *
00026  * \author Mark Spencer <markster@digium.com>
00027  *
00028  * \note Special thanks to comphealth.com for sponsoring this
00029  * GPL application.
00030  * 
00031  * \ingroup applications
00032  */
00033 
00034 /*** MODULEINFO
00035    <depend>dahdi</depend>
00036    <support_level>deprecated</support_level>
00037    <replacement>app_chanspy</replacement>
00038  ***/
00039 
00040 #include "asterisk.h"
00041 
00042 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328446 $")
00043 
00044 #include <dahdi/user.h>
00045 
00046 #include "asterisk/lock.h"
00047 #include "asterisk/file.h"
00048 #include "asterisk/channel.h"
00049 #include "asterisk/pbx.h"
00050 #include "asterisk/module.h"
00051 #include "asterisk/config.h"
00052 #include "asterisk/app.h"
00053 #include "asterisk/cli.h"
00054 #include "asterisk/say.h"
00055 #include "asterisk/utils.h"
00056 
00057 /*** DOCUMENTATION
00058    <application name="DAHDIBarge" language="en_US">
00059       <synopsis>
00060          Barge in (monitor) DAHDI channel.
00061       </synopsis>
00062       <syntax>
00063          <parameter name="channel">
00064             <para>Channel to barge.</para>
00065          </parameter>
00066       </syntax>
00067       <description>
00068          <para>Barges in on a specified DAHDI <replaceable>channel</replaceable> or prompts
00069          if one is not specified. Returns <literal>-1</literal> when caller user hangs
00070          up and is independent of the state of the channel being monitored.
00071          </para>
00072       </description>
00073    </application>
00074  ***/
00075 static const char app[] = "DAHDIBarge";
00076 
00077 #define CONF_SIZE 160
00078 
00079 static int careful_write(int fd, unsigned char *data, int len)
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 }
00096 
00097 static int conf_run(struct ast_channel *chan, int confno, int confflags)
00098 {
00099    int fd;
00100    struct dahdi_confinfo dahdic;
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 retrydahdi;
00110    int origfd;
00111    int ret = -1;
00112 
00113    struct dahdi_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    retrydahdi = strcasecmp(chan->tech->type, "DAHDI");
00130 dahdiretry:
00131    origfd = chan->fds[0];
00132    if (retrydahdi) {
00133       fd = open("/dev/dahdi/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 = DAHDI_POLICY_IMMEDIATE;
00154       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
00155       bi.numbufs = 4;
00156       if (ioctl(fd, DAHDI_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(&dahdic, 0, sizeof(dahdic));
00168    /* Check to see if we're in a conference... */
00169    dahdic.chan = 0;  
00170    if (ioctl(fd, DAHDI_GETCONF, &dahdic)) {
00171       ast_log(LOG_WARNING, "Error getting conference\n");
00172       close(fd);
00173       goto outrun;
00174    }
00175    if (dahdic.confmode) {
00176       /* Whoa, already in a conference...  Retry... */
00177       if (!retrydahdi) {
00178          ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n");
00179          retrydahdi = 1;
00180          goto dahdiretry;
00181       }
00182    }
00183    memset(&dahdic, 0, sizeof(dahdic));
00184    /* Add us to the conference */
00185    dahdic.chan = 0;  
00186    dahdic.confno = confno;
00187    dahdic.confmode = DAHDI_CONF_MONITORBOTH;
00188 
00189    if (ioctl(fd, DAHDI_SETCONF, &dahdic)) {
00190       ast_log(LOG_WARNING, "Error setting conference\n");
00191       close(fd);
00192       goto outrun;
00193    }
00194    ast_debug(1, "Placed channel %s in DAHDI 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 (retrydahdi) {
00203                /* Kill old pseudo */
00204                close(fd);
00205             }
00206             ast_debug(1, "Ooh, something swapped out under us, starting over\n");
00207             retrydahdi = 0;
00208             goto dahdiretry;
00209          }
00210          f = ast_read(c);
00211          if (!f) 
00212             break;
00213          if ((f->frametype == AST_FRAME_DTMF) && (f->subclass.integer == '#')) {
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.codec == AST_FORMAT_ULAW) {
00220                   /* Carefully write */
00221                   careful_write(fd, f->data.ptr, f->datalen);
00222                } else
00223                   ast_log(LOG_WARNING, "Huh?  Got a non-ulaw (%s) frame in the conference\n", ast_getformatname(f->subclass.codec));
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.codec = AST_FORMAT_ULAW;
00233             fr.datalen = res;
00234             fr.samples = res;
00235             fr.data.ptr = 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       dahdic.chan = 0;  
00251       dahdic.confno = 0;
00252       dahdic.confmode = 0;
00253       if (ioctl(fd, DAHDI_SETCONF, &dahdic)) {
00254          ast_log(LOG_WARNING, "Error setting conference\n");
00255       }
00256    }
00257 
00258 outrun:
00259 
00260    return ret;
00261 }
00262 
00263 static int conf_exec(struct ast_channel *chan, const char *data)
00264 {
00265    int res = -1;
00266    int retrycnt = 0;
00267    int confflags = 0;
00268    int confno = 0;
00269    char confnostr[80] = "";
00270    
00271    if (!ast_strlen_zero(data)) {
00272       if ((sscanf(data, "DAHDI/%30d", &confno) != 1) &&
00273           (sscanf(data, "%30d", &confno) != 1)) {
00274          ast_log(LOG_WARNING, "DAHDIBarge Argument (if specified) must be a channel number, not '%s'\n", (char *)data);
00275          return 0;
00276       }
00277    }
00278    
00279    if (chan->_state != AST_STATE_UP)
00280       ast_answer(chan);
00281 
00282    while(!confno && (++retrycnt < 4)) {
00283       /* Prompt user for conference number */
00284       confnostr[0] = '\0';
00285       res = ast_app_getdata(chan, "conf-getchannel",confnostr, sizeof(confnostr) - 1, 0);
00286       if (res <0) goto out;
00287       if (sscanf(confnostr, "%30d", &confno) != 1)
00288          confno = 0;
00289    }
00290    if (confno) {
00291       /* XXX Should prompt user for pin if pin is required XXX */
00292       /* Run the conference */
00293       res = conf_run(chan, confno, confflags);
00294    }
00295 out:
00296    /* Do the conference */
00297    return res;
00298 }
00299 
00300 static int unload_module(void)
00301 {
00302    return ast_unregister_application(app);
00303 }
00304 
00305 static int load_module(void)
00306 {
00307    return ((ast_register_application_xml(app, conf_exec)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
00308 }
00309 
00310 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Barge in on DAHDI channel application");

Generated on 7 Aug 2019 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1