dect
/
asterisk
Archived
13
0
Fork 0

Version 0.3.0 from FTP

git-svn-id: http://svn.digium.com/svn/asterisk/trunk@600 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
markster 2003-02-04 15:48:42 +00:00
parent 151774c059
commit bfeaccab3d
12 changed files with 2717 additions and 36 deletions

View File

@ -24,10 +24,13 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <pthread.h> #include <pthread.h>
#include "../asterisk.h" #include "../asterisk.h"
#include "../astconf.h"
static char *tdesc = "Asterisk ADSI Programming Application"; static char *tdesc = "Asterisk ADSI Programming Application";
@ -1321,7 +1324,7 @@ static struct adsi_script *compile_script(char *script)
if (script[0] == '/') if (script[0] == '/')
strncpy(fn, script, sizeof(fn) - 1); strncpy(fn, script, sizeof(fn) - 1);
else else
snprintf(fn, sizeof(fn), "%s/%s", AST_CONFIG_DIR, script); snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, script);
f = fopen(fn, "r"); f = fopen(fn, "r");
if (!f) { if (!f) {
ast_log(LOG_WARNING, "Can't open file '%s'\n", fn); ast_log(LOG_WARNING, "Can't open file '%s'\n", fn);

116
apps/app_flash.c Executable file
View File

@ -0,0 +1,116 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* App to flash a zap trunk
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#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/translate.h>
#include <asterisk/image.h>
#include <asterisk/options.h>
#include <sys/ioctl.h>
#include <linux/zaptel.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Flash zap trunk application";
static char *app = "Flash";
static char *synopsis = "Flashes a Zap Trunk";
static char *descrip =
" Flash(): Sends a flash on a zap trunk. This is only a hack for\n"
"people who want to perform transfers and such via AGI and is generally\n"
"quite useless otherwise. Returns 0 on success or -1 if this is not\n"
"a zap trunk\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static inline int zt_wait_event(int fd)
{
/* Avoid the silly zt_waitevent which ignores a bunch of events */
int i,j=0;
i = ZT_IOMUX_SIGEVENT;
if (ioctl(fd, ZT_IOMUX, &i) == -1) return -1;
if (ioctl(fd, ZT_GETEVENT, &j) == -1) return -1;
return j;
}
static int flash_exec(struct ast_channel *chan, void *data)
{
int res = -1;
int x;
struct localuser *u;
struct zt_params ztp;
LOCAL_USER_ADD(u);
if (!strcasecmp(chan->type, "Zap")) {
memset(&ztp, 0, sizeof(ztp));
res = ioctl(chan->fds[0], ZT_GET_PARAMS, &ztp);
if (!res) {
if (ztp.sigtype & __ZT_SIG_FXS) {
x = ZT_FLASH;
res = ioctl(chan->fds[0], ZT_HOOK, &x);
if (!res || (errno == EINPROGRESS)) {
if (res) {
/* Wait for the event to finish */
zt_wait_event(chan->fds[0]);
}
res = ast_safe_sleep(chan, 1000);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Flashed channel %s\n", chan->name);
} else
ast_log(LOG_WARNING, "Unable to flash channel %s: %s\n", chan->name, strerror(errno));
} else
ast_log(LOG_WARNING, "%s is not an FXO Channel\n", chan->name);
} else
ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", chan->name, strerror(errno));
} else
ast_log(LOG_WARNING, "%s is not a Zap channel\n", chan->name);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, flash_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@ -25,6 +25,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -40,13 +41,20 @@ static char *synopsis = "Simple MeetMe conference bridge";
static char *synopsis2 = "MeetMe participant count"; static char *synopsis2 = "MeetMe participant count";
static char *descrip = static char *descrip =
" MeetMe(confno): Enters the user into a specified MeetMe conference.\n" " MeetMe(confno[|options]): Enters the user into a specified MeetMe conference.\n"
"If the conference number is omitted, the user will be prompted to enter\n" "If the conference number is omitted, the user will be prompted to enter\n"
"one. This application always returns -1. A ZAPTEL INTERFACE MUST BE\n" "one. This application always returns -1. A ZAPTEL INTERFACE MUST BE\n"
"INSTALLED FOR CONFERENCING FUNCTIONALITY.\n"; "INSTALLED FOR CONFERENCING FUNCTIONALITY.\n"
"The option string may contain zero or more of the following characters:\n"
" 'a' -- set admin mode\n"
" 'm' -- set monitor only mode\n"
" 'p' -- allow user to exit the conference by pressing '#'\n"
" 's' -- send user to admin/user menu if '*' is received\n"
" 't' -- set talk only mode\n"
" 'q' -- quiet mode (don't play enter/leave sounds)\n";
static char *descrip2 = static char *descrip2 =
" MeetMe2(confno): Plays back the number of users in the specified MeetMe\n" " MeetMeCount(confno): Plays back the number of users in the specified MeetMe\n"
"conference. Returns 0 on success or -1 on a hangup. A ZAPTEL INTERFACE\n" "conference. Returns 0 on success or -1 on a hangup. A ZAPTEL INTERFACE\n"
"MUST BE INSTALLED FOR CONFERENCING FUNCTIONALITY.\n"; "MUST BE INSTALLED FOR CONFERENCING FUNCTIONALITY.\n";
@ -73,6 +81,13 @@ static pthread_mutex_t conflock = AST_MUTEX_INITIALIZER;
#define CONF_SIZE 160 #define CONF_SIZE 160
#define CONFFLAG_ADMIN (1 << 1) /* If set the user has admin access on the conference */
#define CONFFLAG_MONITOR (1 << 2) /* If set the user can only receive audio from the conference */
#define CONFFLAG_POUNDEXIT (1 << 3) /* If set asterisk will exit conference when '#' is pressed */
#define CONFFLAG_STARMENU (1 << 4) /* If set asterisk will provide a menu to the user what '*' is pressed */
#define CONFFLAG_TALKER (1 << 5) /* If set the use can only send audio to the conference */
#define CONFFLAG_QUIET (1 << 6) /* If set there will be no enter or leave sounds */
static int careful_write(int fd, unsigned char *data, int len) static int careful_write(int fd, unsigned char *data, int len)
{ {
int res; int res;
@ -153,7 +168,7 @@ static struct conf *build_conf(char *confno, int make)
cnf->start = time(NULL); cnf->start = time(NULL);
cnf->zapconf = ztc.confno; cnf->zapconf = ztc.confno;
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Crated ZapTel conference %d for conference '%s'\n", cnf->zapconf, cnf->confno); ast_verbose(VERBOSE_PREFIX_3 "Created ZapTel conference %d for conference '%s'\n", cnf->zapconf, cnf->confno);
cnf->next = confs; cnf->next = confs;
confs = cnf; confs = cnf;
} else } else
@ -202,7 +217,7 @@ static struct ast_cli_entry cli_show_confs = {
{ "show", "conferences", NULL }, confs_show, { "show", "conferences", NULL }, confs_show,
"Show status of conferences", show_confs_usage, NULL }; "Show status of conferences", show_confs_usage, NULL };
static void conf_run(struct ast_channel *chan, struct conf *conf) static int conf_run(struct ast_channel *chan, struct conf *conf, int confflags)
{ {
struct conf *prev=NULL, *cur; struct conf *prev=NULL, *cur;
int fd; int fd;
@ -215,12 +230,20 @@ static void conf_run(struct ast_channel *chan, struct conf *conf)
int nfds; int nfds;
int res; int res;
int flags; int flags;
int retryzap=0; int retryzap;
int origfd;
int firstpass = 0;
int ret = -1;
ZT_BUFFERINFO bi; ZT_BUFFERINFO bi;
char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
char *buf = __buf + AST_FRIENDLY_OFFSET; char *buf = __buf + AST_FRIENDLY_OFFSET;
if (!(confflags & CONFFLAG_QUIET) && conf->users == 1) {
if (!ast_streamfile(chan, "conf-onlyperson", chan->language))
ast_waitstream(chan, "");
}
/* Set it into U-law mode (write) */ /* Set it into U-law mode (write) */
if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) { 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); ast_log(LOG_WARNING, "Unable to set '%s' to write ulaw mode\n", chan->name);
@ -232,9 +255,11 @@ static void conf_run(struct ast_channel *chan, struct conf *conf)
ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name); ast_log(LOG_WARNING, "Unable to set '%s' to read ulaw mode\n", chan->name);
goto outrun; goto outrun;
} }
ast_indicate(chan, -1);
retryzap = strcasecmp(chan->type, "Zap");
zapretry: zapretry:
origfd = chan->fds[0];
if (retryzap || strcasecmp(chan->type, "Zap")) { if (retryzap) {
fd = open("/dev/zap/pseudo", O_RDWR); fd = open("/dev/zap/pseudo", O_RDWR);
if (fd < 0) { if (fd < 0) {
ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
@ -289,25 +314,53 @@ zapretry:
/* Add us to the conference */ /* Add us to the conference */
ztc.chan = 0; ztc.chan = 0;
ztc.confno = conf->zapconf; ztc.confno = conf->zapconf;
ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; if (confflags & CONFFLAG_MONITOR)
ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER;
else if (confflags & CONFFLAG_TALKER)
ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
else
ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
if (ioctl(fd, ZT_SETCONF, &ztc)) { if (ioctl(fd, ZT_SETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error setting conference\n"); ast_log(LOG_WARNING, "Error setting conference\n");
close(fd); close(fd);
goto outrun; goto outrun;
} }
ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf); ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf);
/* Run the conference enter tone... */ if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) {
conf_play(conf, ENTER); firstpass = 1;
if (!(confflags & CONFFLAG_QUIET))
conf_play(conf, ENTER);
}
for(;;) { for(;;) {
outfd = -1; outfd = -1;
ms = -1; ms = -1;
c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
if (c) { if (c) {
if (c->fds[0] != origfd) {
if (retryzap) {
/* Kill old pseudo */
close(fd);
}
ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n");
retryzap = 0;
goto zapretry;
}
f = ast_read(c); f = ast_read(c);
if (!f) if (!f)
break; break;
if (fd != chan->fds[0]) { if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) {
ret = 0;
break;
} else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) {
if ((confflags & CONFFLAG_ADMIN)) {
/* Do admin stuff here */
} else {
/* Do user menu here */
}
} else if (fd != chan->fds[0]) {
if (f->frametype == AST_FRAME_VOICE) { if (f->frametype == AST_FRAME_VOICE) {
if (f->subclass == AST_FORMAT_ULAW) { if (f->subclass == AST_FORMAT_ULAW) {
/* Carefully write */ /* Carefully write */
@ -324,7 +377,7 @@ zapretry:
fr.frametype = AST_FRAME_VOICE; fr.frametype = AST_FRAME_VOICE;
fr.subclass = AST_FORMAT_ULAW; fr.subclass = AST_FORMAT_ULAW;
fr.datalen = res; fr.datalen = res;
fr.timelen = res / 8; fr.samples = res;
fr.data = buf; fr.data = buf;
fr.offset = AST_FRIENDLY_OFFSET; fr.offset = AST_FRIENDLY_OFFSET;
if (ast_write(chan, &fr) < 0) { if (ast_write(chan, &fr) < 0) {
@ -348,7 +401,8 @@ zapretry:
} }
} }
conf_play(conf, LEAVE); if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN))
conf_play(conf, LEAVE);
outrun: outrun:
@ -375,6 +429,7 @@ outrun:
free(conf); free(conf);
} }
pthread_mutex_unlock(&conflock); pthread_mutex_unlock(&conflock);
return ret;
} }
static struct conf *find_conf(char *confno, int make) static struct conf *find_conf(char *confno, int make)
@ -435,6 +490,8 @@ static int conf_exec(struct ast_channel *chan, void *data)
int allowretry = 0; int allowretry = 0;
int retrycnt = 0; int retrycnt = 0;
struct conf *cnf; struct conf *cnf;
int confflags = 0;
char info[256], *ptr, *inflags, *inpin;
if (!data || !strlen(data)) { if (!data || !strlen(data)) {
allowretry = 1; allowretry = 1;
@ -443,10 +500,41 @@ static int conf_exec(struct ast_channel *chan, void *data)
LOCAL_USER_ADD(u); LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP) if (chan->_state != AST_STATE_UP)
ast_answer(chan); ast_answer(chan);
retry:
/* Parse out the stuff */
strncpy(confno, data, sizeof(confno) - 1);
strncpy(info, (char *)data, sizeof(info) - 1);
ptr = info;
if (info) {
inflags = strchr(info, '|');
if (inflags) {
*inflags = '\0';
inflags++;
if (strchr(inflags, 'a'))
confflags |= CONFFLAG_ADMIN;
if (strchr(inflags, 'm'))
confflags |= CONFFLAG_MONITOR;
if (strchr(inflags, 'p'))
confflags |= CONFFLAG_POUNDEXIT;
if (strchr(inflags, 's'))
confflags |= CONFFLAG_STARMENU;
if (strchr(inflags, 't'))
confflags |= CONFFLAG_TALKER;
if (strchr(inflags, 'q'))
confflags |= CONFFLAG_QUIET;
inpin = strchr(inflags, '|');
if (inpin) {
*inpin = '\0';
inpin++;
/* XXX Need to do something with pin XXX */
ast_log(LOG_WARNING, "MEETME WITH PIN=(%s)\n", inpin);
}
}
}
/* Parse out the stuff */
strncpy(confno, info, sizeof(confno) - 1);
retry:
while(!strlen(confno) && (++retrycnt < 4)) { while(!strlen(confno) && (++retrycnt < 4)) {
/* Prompt user for conference number */ /* Prompt user for conference number */
res = ast_app_getdata(chan, "conf-getconfno",confno, sizeof(confno) - 1, 0); res = ast_app_getdata(chan, "conf-getconfno",confno, sizeof(confno) - 1, 0);
@ -467,9 +555,9 @@ retry:
goto retry; goto retry;
} }
} else { } else {
/* XXX Should prompt user for pin if pin is required XXX */
/* Run the conference */ /* Run the conference */
conf_run(chan, cnf); res = conf_run(chan, cnf, confflags);
res = -1;
} }
} }
out: out:

