mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 12:36:58 +00:00
(closes issue #11825)
Reported by: ctooley Patches: additional_eivr_commands.patch uploaded by ctooley (license 136) Tested by: ctooley git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@103662 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -85,7 +85,11 @@ struct gen_state {
|
|||||||
int sample_queue;
|
int sample_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void send_child_event(FILE *handle, const char event, const char *data,
|
static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
|
||||||
|
int eivr_events_fd, int eivr_commands_fd, int eivr_errors_fd,
|
||||||
|
const char *args);
|
||||||
|
|
||||||
|
static void send_eivr_event(FILE *handle, const char event, const char *data,
|
||||||
const struct ast_channel *chan)
|
const struct ast_channel *chan)
|
||||||
{
|
{
|
||||||
char tmp[256];
|
char tmp[256];
|
||||||
@@ -222,6 +226,69 @@ static struct ast_generator gen =
|
|||||||
generate: gen_generate,
|
generate: gen_generate,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void ast_eivr_getvariable(struct ast_channel *chan, char *data, char *outbuf, int outbuflen)
|
||||||
|
{
|
||||||
|
// original input data: "G,var1,var2,"
|
||||||
|
// data passed as "data": "var1,var2"
|
||||||
|
char *inbuf, *variable;
|
||||||
|
|
||||||
|
const char *value;
|
||||||
|
char *saveptr;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
outbuf[0] = 0;
|
||||||
|
|
||||||
|
for (j = 1, inbuf = data; ; j++, inbuf = NULL) {
|
||||||
|
variable = strtok_r(inbuf, ",", &saveptr);
|
||||||
|
if (variable == NULL) {
|
||||||
|
int outstrlen = strlen(outbuf);
|
||||||
|
if(outstrlen && outbuf[outstrlen - 1] == ',') {
|
||||||
|
outbuf[outstrlen - 1] = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = pbx_builtin_getvar_helper(chan, variable);
|
||||||
|
if(!value)
|
||||||
|
value = "";
|
||||||
|
strncat(outbuf,variable,outbuflen);
|
||||||
|
strncat(outbuf,"=",outbuflen);
|
||||||
|
strncat(outbuf,value,outbuflen);
|
||||||
|
strncat(outbuf,",",outbuflen);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ast_eivr_setvariable(struct ast_channel *chan, char *data)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
char *inbuf, *variable;
|
||||||
|
|
||||||
|
char *saveptr;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for(j=1, inbuf=data; ; j++, inbuf=NULL) {
|
||||||
|
variable = strtok_r(inbuf, ",", &saveptr);
|
||||||
|
ast_chan_log(LOG_DEBUG, chan, "Setting up a variable: %s\n", variable);
|
||||||
|
if(variable) {
|
||||||
|
//variable contains "varname=value"
|
||||||
|
strncpy(buf, variable, sizeof(buf));
|
||||||
|
value = strchr(buf, '=');
|
||||||
|
if(!value)
|
||||||
|
value="";
|
||||||
|
else {
|
||||||
|
value[0] = 0;
|
||||||
|
value++;
|
||||||
|
}
|
||||||
|
pbx_builtin_setvar_helper(chan, buf, value);
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
static struct playlist_entry *make_entry(const char *filename)
|
static struct playlist_entry *make_entry(const char *filename)
|
||||||
{
|
{
|
||||||
struct playlist_entry *entry;
|
struct playlist_entry *entry;
|
||||||
@@ -243,10 +310,7 @@ static int app_exec(struct ast_channel *chan, void *data)
|
|||||||
int res = -1;
|
int res = -1;
|
||||||
int gen_active = 0;
|
int gen_active = 0;
|
||||||
int pid;
|
int pid;
|
||||||
char *buf, *command;
|
char *buf, *pipe_delim_argbuf, *pdargbuf_ptr;
|
||||||
FILE *child_commands = NULL;
|
|
||||||
FILE *child_errors = NULL;
|
|
||||||
FILE *child_events = NULL;
|
|
||||||
struct ivr_localuser foo = {
|
struct ivr_localuser foo = {
|
||||||
.playlist = AST_LIST_HEAD_INIT_VALUE,
|
.playlist = AST_LIST_HEAD_INIT_VALUE,
|
||||||
.finishlist = AST_LIST_HEAD_INIT_VALUE,
|
.finishlist = AST_LIST_HEAD_INIT_VALUE,
|
||||||
@@ -271,25 +335,26 @@ static int app_exec(struct ast_channel *chan, void *data)
|
|||||||
buf = ast_strdupa(data);
|
buf = ast_strdupa(data);
|
||||||
AST_STANDARD_APP_ARGS(args, buf);
|
AST_STANDARD_APP_ARGS(args, buf);
|
||||||
|
|
||||||
|
//copy args and replace commas with pipes
|
||||||
|
pipe_delim_argbuf = ast_strdupa(data);
|
||||||
|
while((pdargbuf_ptr = strchr(pipe_delim_argbuf, ',')) != NULL)
|
||||||
|
pdargbuf_ptr[0] = '|';
|
||||||
|
|
||||||
if (pipe(child_stdin)) {
|
if (pipe(child_stdin)) {
|
||||||
ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child input: %s\n", strerror(errno));
|
ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child input: %s\n", strerror(errno));
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipe(child_stdout)) {
|
if (pipe(child_stdout)) {
|
||||||
ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child output: %s\n", strerror(errno));
|
ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child output: %s\n", strerror(errno));
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipe(child_stderr)) {
|
if (pipe(child_stderr)) {
|
||||||
ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child errors: %s\n", strerror(errno));
|
ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child errors: %s\n", strerror(errno));
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan->_state != AST_STATE_UP) {
|
if (chan->_state != AST_STATE_UP) {
|
||||||
ast_answer(chan);
|
ast_answer(chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ast_activate_generator(chan, &gen, u) < 0) {
|
if (ast_activate_generator(chan, &gen, u) < 0) {
|
||||||
ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n");
|
ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
@@ -322,17 +387,6 @@ static int app_exec(struct ast_channel *chan, void *data)
|
|||||||
_exit(1);
|
_exit(1);
|
||||||
} else {
|
} else {
|
||||||
/* parent process */
|
/* parent process */
|
||||||
int child_events_fd = child_stdin[1];
|
|
||||||
int child_commands_fd = child_stdout[0];
|
|
||||||
int child_errors_fd = child_stderr[0];
|
|
||||||
struct ast_frame *f;
|
|
||||||
int ms;
|
|
||||||
int exception;
|
|
||||||
int ready_fd;
|
|
||||||
int waitfds[2] = { child_errors_fd, child_commands_fd };
|
|
||||||
struct ast_channel *rchan;
|
|
||||||
|
|
||||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
|
||||||
|
|
||||||
close(child_stdin[0]);
|
close(child_stdin[0]);
|
||||||
child_stdin[0] = 0;
|
child_stdin[0] = 0;
|
||||||
@@ -340,204 +394,12 @@ static int app_exec(struct ast_channel *chan, void *data)
|
|||||||
child_stdout[1] = 0;
|
child_stdout[1] = 0;
|
||||||
close(child_stderr[1]);
|
close(child_stderr[1]);
|
||||||
child_stderr[1] = 0;
|
child_stderr[1] = 0;
|
||||||
|
res = eivr_comm(chan, u, child_stdin[1], child_stdout[0], child_stderr[0], pipe_delim_argbuf);
|
||||||
if (!(child_events = fdopen(child_events_fd, "w"))) {
|
|
||||||
ast_chan_log(LOG_WARNING, chan, "Could not open stream for child events\n");
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(child_commands = fdopen(child_commands_fd, "r"))) {
|
|
||||||
ast_chan_log(LOG_WARNING, chan, "Could not open stream for child commands\n");
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(child_errors = fdopen(child_errors_fd, "r"))) {
|
|
||||||
ast_chan_log(LOG_WARNING, chan, "Could not open stream for child errors\n");
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
setvbuf(child_events, NULL, _IONBF, 0);
|
|
||||||
setvbuf(child_commands, NULL, _IONBF, 0);
|
|
||||||
setvbuf(child_errors, NULL, _IONBF, 0);
|
|
||||||
|
|
||||||
res = 0;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
if (ast_test_flag(chan, AST_FLAG_ZOMBIE)) {
|
|
||||||
ast_chan_log(LOG_NOTICE, chan, "Is a zombie\n");
|
|
||||||
res = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ast_check_hangup(chan)) {
|
|
||||||
ast_chan_log(LOG_NOTICE, chan, "Got check_hangup\n");
|
|
||||||
send_child_event(child_events, 'H', NULL, chan);
|
|
||||||
res = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ready_fd = 0;
|
|
||||||
ms = 100;
|
|
||||||
errno = 0;
|
|
||||||
exception = 0;
|
|
||||||
|
|
||||||
rchan = ast_waitfor_nandfds(&chan, 1, waitfds, 2, &exception, &ready_fd, &ms);
|
|
||||||
|
|
||||||
if (!AST_LIST_EMPTY(&u->finishlist)) {
|
|
||||||
AST_LIST_LOCK(&u->finishlist);
|
|
||||||
while ((entry = AST_LIST_REMOVE_HEAD(&u->finishlist, list))) {
|
|
||||||
send_child_event(child_events, 'F', entry->filename, chan);
|
|
||||||
ast_free(entry);
|
|
||||||
}
|
|
||||||
AST_LIST_UNLOCK(&u->finishlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rchan) {
|
|
||||||
/* the channel has something */
|
|
||||||
f = ast_read(chan);
|
|
||||||
if (!f) {
|
|
||||||
ast_chan_log(LOG_NOTICE, chan, "Returned no frame\n");
|
|
||||||
send_child_event(child_events, 'H', NULL, chan);
|
|
||||||
res = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f->frametype == AST_FRAME_DTMF) {
|
|
||||||
send_child_event(child_events, f->subclass, NULL, chan);
|
|
||||||
if (u->option_autoclear) {
|
|
||||||
if (!u->abort_current_sound && !u->playing_silence)
|
|
||||||
send_child_event(child_events, 'T', NULL, chan);
|
|
||||||
AST_LIST_LOCK(&u->playlist);
|
|
||||||
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
|
|
||||||
send_child_event(child_events, 'D', entry->filename, chan);
|
|
||||||
ast_free(entry);
|
|
||||||
}
|
|
||||||
if (!u->playing_silence)
|
|
||||||
u->abort_current_sound = 1;
|
|
||||||
AST_LIST_UNLOCK(&u->playlist);
|
|
||||||
}
|
|
||||||
} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
|
|
||||||
ast_chan_log(LOG_NOTICE, chan, "Got AST_CONTROL_HANGUP\n");
|
|
||||||
send_child_event(child_events, 'H', NULL, chan);
|
|
||||||
ast_frfree(f);
|
|
||||||
res = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ast_frfree(f);
|
|
||||||
} else if (ready_fd == child_commands_fd) {
|
|
||||||
char input[1024];
|
|
||||||
|
|
||||||
if (exception || feof(child_commands)) {
|
|
||||||
ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
|
|
||||||
res = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fgets(input, sizeof(input), child_commands))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
command = ast_strip(input);
|
|
||||||
|
|
||||||
if (option_debug)
|
|
||||||
ast_chan_log(LOG_DEBUG, chan, "got command '%s'\n", input);
|
|
||||||
|
|
||||||
if (strlen(input) < 4)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (input[0] == 'S') {
|
|
||||||
if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
|
|
||||||
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
|
|
||||||
send_child_event(child_events, 'Z', NULL, chan);
|
|
||||||
strcpy(&input[2], "exception");
|
|
||||||
}
|
|
||||||
if (!u->abort_current_sound && !u->playing_silence)
|
|
||||||
send_child_event(child_events, 'T', NULL, chan);
|
|
||||||
AST_LIST_LOCK(&u->playlist);
|
|
||||||
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
|
|
||||||
send_child_event(child_events, 'D', entry->filename, chan);
|
|
||||||
ast_free(entry);
|
|
||||||
}
|
|
||||||
if (!u->playing_silence)
|
|
||||||
u->abort_current_sound = 1;
|
|
||||||
entry = make_entry(&input[2]);
|
|
||||||
if (entry)
|
|
||||||
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
|
|
||||||
AST_LIST_UNLOCK(&u->playlist);
|
|
||||||
} else if (input[0] == 'A') {
|
|
||||||
if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
|
|
||||||
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
|
|
||||||
send_child_event(child_events, 'Z', NULL, chan);
|
|
||||||
strcpy(&input[2], "exception");
|
|
||||||
}
|
|
||||||
entry = make_entry(&input[2]);
|
|
||||||
if (entry) {
|
|
||||||
AST_LIST_LOCK(&u->playlist);
|
|
||||||
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
|
|
||||||
AST_LIST_UNLOCK(&u->playlist);
|
|
||||||
}
|
|
||||||
} else if (input[0] == 'E') {
|
|
||||||
ast_chan_log(LOG_NOTICE, chan, "Exiting: %s\n", &input[2]);
|
|
||||||
send_child_event(child_events, 'E', NULL, chan);
|
|
||||||
res = 0;
|
|
||||||
break;
|
|
||||||
} else if (input[0] == 'H') {
|
|
||||||
ast_chan_log(LOG_NOTICE, chan, "Hanging up: %s\n", &input[2]);
|
|
||||||
send_child_event(child_events, 'H', NULL, chan);
|
|
||||||
res = -1;
|
|
||||||
break;
|
|
||||||
} else if (input[0] == 'O') {
|
|
||||||
if (!strcasecmp(&input[2], "autoclear"))
|
|
||||||
u->option_autoclear = 1;
|
|
||||||
else if (!strcasecmp(&input[2], "noautoclear"))
|
|
||||||
u->option_autoclear = 0;
|
|
||||||
else
|
|
||||||
ast_chan_log(LOG_WARNING, chan, "Unknown option requested '%s'\n", &input[2]);
|
|
||||||
} else if (input[0] == 'V') {
|
|
||||||
char *c;
|
|
||||||
c = strchr(&input[2], '=');
|
|
||||||
if (!c) {
|
|
||||||
send_child_event(child_events, 'Z', NULL, chan);
|
|
||||||
} else {
|
|
||||||
*c++ = '\0';
|
|
||||||
pbx_builtin_setvar_helper(chan, &input[2], c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (ready_fd == child_errors_fd) {
|
|
||||||
char input[1024];
|
|
||||||
|
|
||||||
if (exception || feof(child_errors)) {
|
|
||||||
ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
|
|
||||||
res = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fgets(input, sizeof(input), child_errors)) {
|
|
||||||
command = ast_strip(input);
|
|
||||||
ast_chan_log(LOG_NOTICE, chan, "stderr: %s\n", command);
|
|
||||||
}
|
|
||||||
} else if ((ready_fd < 0) && ms) {
|
|
||||||
if (errno == 0 || errno == EINTR)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ast_chan_log(LOG_WARNING, chan, "Wait failed (%s)\n", strerror(errno));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (gen_active)
|
if (gen_active)
|
||||||
ast_deactivate_generator(chan);
|
ast_deactivate_generator(chan);
|
||||||
|
|
||||||
if (child_events)
|
|
||||||
fclose(child_events);
|
|
||||||
|
|
||||||
if (child_commands)
|
|
||||||
fclose(child_commands);
|
|
||||||
|
|
||||||
if (child_errors)
|
|
||||||
fclose(child_errors);
|
|
||||||
|
|
||||||
if (child_stdin[0])
|
if (child_stdin[0])
|
||||||
close(child_stdin[0]);
|
close(child_stdin[0]);
|
||||||
|
|
||||||
@@ -560,8 +422,235 @@ static int app_exec(struct ast_channel *chan, void *data)
|
|||||||
ast_free(entry);
|
ast_free(entry);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
|
||||||
|
int eivr_events_fd, int eivr_commands_fd, int eivr_errors_fd,
|
||||||
|
const char *args)
|
||||||
|
{
|
||||||
|
struct playlist_entry *entry;
|
||||||
|
struct ast_frame *f;
|
||||||
|
int ms;
|
||||||
|
int exception;
|
||||||
|
int ready_fd;
|
||||||
|
int waitfds[2] = { eivr_commands_fd, eivr_errors_fd };
|
||||||
|
struct ast_channel *rchan;
|
||||||
|
char *command;
|
||||||
|
int res = -1;
|
||||||
|
|
||||||
|
FILE *eivr_commands = NULL;
|
||||||
|
FILE *eivr_errors = NULL;
|
||||||
|
FILE *eivr_events = NULL;
|
||||||
|
|
||||||
|
if (!(eivr_events = fdopen(eivr_events_fd, "w"))) {
|
||||||
|
ast_chan_log(LOG_WARNING, chan, "Could not open stream to send events\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!(eivr_commands = fdopen(eivr_commands_fd, "r"))) {
|
||||||
|
ast_chan_log(LOG_WARNING, chan, "Could not open stream to receive commands\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if(eivr_errors_fd) { /*if opening a socket connection, error stream will not be used*/
|
||||||
|
if (!(eivr_errors = fdopen(eivr_errors_fd, "r"))) {
|
||||||
|
ast_chan_log(LOG_WARNING, chan, "Could not open stream to receive errors\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setvbuf(eivr_events, NULL, _IONBF, 0);
|
||||||
|
setvbuf(eivr_commands, NULL, _IONBF, 0);
|
||||||
|
if(eivr_errors)
|
||||||
|
setvbuf(eivr_errors, NULL, _IONBF, 0);
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (ast_test_flag(chan, AST_FLAG_ZOMBIE)) {
|
||||||
|
ast_chan_log(LOG_NOTICE, chan, "Is a zombie\n");
|
||||||
|
res = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ast_check_hangup(chan)) {
|
||||||
|
ast_chan_log(LOG_NOTICE, chan, "Got check_hangup\n");
|
||||||
|
send_eivr_event(eivr_events, 'H', NULL, chan);
|
||||||
|
res = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ready_fd = 0;
|
||||||
|
ms = 100;
|
||||||
|
errno = 0;
|
||||||
|
exception = 0;
|
||||||
|
|
||||||
|
rchan = ast_waitfor_nandfds(&chan, 1, waitfds, 2, &exception, &ready_fd, &ms);
|
||||||
|
|
||||||
|
if (!AST_LIST_EMPTY(&u->finishlist)) {
|
||||||
|
AST_LIST_LOCK(&u->finishlist);
|
||||||
|
while ((entry = AST_LIST_REMOVE_HEAD(&u->finishlist, list))) {
|
||||||
|
send_eivr_event(eivr_events, 'F', entry->filename, chan);
|
||||||
|
ast_free(entry);
|
||||||
|
}
|
||||||
|
AST_LIST_UNLOCK(&u->finishlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rchan) {
|
||||||
|
/* the channel has something */
|
||||||
|
f = ast_read(chan);
|
||||||
|
if (!f) {
|
||||||
|
ast_chan_log(LOG_NOTICE, chan, "Returned no frame\n");
|
||||||
|
send_eivr_event(eivr_events, 'H', NULL, chan);
|
||||||
|
res = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (f->frametype == AST_FRAME_DTMF) {
|
||||||
|
send_eivr_event(eivr_events, f->subclass, NULL, chan);
|
||||||
|
if (u->option_autoclear) {
|
||||||
|
if (!u->abort_current_sound && !u->playing_silence)
|
||||||
|
send_eivr_event(eivr_events, 'T', NULL, chan);
|
||||||
|
AST_LIST_LOCK(&u->playlist);
|
||||||
|
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
|
||||||
|
send_eivr_event(eivr_events, 'D', entry->filename, chan);
|
||||||
|
ast_free(entry);
|
||||||
|
}
|
||||||
|
if (!u->playing_silence)
|
||||||
|
u->abort_current_sound = 1;
|
||||||
|
AST_LIST_UNLOCK(&u->playlist);
|
||||||
|
}
|
||||||
|
} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
|
||||||
|
ast_chan_log(LOG_NOTICE, chan, "Got AST_CONTROL_HANGUP\n");
|
||||||
|
send_eivr_event(eivr_events, 'H', NULL, chan);
|
||||||
|
ast_frfree(f);
|
||||||
|
res = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ast_frfree(f);
|
||||||
|
} else if (ready_fd == eivr_commands_fd) {
|
||||||
|
char input[1024];
|
||||||
|
|
||||||
|
if (exception || feof(eivr_commands)) {
|
||||||
|
ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
|
||||||
|
res = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fgets(input, sizeof(input), eivr_commands))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
command = ast_strip(input);
|
||||||
|
|
||||||
|
if (option_debug)
|
||||||
|
ast_chan_log(LOG_DEBUG, chan, "got command '%s'\n", input);
|
||||||
|
|
||||||
|
if (strlen(input) < 4)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (input[0] == 'P') {
|
||||||
|
send_eivr_event(eivr_events, 'P', args, chan);
|
||||||
|
|
||||||
|
} else if (input[0] == 'S') {
|
||||||
|
if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
|
||||||
|
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
|
||||||
|
send_eivr_event(eivr_events, 'Z', NULL, chan);
|
||||||
|
strcpy(&input[2], "exception");
|
||||||
|
}
|
||||||
|
if (!u->abort_current_sound && !u->playing_silence)
|
||||||
|
send_eivr_event(eivr_events, 'T', NULL, chan);
|
||||||
|
AST_LIST_LOCK(&u->playlist);
|
||||||
|
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
|
||||||
|
send_eivr_event(eivr_events, 'D', entry->filename, chan);
|
||||||
|
ast_free(entry);
|
||||||
|
}
|
||||||
|
if (!u->playing_silence)
|
||||||
|
u->abort_current_sound = 1;
|
||||||
|
entry = make_entry(&input[2]);
|
||||||
|
if (entry)
|
||||||
|
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
|
||||||
|
AST_LIST_UNLOCK(&u->playlist);
|
||||||
|
} else if (input[0] == 'A') {
|
||||||
|
if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
|
||||||
|
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
|
||||||
|
send_eivr_event(eivr_events, 'Z', NULL, chan);
|
||||||
|
strcpy(&input[2], "exception");
|
||||||
|
}
|
||||||
|
entry = make_entry(&input[2]);
|
||||||
|
if (entry) {
|
||||||
|
AST_LIST_LOCK(&u->playlist);
|
||||||
|
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
|
||||||
|
AST_LIST_UNLOCK(&u->playlist);
|
||||||
|
}
|
||||||
|
} else if (input[0] == 'G') {
|
||||||
|
// A get variable message: "G,variable1,variable2,..."
|
||||||
|
char response[2048];
|
||||||
|
ast_chan_log(LOG_NOTICE, chan, "Getting a Variable out of the channel: %s\n", &input[2]);
|
||||||
|
ast_eivr_getvariable(chan, &input[2], response, sizeof(response));
|
||||||
|
send_eivr_event(eivr_events, 'G', response, chan);
|
||||||
|
} else if (input[0] == 'V') {
|
||||||
|
// A set variable message: "V,variablename=foo"
|
||||||
|
ast_chan_log(LOG_NOTICE, chan, "Setting a Variable up: %s\n", &input[2]);
|
||||||
|
ast_eivr_setvariable(chan, &input[2]);
|
||||||
|
} else if (input[0] == 'L') {
|
||||||
|
ast_chan_log(LOG_NOTICE, chan, "Log message from EIVR: %s\n", &input[2]);
|
||||||
|
} else if (input[0] == 'X') {
|
||||||
|
ast_chan_log(LOG_NOTICE, chan, "Exiting ExternalIVR: %s\n", &input[2]);
|
||||||
|
//TODO: add deprecation debug message for X command here
|
||||||
|
res = 0;
|
||||||
|
break;
|
||||||
|
} else if (input[0] == 'E') {
|
||||||
|
ast_chan_log(LOG_NOTICE, chan, "Exiting: %s\n", &input[2]);
|
||||||
|
send_eivr_event(eivr_events, 'E', NULL, chan);
|
||||||
|
res = 0;
|
||||||
|
break;
|
||||||
|
} else if (input[0] == 'H') {
|
||||||
|
ast_chan_log(LOG_NOTICE, chan, "Hanging up: %s\n", &input[2]);
|
||||||
|
send_eivr_event(eivr_events, 'H', NULL, chan);
|
||||||
|
res = -1;
|
||||||
|
break;
|
||||||
|
} else if (input[0] == 'O') {
|
||||||
|
if (!strcasecmp(&input[2], "autoclear"))
|
||||||
|
u->option_autoclear = 1;
|
||||||
|
else if (!strcasecmp(&input[2], "noautoclear"))
|
||||||
|
u->option_autoclear = 0;
|
||||||
|
else
|
||||||
|
ast_chan_log(LOG_WARNING, chan, "Unknown option requested '%s'\n", &input[2]);
|
||||||
|
}
|
||||||
|
} else if (eivr_errors_fd && ready_fd == eivr_errors_fd) {
|
||||||
|
char input[1024];
|
||||||
|
|
||||||
|
if (exception || feof(eivr_errors)) {
|
||||||
|
ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
|
||||||
|
res = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fgets(input, sizeof(input), eivr_errors)) {
|
||||||
|
command = ast_strip(input);
|
||||||
|
ast_chan_log(LOG_NOTICE, chan, "stderr: %s\n", command);
|
||||||
|
}
|
||||||
|
} else if ((ready_fd < 0) && ms) {
|
||||||
|
if (errno == 0 || errno == EINTR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ast_chan_log(LOG_WARNING, chan, "Wait failed (%s)\n", strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
if (eivr_events)
|
||||||
|
fclose(eivr_events);
|
||||||
|
|
||||||
|
if (eivr_commands)
|
||||||
|
fclose(eivr_commands);
|
||||||
|
|
||||||
|
if (eivr_errors)
|
||||||
|
fclose(eivr_errors);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static int unload_module(void)
|
static int unload_module(void)
|
||||||
{
|
{
|
||||||
return ast_unregister_application(app);
|
return ast_unregister_application(app);
|
||||||
|
Reference in New Issue
Block a user