DAHDI Barge support. More...
#include "asterisk.h"#include <dahdi/user.h>#include "asterisk/lock.h"#include "asterisk/file.h"#include "asterisk/channel.h"#include "asterisk/pbx.h"#include "asterisk/module.h"#include "asterisk/config.h"#include "asterisk/app.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 | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | careful_write (int fd, unsigned char *data, int len) |
| static int | conf_exec (struct ast_channel *chan, const char *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 struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Barge in on DAHDI channel application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
| static const char | app [] = "DAHDIBarge" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
DAHDI Barge support.
Definition in file app_dahdibarge.c.
| #define CONF_SIZE 160 |
Definition at line 77 of file app_dahdibarge.c.
Referenced by conf_run().
| static void __reg_module | ( | void | ) | [static] |
Definition at line 310 of file app_dahdibarge.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 310 of file app_dahdibarge.c.
| static int careful_write | ( | int | fd, |
| unsigned char * | data, | ||
| int | len | ||
| ) | [static] |
Definition at line 79 of file app_dahdibarge.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by conf_run().
{
int res;
while(len) {
res = write(fd, data, len);
if (res < 1) {
if (errno != EAGAIN) {
ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno));
return -1;
} else
return 0;
}
len -= res;
data += res;
}
return 0;
}
| static int conf_exec | ( | struct ast_channel * | chan, |
| const char * | data | ||
| ) | [static] |
Definition at line 263 of file app_dahdibarge.c.
References ast_channel::_state, ast_answer(), ast_app_getdata(), ast_log(), AST_STATE_UP, ast_strlen_zero(), conf_run(), and LOG_WARNING.
Referenced by load_module().
{
int res = -1;
int retrycnt = 0;
int confflags = 0;
int confno = 0;
char confnostr[80] = "";
if (!ast_strlen_zero(data)) {
if ((sscanf(data, "DAHDI/%30d", &confno) != 1) &&
(sscanf(data, "%30d", &confno) != 1)) {
ast_log(LOG_WARNING, "DAHDIBarge Argument (if specified) must be a channel number, not '%s'\n", (char *)data);
return 0;
}
}
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
while(!confno && (++retrycnt < 4)) {
/* Prompt user for conference number */
confnostr[0] = '\0';
res = ast_app_getdata(chan, "conf-getchannel",confnostr, sizeof(confnostr) - 1, 0);
if (res <0) goto out;
if (sscanf(confnostr, "%30d", &confno) != 1)
confno = 0;
}
if (confno) {
/* XXX Should prompt user for pin if pin is required XXX */
/* Run the conference */
res = conf_run(chan, confno, confflags);
}
out:
/* Do the conference */
return res;
}
| static int conf_run | ( | struct ast_channel * | chan, |
| int | confno, | ||
| int | confflags | ||
| ) | [static] |
Definition at line 97 of file app_dahdibarge.c.
References ast_debug, AST_FORMAT_ULAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_indicate(), ast_log(), ast_read(), ast_set_read_format(), ast_set_write_format(), ast_waitfor_nandfds(), ast_write(), careful_write(), ast_frame_subclass::codec, CONF_SIZE, ast_frame::data, ast_frame::datalen, errno, f, ast_channel::fds, ast_frame::flags, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, ast_channel::name, ast_frame::offset, ast_frame::ptr, ast_frame::samples, ast_frame::subclass, ast_channel::tech, and ast_channel_tech::type.
Referenced by conf_exec().
{
int fd;
struct dahdi_confinfo dahdic;
struct ast_frame *f;
struct ast_channel *c;
struct ast_frame fr;
int outfd;
int ms;
int nfds;
int res;
int flags;
int retrydahdi;
int origfd;
int ret = -1;
struct dahdi_bufferinfo bi;
char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
char *buf = __buf + AST_FRIENDLY_OFFSET;
/* Set it into U-law mode (write) */
if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name);
goto outrun;
}
/* Set it into U-law mode (read) */
if (ast_set_read_format(chan, AST_FORMAT_ULAW) < 0) {
ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name);
goto outrun;
}
ast_indicate(chan, -1);
retrydahdi = strcasecmp(chan->tech->type, "DAHDI");
dahdiretry:
origfd = chan->fds[0];
if (retrydahdi) {
fd = open("/dev/dahdi/pseudo", O_RDWR);
if (fd < 0) {
ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
goto outrun;
}
/* Make non-blocking */
flags = fcntl(fd, F_GETFL);
if (flags < 0) {
ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno));
close(fd);
goto outrun;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno));
close(fd);
goto outrun;
}
/* Setup buffering information */
memset(&bi, 0, sizeof(bi));
bi.bufsize = CONF_SIZE;
bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
bi.numbufs = 4;
if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) {
ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno));
close(fd);
goto outrun;
}
nfds = 1;
} else {
/* XXX Make sure we're not running on a pseudo channel XXX */
fd = chan->fds[0];
nfds = 0;
}
memset(&dahdic, 0, sizeof(dahdic));
/* Check to see if we're in a conference... */
dahdic.chan = 0;
if (ioctl(fd, DAHDI_GETCONF, &dahdic)) {
ast_log(LOG_WARNING, "Error getting conference\n");
close(fd);
goto outrun;
}
if (dahdic.confmode) {
/* Whoa, already in a conference... Retry... */
if (!retrydahdi) {
ast_debug(1, "DAHDI channel is in a conference already, retrying with pseudo\n");
retrydahdi = 1;
goto dahdiretry;
}
}
memset(&dahdic, 0, sizeof(dahdic));
/* Add us to the conference */
dahdic.chan = 0;
dahdic.confno = confno;
dahdic.confmode = DAHDI_CONF_MONITORBOTH;
if (ioctl(fd, DAHDI_SETCONF, &dahdic)) {
ast_log(LOG_WARNING, "Error setting conference\n");
close(fd);
goto outrun;
}
ast_debug(1, "Placed channel %s in DAHDI channel %d monitor\n", chan->name, confno);
for(;;) {
outfd = -1;
ms = -1;
c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
if (c) {
if (c->fds[0] != origfd) {
if (retrydahdi) {
/* Kill old pseudo */
close(fd);
}
ast_debug(1, "Ooh, something swapped out under us, starting over\n");
retrydahdi = 0;
goto dahdiretry;
}
f = ast_read(c);
if (!f)
break;
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass.integer == '#')) {
ret = 0;
ast_frfree(f);
break;
} else if (fd != chan->fds[0]) {
if (f->frametype == AST_FRAME_VOICE) {
if (f->subclass.codec == AST_FORMAT_ULAW) {
/* Carefully write */
careful_write(fd, f->data.ptr, f->datalen);
} else
ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%s) frame in the conference\n", ast_getformatname(f->subclass.codec));
}
}
ast_frfree(f);
} else if (outfd > -1) {
res = read(outfd, buf, CONF_SIZE);
if (res > 0) {
memset(&fr, 0, sizeof(fr));
fr.frametype = AST_FRAME_VOICE;
fr.subclass.codec = AST_FORMAT_ULAW;
fr.datalen = res;
fr.samples = res;
fr.data.ptr = buf;
fr.offset = AST_FRIENDLY_OFFSET;
if (ast_write(chan, &fr) < 0) {
ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
/* break; */
}
} else
ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno));
}
}
if (fd != chan->fds[0])
close(fd);
else {
/* Take out of conference */
/* Add us to the conference */
dahdic.chan = 0;
dahdic.confno = 0;
dahdic.confmode = 0;
if (ioctl(fd, DAHDI_SETCONF, &dahdic)) {
ast_log(LOG_WARNING, "Error setting conference\n");
}
}
outrun:
return ret;
}
| static int load_module | ( | void | ) | [static] |
Definition at line 305 of file app_dahdibarge.c.
References AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, and conf_exec().
{
return ((ast_register_application_xml(app, conf_exec)) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS);
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 300 of file app_dahdibarge.c.
References ast_unregister_application().
{
return ast_unregister_application(app);
}
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Barge in on DAHDI channel application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 310 of file app_dahdibarge.c.
const char app[] = "DAHDIBarge" [static] |
Definition at line 75 of file app_dahdibarge.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 310 of file app_dahdibarge.c.