View File

@ -21,6 +21,7 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
#include <pthread.h> #include <pthread.h>
@ -73,7 +74,7 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len)
wf.mallocd = 0; wf.mallocd = 0;
wf.data = buf; wf.data = buf;
wf.datalen = len; wf.datalen = len;
wf.timelen = wf.datalen / 8; wf.samples = wf.datalen;
wf.src = "app_milliwatt"; wf.src = "app_milliwatt";
/* create a buffer containing the digital milliwatt pattern */ /* create a buffer containing the digital milliwatt pattern */
for(i = 0; i < len; i++) for(i = 0; i < len; i++)

305
apps/app_zapbarge.c Executable file
View File

@ -0,0 +1,305 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Zap Barge support
*
* Copyright (C) 2003, Digium
*
* Mark Spencer <markster@digium.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*
* Special thanks to comphealth.com for sponsoring this
* GPL application.
*/
#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 <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <linux/zaptel.h>
static char *tdesc = "Barge in on Zap channel application";
static char *app = "ZapBarge";
static char *synopsis = "Barge in (monitor) Zap channel";
static char *descrip =
" 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.";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
#define CONF_SIZE 160
static int careful_write(int fd, unsigned char *data, int len)
{
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_run(struct ast_channel *chan, int confno, int confflags)
{
int fd;
struct zt_confinfo ztc;
struct ast_frame *f;
struct ast_channel *c;
struct ast_frame fr;
int outfd;
int ms;
int nfds;
int res;
int flags;
int retryzap;
int origfd;
int ret = -1;
ZT_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);
retryzap = strcasecmp(chan->type, "Zap");
zapretry:
origfd = chan->fds[0];
if (retryzap) {
fd = open("/dev/zap/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 = ZT_POLICY_IMMEDIATE;
bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
bi.numbufs = 4;
if (ioctl(fd, ZT_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(&ztc, 0, sizeof(ztc));
/* Check to see if we're in a conference... */
ztc.chan = 0;
if (ioctl(fd, ZT_GETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error getting conference\n");
close(fd);
goto outrun;
}
if (ztc.confmode) {
/* Whoa, already in a conference... Retry... */
if (!retryzap) {
ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n");
retryzap = 1;
goto zapretry;
}
}
memset(&ztc, 0, sizeof(ztc));
/* Add us to the conference */
ztc.chan = 0;
ztc.confno = confno;
ztc.confmode = ZT_CONF_MONITORBOTH;
if (ioctl(fd, ZT_SETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error setting conference\n");
close(fd);
goto outrun;
}
ast_log(LOG_DEBUG, "Placed channel %s in ZAP 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 (retryzap) {
/* Kill old pseudo */
close(fd);
}
ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n");
retryzap = 0;
goto zapretry;
}
f = ast_read(c);
if (!f)
break;
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
ret = 0;
break;
} else if (fd != chan->fds[0]) {
if (f->frametype == AST_FRAME_VOICE) {
if (f->subclass == AST_FORMAT_ULAW) {
/* Carefully write */
careful_write(fd, f->data, 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 = 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 */
ztc.chan = 0;
ztc.confno = 0;
ztc.confmode = 0;
if (ioctl(fd, ZT_SETCONF, &ztc)) {
ast_log(LOG_WARNING, "Error setting conference\n");
}
}
outrun:
return ret;
}
static int conf_exec(struct ast_channel *chan, void *data)
{
int res=-1;
struct localuser *u;
int retrycnt = 0;
int confflags = 0;
int confno = 0;
char confstr[80];
if (data && strlen(data)) {
if ((sscanf(data, "Zap/%d", &confno) != 1) &&
(sscanf(data, "%d", &confno) != 1)) {
ast_log(LOG_WARNING, "ZapBarge Argument (if specified) must be a channel number, not '%s'\n", (char *)data);
return 0;
}
}
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
while(!confno && (++retrycnt < 4)) {
/* Prompt user for conference number */
strcpy(confstr, "");
res = ast_app_getdata(chan, "conf-getchannel",confstr, sizeof(confstr) - 1, 0);
if (res <0) goto out;
if (sscanf(confstr, "%d", &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 */
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, conf_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@ -26,6 +26,9 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h> #include <pthread.h>
@ -60,6 +63,7 @@ static pid_t spawn_ras(struct ast_channel *chan, char *args)
char *argv[PPP_MAX_ARGS]; char *argv[PPP_MAX_ARGS];
int argc = 0; int argc = 0;
char *stringp=NULL;
/* Start by forking */ /* Start by forking */
pid = fork(); pid = fork();
@ -86,10 +90,11 @@ static pid_t spawn_ras(struct ast_channel *chan, char *args)
argv[argc++] = "nodetach"; argv[argc++] = "nodetach";
/* And all the other arguments */ /* And all the other arguments */
c = strtok(args, "|"); stringp=args;
c = strsep(&stringp, "|");
while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) { while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
argv[argc++] = c; argv[argc++] = c;
c = strtok(NULL, "|"); c = strsep(&stringp, "|");
} }
argv[argc++] = "plugin"; argv[argc++] = "plugin";

1321
dsp.c Executable file

File diff suppressed because it is too large Load Diff

View File

@ -98,7 +98,7 @@ static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *f
#define AST_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER #define AST_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#define AST_MUTEX_KIND PTHREAD_MUTEX_FAST_NP #define AST_MUTEX_KIND PTHREAD_MUTEX_FAST_NP
#define ast_pthread_mutex_initi(mutex,kind) pthread_mutex_init(mutex) #define ast_pthread_mutex_init(mutex) pthread_mutex_init(mutex, NULL)
#define ast_pthread_mutex_lock pthread_mutex_lock #define ast_pthread_mutex_lock pthread_mutex_lock
#define ast_pthread_mutex_unlock pthread_mutex_unlock #define ast_pthread_mutex_unlock pthread_mutex_unlock

470
indications.c Executable file
View File

@ -0,0 +1,470 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Tone Management
*
* Copyright (C) 2002, Pauline Middelink
*
* Pauline Middelink <middelink@polyware.nl>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*
* This set of function allow us to play a list of tones on a channel.
* Each element has two frequencies, which are mixed together and a
* duration. For silence both frequencies can be set to 0.
* The playtones can be given as a comma seperated string.
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <math.h> /* For PI */
#include <asterisk/indications.h>
#include <asterisk/frame.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/logger.h>
#define PTHREAD_MUTEX_LOCK(a) ast_pthread_mutex_lock(a)
#define PTHREAD_MUTEX_UNLOCK(a) ast_pthread_mutex_unlock(a)
struct playtones_item {
int freq1;
int freq2;
int duration;
};
struct playtones_def {
int vol;
int reppos;
int nitems;
struct playtones_item *items;
};
struct playtones_state {
int vol;
int reppos;
int nitems;
struct playtones_item *items;
int npos;
int pos;
int origwfmt;
struct ast_frame f;
short data[4000];
};
static void playtones_release(struct ast_channel *chan, void *params)
{
struct playtones_state *ps = params;
if (chan) {
ast_set_write_format(chan, ps->origwfmt);
}
if (ps->items) free(ps->items);
free(ps);
}
static void * playtones_alloc(struct ast_channel *chan, void *params)
{
struct playtones_def *pd = params;
struct playtones_state *ps = malloc(sizeof(struct playtones_state));
if (!ps)
return NULL;
memset(ps, 0, sizeof(struct playtones_state));
ps->origwfmt = chan->writeformat;
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name);
playtones_release(NULL, ps);
ps = NULL;
} else {
ps->vol = pd->vol;
ps->reppos = pd->reppos;
ps->nitems = pd->nitems;
ps->items = pd->items;
}
/* Let interrupts interrupt :) */
chan->writeinterrupt = 1;
return ps;
}
static int playtones_generator(struct ast_channel *chan, void *data, int len, int samples)
{
struct playtones_state *ps = data;
struct playtones_item *pi;
int x;
/* we need to prepare a frame with 16 * timelen samples as we're
* generating SLIN audio
*/
len = samples * 2;
if (len > sizeof(ps->data) / 2 - 1) {
ast_log(LOG_WARNING, "Can't generate that much data!\n");
return -1;
}
memset(&ps->f, 0, sizeof(ps->f));
pi = &ps->items[ps->npos];
for (x=0;x<len/2;x++) {
ps->data[x] = ps->vol * (
sin((pi->freq1 * 2.0 * M_PI / 8000.0) * (ps->pos + x)) +
sin((pi->freq2 * 2.0 * M_PI / 8000.0) * (ps->pos + x))
);
}
ps->f.frametype = AST_FRAME_VOICE;
ps->f.subclass = AST_FORMAT_SLINEAR;
ps->f.datalen = len;
ps->f.samples = samples;
ps->f.offset = AST_FRIENDLY_OFFSET;
ps->f.data = ps->data;
ast_write(chan, &ps->f);
ps->pos += x;
if (pi->duration && ps->pos >= pi->duration * 8) { /* item finished? */
ps->pos = 0; /* start new item */
ps->npos++;
if (ps->npos >= ps->nitems) { /* last item? */
if (ps->reppos == -1) /* repeat set? */
return -1;
ps->npos = ps->reppos; /* redo from top */
}
}
return 0;
}
static struct ast_generator playtones = {
alloc: playtones_alloc,
release: playtones_release,
generate: playtones_generator,
};
int ast_playtones_start(struct ast_channel *chan, int vol, const char *playlst)
{
char *s, *data = strdupa(playlst); /* cute */
struct playtones_def d = { vol, -1, 0, NULL};
char *stringp=NULL;
if (!data)
return -1;
if (vol < 1)
d.vol = 8192;
stringp=data;
s = strsep(&stringp,",");
while(s && *s) {
int freq1, freq2, time;
if (s[0]=='!')
s++;
else if (d.reppos == -1)
d.reppos = d.nitems;
if (sscanf(s, "%d+%d/%d", &freq1, &freq2, &time) == 3) {
/* f1+f2/time format */
} else if (sscanf(s, "%d+%d", &freq1, &freq2) == 2) {
/* f1+f2 format */
time = 0;
} else if (sscanf(s, "%d/%d", &freq1, &time) == 2) {
/* f1/time format */
freq2 = 0;
} else if (sscanf(s, "%d", &freq1) == 1) {
/* f1 format */
freq2 = 0;
time = 0;
} else {
ast_log(LOG_WARNING,"%s: tone component '%s' of '%s' is no good\n",chan->name,s,playlst);
return -1;
}
d.items = realloc(d.items,(d.nitems+1)*sizeof(struct playtones_item));
if (d.items == NULL)
return -1;
d.items[d.nitems].freq1 = freq1;
d.items[d.nitems].freq2 = freq2;
d.items[d.nitems].duration = time;
d.nitems++;
s = strsep(&stringp,",");
}
if (ast_activate_generator(chan, &playtones, &d)) {
free(d.items);
return -1;
}
return 0;
}
void ast_playtones_stop(struct ast_channel *chan)
{
ast_deactivate_generator(chan);
}
/*--------------------------------------------*/
struct tone_zone *tone_zones;
static struct tone_zone *current_tonezone;
/* Protect the tone_zones list (highly unlikely that two things would change
* it at the same time, but still! */
pthread_mutex_t tzlock = AST_MUTEX_INITIALIZER;
/* Set global indication country */
int ast_set_indication_country(const char *country)
{
if (country) {
struct tone_zone *z = ast_get_indication_zone(country);
if (z) {
ast_verbose(VERBOSE_PREFIX_3 "Setting default indication country to '%s'\n",country);
current_tonezone = z;
return 0;
}
}
return 1; /* not found */
}
/* locate tone_zone, given the country. if country == NULL, use the default country */
struct tone_zone *ast_get_indication_zone(const char *country)
{
struct tone_zone *tz;
int alias_loop = 0;
/* we need some tonezone, pick the first */
if (country == NULL && current_tonezone)
return current_tonezone; /* default country? */
if (country == NULL && tone_zones)
return tone_zones; /* any country? */
if (country == NULL)
return 0; /* not a single country insight */
if (PTHREAD_MUTEX_LOCK(&tzlock)) {
ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
return 0;
}
do {
for (tz=tone_zones; tz; tz=tz->next) {
if (strcasecmp(country,tz->country)==0) {
/* tone_zone found */
if (tz->alias && tz->alias[0]) {
country = tz->alias;
break;
}
PTHREAD_MUTEX_UNLOCK(&tzlock);
return tz;
}
}
} while (++alias_loop<20 && tz);
PTHREAD_MUTEX_UNLOCK(&tzlock);
if (alias_loop==20)
ast_log(LOG_NOTICE,"Alias loop for '%s' forcefull broken\n",country);
/* nothing found, sorry */
return 0;
}
/* locate a tone_zone_sound, given the tone_zone. if tone_zone == NULL, use the default tone_zone */
struct tone_zone_sound *ast_get_indication_tone(const struct tone_zone *zone, const char *indication)
{
struct tone_zone_sound *ts;
/* we need some tonezone, pick the first */
if (zone == NULL && current_tonezone)
zone = current_tonezone; /* default country? */
if (zone == NULL && tone_zones)
zone = tone_zones; /* any country? */
if (zone == NULL)
return 0; /* not a single country insight */
if (PTHREAD_MUTEX_LOCK(&tzlock)) {
ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
return 0;
}
for (ts=zone->tones; ts; ts=ts->next) {
if (strcasecmp(indication,ts->name)==0) {
/* found indication! */
PTHREAD_MUTEX_UNLOCK(&tzlock);
return ts;
}
}
/* nothing found, sorry */
PTHREAD_MUTEX_UNLOCK(&tzlock);
return 0;
}
/* helper function to delete a tone_zone in its entirety */
static inline void free_zone(struct tone_zone* zone)
{
while (zone->tones) {
struct tone_zone_sound *tmp = zone->tones->next;
free((void*)zone->tones->name);
free((void*)zone->tones->data);
free(zone->tones);
zone->tones = tmp;
}
free(zone);
}
/*--------------------------------------------*/
/* add a new country, if country exists, it will be replaced. */
int ast_register_indication_country(struct tone_zone *zone)
{
struct tone_zone *tz,*pz;
if (PTHREAD_MUTEX_LOCK(&tzlock)) {
ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
return -1;
}
for (pz=NULL,tz=tone_zones; tz; pz=tz,tz=tz->next) {
if (strcasecmp(zone->country,tz->country)==0) {
/* tone_zone already there, replace */
zone->next = tz->next;
if (pz)
pz->next = zone;
else
tone_zones = zone;
/* if we are replacing the default zone, re-point it */
if (tz == current_tonezone)
current_tonezone = zone;
/* now free the previous zone */
free_zone(tz);
PTHREAD_MUTEX_UNLOCK(&tzlock);
return 0;
}
}
/* country not there, add */
zone->next = NULL;
if (pz)
pz->next = zone;
else
tone_zones = zone;
PTHREAD_MUTEX_UNLOCK(&tzlock);
ast_verbose(VERBOSE_PREFIX_3 "Registered indication country '%s'\n",zone->country);
return 0;
}
/* remove an existing country and all its indications, country must exist.
* Also, all countries which are an alias for the specified country are removed. */
int ast_unregister_indication_country(const char *country)
{
struct tone_zone *tz, *pz = NULL, *tmp;
int res = -1;
if (PTHREAD_MUTEX_LOCK(&tzlock)) {
ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
return -1;
}
tz = tone_zones;
while (tz) {
if (country==NULL ||
(strcasecmp(country, tz->country)==0 ||
strcasecmp(country, tz->alias)==0)) {
/* tone_zone found, remove */
tmp = tz->next;
if (pz)
pz->next = tmp;
else
tone_zones = tmp;
/* if we are unregistering the default country, w'll notice */
if (tz == current_tonezone) {
ast_log(LOG_NOTICE,"Removed default indication country '%s'\n",tz->country);
current_tonezone = NULL;
}
ast_verbose(VERBOSE_PREFIX_3 "Unregistered indication country '%s'\n",tz->country);
free_zone(tz);
tz = tmp;
res = 0;
}
else {
/* next zone please */
pz = tz;
tz = tz->next;
}
}
PTHREAD_MUTEX_UNLOCK(&tzlock);
return res;
}
/* add a new indication to a tone_zone. tone_zone must exist. if the indication already
* exists, it will be replaced. */
int ast_register_indication(struct tone_zone *zone, const char *indication, const char *tonelist)
{
struct tone_zone_sound *ts,*ps;
/* is it an alias? stop */
if (zone->alias[0])
return -1;
if (PTHREAD_MUTEX_LOCK(&tzlock)) {
ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
return -2;
}
for (ps=NULL,ts=zone->tones; ts; ps=ts,ts=ts->next) {
if (strcasecmp(indication,ts->name)==0) {
/* indication already there, replace */
free((void*)ts->name);
free((void*)ts->data);
break;
}
}
if (!ts) {
/* not there, we have to add */
ts = malloc(sizeof(struct tone_zone_sound));
if (!ts) {
ast_log(LOG_WARNING, "Out of memory\n");
PTHREAD_MUTEX_UNLOCK(&tzlock);
return -2;
}
ts->next = NULL;
}
ts->name = strdup(indication);
ts->data = strdup(tonelist);
if (ts->name==NULL || ts->data==NULL) {
ast_log(LOG_WARNING, "Out of memory\n");
PTHREAD_MUTEX_UNLOCK(&tzlock);
return -2;
}
if (ps)
ps->next = ts;
else
zone->tones = ts;
PTHREAD_MUTEX_UNLOCK(&tzlock);
return 0;
}
/* remove an existing country's indication. Both country and indication must exist */
int ast_unregister_indication(struct tone_zone *zone, const char *indication)
{
struct tone_zone_sound *ts,*ps = NULL, *tmp;
int res = -1;
/* is it an alias? stop */
if (zone->alias[0])
return -1;
if (PTHREAD_MUTEX_LOCK(&tzlock)) {
ast_log(LOG_WARNING, "Unable to lock tone_zones list\n");
return -1;
}
ts = zone->tones;
while (ts) {
if (strcasecmp(indication,ts->name)==0) {
/* indication found */
tmp = ts->next;
if (ps)
ps->next = tmp;
else
zone->tones = tmp;
free((void*)ts->name);
free((void*)ts->data);
free(ts);
ts = tmp;
res = 0;
}
else {
/* next zone please */
ps = ts;
ts = ts->next;
}
}
/* indication not found, goodbye */
PTHREAD_MUTEX_UNLOCK(&tzlock);
return res;
}

365
pbx/pbx_spool.c Executable file
View File

@ -0,0 +1,365 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Full-featured outgoing call spool support
*
* Copyright (C) 2002, Digium
*
* Mark Spencer <markster@digium.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#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/options.h>
#include <pthread.h>
#include <sys/stat.h>
#include <errno.h>
#include <time.h>
#include <utime.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "../astconf.h"
/*
* pbx_spool is similar in spirit to qcall, but with substantially enhanced functionality...
* The spool file contains a header
*/
static char *tdesc = "Outgoing Spool Support";
static char qdir[255];
struct outgoing {
char fn[256];
/* Current number of retries */
int retries;
/* Maximum number of retries permitted */
int maxretries;
/* How long to wait between retries (in seconds) */
int retrytime;
/* How long to wait for an answer */
int waittime;
/* What to connect to outgoing */
char tech[256];
char dest[256];
/* If application */
char app[256];
char data[256];
/* If extension/context/priority */
char exten[256];
char context[256];
int priority;
/* CallerID Information */
char callerid[256];
/* Channel variables */
char variable[10*256];
/* Maximum length of call */
int maxlen;
};
static void init_outgoing(struct outgoing *o)
{
memset(o, 0, sizeof(struct outgoing));
o->priority = 1;
o->retrytime = 300;
o->waittime = 45;
}
static int apply_outgoing(struct outgoing *o, char *fn, FILE *f)
{
char buf[256];
char *c, *c2;
int lineno = 0;
while(!feof(f)) {
fgets(buf, sizeof(buf), f);
lineno++;
if (!feof(f)) {
/* Trim comments */
c = strchr(buf, '#');
if (c)
*c = '\0';
c = strchr(buf, ';');
if (c)
*c = '\0';
/* Trim trailing white space */
while(strlen(buf) && buf[strlen(buf) - 1] < 33)
buf[strlen(buf) - 1] = '\0';
if (strlen(buf)) {
c = strchr(buf, ':');
if (c) {
*c = '\0';
c++;
while(*c < 33)
c++;
#if 0
printf("'%s' is '%s' at line %d\n", buf, c, lineno);
#endif
if (!strcasecmp(buf, "channel")) {
strncpy(o->tech, c, sizeof(o->tech) - 1);
if ((c2 = strchr(o->tech, '/'))) {
*c2 = '\0';
c2++;
strncpy(o->dest, c2, sizeof(o->dest) - 1);
} else {
ast_log(LOG_NOTICE, "Channel should be in form Tech/Dest at line %d of %s\n", lineno, fn);
strcpy(o->tech, "");
}
} else if (!strcasecmp(buf, "callerid")) {
strncpy(o->callerid, c, sizeof(o->callerid) - 1);
} else if (!strcasecmp(buf, "application")) {
strncpy(o->app, c, sizeof(o->app) - 1);
} else if (!strcasecmp(buf, "data")) {
strncpy(o->data, c, sizeof(o->data) - 1);
} else if (!strcasecmp(buf, "maxretries")) {
if (sscanf(c, "%d", &o->maxretries) != 1) {
ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, fn);
o->maxretries = 0;
}
} else if (!strcasecmp(buf, "context")) {
strncpy(o->context, c, sizeof(o->context) - 1);
} else if (!strcasecmp(buf, "extension")) {
strncpy(o->exten, c, sizeof(o->exten) - 1);
} else if (!strcasecmp(buf, "priority")) {
if ((sscanf(c, "%d", &o->priority) != 1) || (o->priority < 1)) {
ast_log(LOG_WARNING, "Invalid priority at line %d of %s\n", lineno, fn);
o->priority = 1;
}
} else if (!strcasecmp(buf, "retrytime")) {
if ((sscanf(c, "%d", &o->retrytime) != 1) || (o->retrytime < 1)) {
ast_log(LOG_WARNING, "Invalid retrytime at line %d of %s\n", lineno, fn);
o->retrytime = 300;
}
} else if (!strcasecmp(buf, "waittime")) {
if ((sscanf(c, "%d", &o->waittime) != 1) || (o->waittime < 1)) {
ast_log(LOG_WARNING, "Invalid retrytime at line %d of %s\n", lineno, fn);
o->waittime = 45;
}
} else if (!strcasecmp(buf, "retry")) {
o->retries++;
} else if (!strcasecmp(buf, "setvar")) { /* JDG variable support */
strncat(o->variable, c, sizeof(o->variable) - strlen(o->variable) - 1);
strncat(o->variable, "|", sizeof(o->variable) - strlen(o->variable) - 1);
} else {
ast_log(LOG_WARNING, "Unknown keyword '%s' at line %d of %s\n", buf, lineno, fn);
}
} else
ast_log(LOG_NOTICE, "Syntax error at line %d of %s\n", lineno, fn);
}
}
}
strncpy(o->fn, fn, sizeof(o->fn) - 1);
/* Check sanity of times */
if (o->retrytime < o->waittime + 5)
o->retrytime = o->waittime + 5;
if (!strlen(o->tech) || !strlen(o->dest) || (!strlen(o->app) && !strlen(o->exten))) {
ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn);
return -1;
}
return 0;
}
static void *attempt_thread(void *data)
{
struct outgoing *o = data;
int res, reason;
if (strlen(o->app)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->callerid);
} else {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
res = ast_pbx_outgoing_exten(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->callerid, o->variable );
}
if (res) {
ast_log(LOG_NOTICE, "Call failed to go through, reason %d\n", reason);
if (o->retries >= o->maxretries + 1) {
/* Max retries exceeded */
ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt(s)\n", o->tech, o->dest, o->retries - 1);
unlink(o->fn);
}
} else {
ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest);
unlink(o->fn);
}
free(o);
return NULL;
}
static void launch_service(struct outgoing *o)
{
pthread_t t;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&t,&attr,attempt_thread, o) == -1) {
ast_log(LOG_WARNING, "Unable to create thread :(\n");
free(o);
}
}
static int scan_service(char *fn, time_t now, time_t atime)
{
struct outgoing *o;
struct utimbuf tbuf;
FILE *f;
o = malloc(sizeof(struct outgoing));
if (o) {
init_outgoing(o);
f = fopen(fn, "r+");
if (f) {
if (!apply_outgoing(o, fn, f)) {
/* Update the file time */
tbuf.actime = atime;
tbuf.modtime = now + o->retrytime;
if (utime(o->fn, &tbuf))
ast_log(LOG_WARNING, "Unable to set utime on %s: %s\n", fn, strerror(errno));
/* Increment retries */
o->retries++;
#if 0
printf("Retries: %d, max: %d\n", o->retries, o->maxretries);
#endif
if (o->retries <= o->maxretries + 1) {
/* Add a retry line at the end */
fseek(f, 0L, SEEK_END);
fprintf(f, "Retry: %d (%ld)\n", o->retries, now);
fclose(f);
now += o->retrytime;
launch_service(o);
return now;
} else {
ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt(s)\n", o->tech, o->dest, o->retries - 1);
fclose(f);
free(o);
unlink(fn);
return 0;
}
} else {
free(o);
ast_log(LOG_WARNING, "Invalid file contents in %s, deleting\n", fn);
fclose(f);
unlink(fn);
}
} else {
free(o);
ast_log(LOG_WARNING, "Unable to open %s: %s, deleting\n", fn, strerror(errno));
unlink(fn);
}
} else
ast_log(LOG_WARNING, "Out of memory :(\n");
return -1;
}
static void *scan_thread(void *unused)
{
struct stat st;
DIR *dir;
struct dirent *de;
char fn[256];
int res;
time_t last = 0, next = 0, now;
for(;;) {
/* Wait a sec */
sleep(1);
time(&now);
if (!stat(qdir, &st)) {
if ((st.st_mtime != last) || (next && (now > next))) {
#if 0
printf("atime: %ld, mtime: %ld, ctime: %ld\n", st.st_atime, st.st_mtime, st.st_ctime);
printf("Ooh, something changed / timeout\n");
#endif
next = 0;
last = st.st_mtime;
dir = opendir(qdir);
if (dir) {
while((de = readdir(dir))) {
snprintf(fn, sizeof(fn), "%s/%s", qdir, de->d_name);
if (!stat(fn, &st)) {
if (S_ISREG(st.st_mode)) {
if (st.st_mtime <= now) {
res = scan_service(fn, now, st.st_atime);
if (res > 0) {
/* Update next service time */
if (!next || (res < next)) {
next = res;
}
} else if (res)
ast_log(LOG_WARNING, "Failed to scan service '%s'\n", fn);
} else {
/* Update "next" update if necessary */
if (!next || (st.st_mtime < next))
next = st.st_mtime;
}
}
} else
ast_log(LOG_WARNING, "Unable to stat %s: %s\n", fn, strerror(errno));
}
closedir(dir);
} else
ast_log(LOG_WARNING, "Unable to open directory %s: %s\n", qdir, strerror(errno));
}
} else
ast_log(LOG_WARNING, "Unable to stat %s\n", qdir);
}
return NULL;
}
int unload_module(void)
{
return -1;
}
int load_module(void)
{
pthread_t thread;
pthread_attr_t attr;
snprintf((char *)qdir,sizeof(qdir)-1,"%s/%s",(char *)ast_config_AST_SPOOL_DIR,"outgoing");
printf("%s\n",qdir);
if (mkdir(qdir, 0700) && (errno != EEXIST)) {
ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool disabled\n", qdir);
return 0;
}
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&thread,&attr,scan_thread, NULL) == -1) {
ast_log(LOG_WARNING, "Unable to create thread :(\n");
return -1;
}
return 0;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
return 1;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@ -20,7 +20,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <math.h> #include <math.h>
#include <errno.h>
#include <asterisk/ulaw.h> #include <asterisk/ulaw.h>
#include <asterisk/alaw.h>
#include <asterisk/callerid.h> #include <asterisk/callerid.h>
#include <asterisk/logger.h> #include <asterisk/logger.h>
#include <asterisk/fskmodem.h> #include <asterisk/fskmodem.h>
@ -49,7 +51,7 @@ static char speeddial[ADSI_MAX_SPEED_DIAL][3][20];
static int alignment = 0; static int alignment = 0;
static int adsi_generate(unsigned char *buf, int msgtype, char *msg, int msglen, int msgnum, int last) static int adsi_generate(unsigned char *buf, int msgtype, char *msg, int msglen, int msgnum, int last, int codec)
{ {
int sum; int sum;
int x; int x;
@ -121,7 +123,7 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l
outf.subclass = AST_FORMAT_ULAW; outf.subclass = AST_FORMAT_ULAW;
outf.data = buf; outf.data = buf;
outf.datalen = amt; outf.datalen = amt;
outf.timelen = amt * 8; outf.samples = amt;
if (ast_write(chan, &outf)) { if (ast_write(chan, &outf)) {
ast_log(LOG_WARNING, "Failed to carefully write frame\n"); ast_log(LOG_WARNING, "Failed to carefully write frame\n");
return -1; return -1;
@ -156,7 +158,7 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l
outf.subclass = AST_FORMAT_ULAW; outf.subclass = AST_FORMAT_ULAW;
outf.data = buf; outf.data = buf;
outf.datalen = amt; outf.datalen = amt;
outf.timelen = amt * 8; outf.samples = amt;
if (ast_write(chan, &outf)) { if (ast_write(chan, &outf)) {
ast_log(LOG_WARNING, "Failed to carefully write frame\n"); ast_log(LOG_WARNING, "Failed to carefully write frame\n");
return -1; return -1;
@ -196,7 +198,7 @@ static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **ms
while(retries < maxretries) { while(retries < maxretries) {
if (!(chan->adsicpe & ADSI_FLAG_DATAMODE)) { if (!(chan->adsicpe & ADSI_FLAG_DATAMODE)) {
/* Generate CAS (no SAS) */ /* Generate CAS (no SAS) */
ast_gen_cas(buf, 0, 680); ast_gen_cas(buf, 0, 680, AST_FORMAT_ULAW);
/* Send CAS */ /* Send CAS */
if (adsi_careful_send(chan, buf, 680, NULL)) { if (adsi_careful_send(chan, buf, 680, NULL)) {
@ -249,7 +251,7 @@ static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **ms
def= ast_channel_defer_dtmf(chan); def= ast_channel_defer_dtmf(chan);
#endif #endif
while((x < 6) && msg[x]) { while((x < 6) && msg[x]) {
res = adsi_generate(buf + pos, msgtype[x], msg[x], msglen[x], x+1 - start, (x == 5) || !msg[x+1]); res = adsi_generate(buf + pos, msgtype[x], msg[x], msglen[x], x+1 - start, (x == 5) || !msg[x+1], AST_FORMAT_ULAW);
if (res < 0) { if (res < 0) {
ast_log(LOG_WARNING, "Failed to generate ADSI message %d on channel %s\n", x + 1, chan->name); ast_log(LOG_WARNING, "Failed to generate ADSI message %d on channel %s\n", x + 1, chan->name);
return -1; return -1;
@ -1046,8 +1048,10 @@ static void adsi_load(void)
total = x; total = x;
x = 0; x = 0;
while(v) { while(v) {
name = strtok(v->value, ","); char *stringp=NULL;
sname = strtok(NULL, ","); stringp=v->value;
name = strsep(&stringp, ",");
sname = strsep(&stringp, ",");
if (!sname) if (!sname)
sname = name; sname = name;
if (x < ADSI_MAX_SPEED_DIAL) { if (x < ADSI_MAX_SPEED_DIAL) {

View File

@ -28,7 +28,10 @@
#include <dirent.h> #include <dirent.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include "../asterisk.h" #include "../asterisk.h"
#include "../astconf.h"
/* /*
* Asterisk uses RSA keys with SHA-1 message digests for its * Asterisk uses RSA keys with SHA-1 message digests for its
@ -460,14 +463,14 @@ static void crypto_load(int ifd, int ofd)
} }
ast_pthread_mutex_unlock(&keylock); ast_pthread_mutex_unlock(&keylock);
/* Load new keys */ /* Load new keys */
dir = opendir(AST_KEY_DIR); dir = opendir((char *)ast_config_AST_KEY_DIR);
if (dir) { if (dir) {
while((ent = readdir(dir))) { while((ent = readdir(dir))) {
try_load_key(AST_KEY_DIR, ent->d_name, ifd, ofd, &note); try_load_key((char *)ast_config_AST_KEY_DIR, ent->d_name, ifd, ofd, &note);
} }
closedir(dir); closedir(dir);
} else } else
ast_log(LOG_WARNING, "Unable to open key directory '%s'\n", AST_KEY_DIR); ast_log(LOG_WARNING, "Unable to open key directory '%s'\n", (char *)ast_config_AST_KEY_DIR);
if (note) { if (note) {
ast_log(LOG_NOTICE, "Please run the command 'init keys' to enter the passcodes for the keys\n"); ast_log(LOG_NOTICE, "Please run the command 'init keys' to enter the passcodes for the keys\n");
} }
@ -531,9 +534,9 @@ static int init_keys(int fd, int argc, char *argv[])
while(key) { while(key) {
/* Reload keys that need pass codes now */ /* Reload keys that need pass codes now */
if (key->ktype & KEY_NEEDS_PASSCODE) { if (key->ktype & KEY_NEEDS_PASSCODE) {
kn = key->fn + strlen(AST_KEY_DIR) + 1; kn = key->fn + strlen(ast_config_AST_KEY_DIR) + 1;
strncpy(tmp, kn, sizeof(tmp)); strncpy(tmp, kn, sizeof(tmp));
try_load_key(AST_KEY_DIR, tmp, fd, fd, &ign); try_load_key((char *)ast_config_AST_KEY_DIR, tmp, fd, fd, &ign);
} }
key = key->next; key = key->next;
} }