DAHDI Scanner. 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/utils.h"#include "asterisk/cli.h"#include "asterisk/say.h"#include "asterisk/options.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, void *data) |
| static int | conf_run (struct ast_channel *chan, int confno, int confflags) |
| static struct ast_channel * | get_dahdi_channel_locked (int num) |
| static int | load_module (void) |
| static int | unload_module (void) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Scan DAHDI channels 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, } |
| static char * | app = "DAHDIScan" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
DAHDI Scanner.
Definition in file app_dahdiscan.c.
| #define CONF_SIZE 160 |
Definition at line 73 of file app_dahdiscan.c.
Referenced by conf_run().
| static void __reg_module | ( | void | ) | [static] |
Definition at line 377 of file app_dahdiscan.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 377 of file app_dahdiscan.c.
| static int careful_write | ( | int | fd, |
| unsigned char * | data, | ||
| int | len | ||
| ) | [static] |
Definition at line 82 of file app_dahdiscan.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, |
| void * | data | ||
| ) | [static] |
Definition at line 290 of file app_dahdiscan.c.
References ast_channel::_state, ast_answer(), ast_channel_unlock, ast_channel_walk_locked(), ast_copy_string(), AST_DIGIT_ANY, AST_FRAME_DTMF, ast_frfree, ast_read(), ast_say_number(), AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_strlen_zero(), ast_verb, ast_waitfor(), conf_run(), f, ast_frame::frametype, get_dahdi_channel_locked(), input(), ast_channel::language, ast_channel::name, pbx_builtin_getvar_helper(), ast_frame::subclass, ast_channel::tech, and ast_channel_tech::type.
Referenced by load_module().
{
int res=-1;
int confflags = 0;
int confno = 0;
char confnostr[80] = "", *tmp = NULL;
struct ast_channel *tempchan = NULL, *lastchan = NULL, *ichan = NULL;
struct ast_frame *f;
char *desired_group;
int input = 0, search_group = 0;
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
desired_group = ast_strdupa(data);
if (!ast_strlen_zero(desired_group)) {
ast_verb(3, "Scanning for group %s\n", desired_group);
search_group = 1;
}
for (;;) {
if (ast_waitfor(chan, 100) < 0)
break;
f = ast_read(chan);
if (!f)
break;
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) {
ast_frfree(f);
break;
}
ast_frfree(f);
ichan = NULL;
if(input) {
ichan = get_dahdi_channel_locked(input);
input = 0;
}
tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan);
if (!tempchan && !lastchan) {
break;
}
if (tempchan && search_group) {
const char *mygroup;
if ((mygroup = pbx_builtin_getvar_helper(tempchan, "GROUP")) && (!strcmp(mygroup, desired_group))) {
ast_verb(3, "Found Matching Channel %s in group %s\n", tempchan->name, desired_group);
} else {
ast_channel_unlock(tempchan);
lastchan = tempchan;
continue;
}
}
if (tempchan && (!strcmp(tempchan->tech->type, "DAHDI")) && (tempchan != chan)) {
ast_verb(3, "DAHDI channel %s is in-use, monitoring...\n", tempchan->name);
ast_copy_string(confnostr, tempchan->name, sizeof(confnostr));
ast_channel_unlock(tempchan);
if ((tmp = strchr(confnostr, '-'))) {
*tmp = '\0';
}
confno = atoi(strchr(confnostr, '/') + 1);
ast_stopstream(chan);
ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL);
res = conf_run(chan, confno, confflags);
if (res < 0) {
break;
}
input = res;
} else if (tempchan) {
ast_channel_unlock(tempchan);
}
lastchan = tempchan;
}
return res;
}
| static int conf_run | ( | struct ast_channel * | chan, |
| int | confno, | ||
| int | confflags | ||
| ) | [static] |
Definition at line 101 of file app_dahdiscan.c.
References ast_debug, 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_verb, ast_waitfor_nandfds(), ast_write(), buf, careful_write(), CONF_SIZE, ast_frame::data, ast_frame::datalen, errno, f, ast_channel::fds, ast_frame::flags, ast_frame::frametype, input(), 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;
char input[4];
int ic = 0;
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) {
if (f->subclass == '#') {
ret = 0;
break;
} else if (f->subclass == '*') {
ret = -1;
break;
} else {
input[ic++] = f->subclass;
}
if (ic == 3) {
input[ic++] = '\0';
ic = 0;
ret = atoi(input);
ast_verb(3, "DAHDIScan: change channel to %d\n", ret);
break;
}
}
if (fd != chan->fds[0]) {
if (f->frametype == AST_FRAME_VOICE) {
if (f->subclass == AST_FORMAT_ULAW) {
/* Carefully write */
careful_write(fd, f->data.ptr, f->datalen);
} else {
ast_log(LOG_WARNING, "Huh? Got a non-ulaw (%d) frame in the conference\n", f->subclass);
}
}
}
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 = 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 (f) {
ast_frfree(f);
}
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 struct ast_channel* get_dahdi_channel_locked | ( | int | num | ) | [static, read] |
Definition at line 75 of file app_dahdiscan.c.
References ast_get_channel_by_name_locked(), and name.
Referenced by conf_exec().
{
char name[80];
snprintf(name, sizeof(name), "DAHDI/%d-1", num);
return ast_get_channel_by_name_locked(name);
}
| static int load_module | ( | void | ) | [static] |
Definition at line 372 of file app_dahdiscan.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 367 of file app_dahdiscan.c.
References ast_unregister_application().
{
return ast_unregister_application(app);
}
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Scan DAHDI channels 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, } [static] |
Definition at line 377 of file app_dahdiscan.c.
char* app = "DAHDIScan" [static] |
Definition at line 71 of file app_dahdiscan.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 377 of file app_dahdiscan.c.