aboutsummaryrefslogtreecommitdiffstats
path: root/res
diff options
context:
space:
mode:
authorqwell <qwell@f38db490-d61c-443f-a65b-d21fe96a405b>2010-09-09 20:06:31 +0000
committerqwell <qwell@f38db490-d61c-443f-a65b-d21fe96a405b>2010-09-09 20:06:31 +0000
commitbbdc6cafb5a4c952b565135ee3470200673b310f (patch)
treebf8e77f6e4f2525aaca5cf79d01143c9973cdbd2 /res
parent994debde3c3d78011509a53fc68dd6ae27a6024e (diff)
Transmit silence when reading DTMF in ast_readstring.
Otherwise, you could get issues with DTMF timeouts causing hangups. (closes issue #17370) Reported by: makoto Patches: channel-readstring-silence-generator.patch uploaded by makoto (license 38) git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@285742 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'res')
-rw-r--r--res/res_config_odbc.c2
-rw-r--r--res/res_config_pgsql.c2
-rw-r--r--res/res_features.c148
-rw-r--r--res/res_musiconhold.c9
4 files changed, 105 insertions, 56 deletions
diff --git a/res/res_config_odbc.c b/res/res_config_odbc.c
index b735c0cd9..daed738d2 100644
--- a/res/res_config_odbc.c
+++ b/res/res_config_odbc.c
@@ -68,7 +68,7 @@ static void decode_chunk(char *chunk)
{
for (; *chunk; chunk++) {
if (*chunk == '^' && strchr("0123456789ABCDEFabcdef", chunk[1]) && strchr("0123456789ABCDEFabcdef", chunk[2])) {
- sscanf(chunk + 1, "%02hhd", chunk);
+ sscanf(chunk + 1, "%02hhX", chunk);
memmove(chunk + 1, chunk + 3, strlen(chunk + 3) + 1);
}
}
diff --git a/res/res_config_pgsql.c b/res/res_config_pgsql.c
index f6cd7250b..beed9e2dd 100644
--- a/res/res_config_pgsql.c
+++ b/res/res_config_pgsql.c
@@ -100,7 +100,7 @@ static char *decode_chunk(char *chunk)
char *orig = chunk;
for (; *chunk; chunk++) {
if (*chunk == '^' && strchr("0123456789ABCDEFabcdef", chunk[1]) && strchr("0123456789ABCDEFabcdef", chunk[2])) {
- sscanf(chunk + 1, "%02hhd", chunk);
+ sscanf(chunk + 1, "%02hhX", chunk);
memmove(chunk + 1, chunk + 3, strlen(chunk + 3) + 1);
}
}
diff --git a/res/res_features.c b/res/res_features.c
index 52f4449cd..fcea7c566 100644
--- a/res/res_features.c
+++ b/res/res_features.c
@@ -525,7 +525,7 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, in
}
}
- /* Wake up the (presumably select()ing) thread */
+ /* Wake up the (presumably poll()ing) thread */
pthread_kill(parking_thread, SIGURG);
/* Only say number if it's a number and the channel hasn't been masqueraded away */
@@ -2282,17 +2282,16 @@ static char *callback_dialoptions(struct ast_flags *features_callee, struct ast_
/*! \brief Take care of parked calls and unpark them if needed */
static void *do_parking_thread(void *ignore)
{
- fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
- FD_ZERO(&rfds);
- FD_ZERO(&efds);
+ /* results from previous poll, to be preserved across loops. */
+ struct pollfd *fds = NULL;
+ int nfds = 0;
+ struct timeval tv;
for (;;) {
struct parkeduser *pu, *pl, *pt = NULL;
- int ms = -1; /* select timeout, uninitialized */
- int max = -1; /* max fd, none there yet */
- fd_set nrfds, nefds; /* args for the next select */
- FD_ZERO(&nrfds);
- FD_ZERO(&nefds);
+ int ms = -1; /* poll2 timeout, uninitialized */
+ struct pollfd *new_fds = NULL;
+ int new_nfds = 0;
ast_mutex_lock(&parking_lock);
pl = NULL;
@@ -2314,25 +2313,29 @@ static void *do_parking_thread(void *ignore)
ast_indicate(chan, AST_CONTROL_UNHOLD);
/* Get chan, exten from derived kludge */
if (pu->peername[0]) {
- char *peername = ast_strdupa(pu->peername);
- char *cp = strrchr(peername, '-');
- if (cp)
- *cp = 0;
- con = ast_context_find(parking_con_dial);
- if (!con) {
- con = ast_context_create(NULL, parking_con_dial, registrar);
- if (!con)
- ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
+ /* Don't use ast_strdupa() inside an infinite loop */
+ char *dash, *peername = ast_strdup(pu->peername);
+ if (!peername) {
+ /* Skip for the time being. */
+ pl = pu;
+ pu = pu->next;
+ continue;
+ }
+ if ((dash = strrchr(peername, '-'))) {
+ *dash = '\0';
}
- if (con) {
+ if (!(con = ast_context_find_or_create(NULL, parking_con_dial, registrar))) {
+ ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
+ } else {
char returnexten[AST_MAX_EXTENSION];
struct ast_datastore *features_datastore;
struct ast_dial_features *dialfeatures = NULL;
ast_channel_lock(chan);
- if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
+ if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL))) {
dialfeatures = features_datastore->data;
+ }
ast_channel_unlock(chan);
@@ -2341,7 +2344,7 @@ static void *do_parking_thread(void *ignore)
}
if (dialfeatures) {
- char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
+ char buf[MAX_DIAL_FEATURE_OPTIONS] = "";
snprintf(returnexten, sizeof(returnexten), "%s|30|%s", peername, callback_dialoptions(&(dialfeatures->features_callee), &(dialfeatures->features_caller), buf, sizeof(buf)));
} else { /* Existing default */
ast_log(LOG_WARNING, "Dialfeatures not found on %s, using default!\n", chan->name);
@@ -2351,6 +2354,7 @@ static void *do_parking_thread(void *ignore)
ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free_ptr, registrar);
}
set_c_e_p(chan, parking_con_dial, peername, 1);
+ ast_free(peername);
} else {
/* They've been waiting too long, send them back to where they came. Theoretically they
should have their original extensions and such, but we copy to be on the safe side */
@@ -2359,78 +2363,107 @@ static void *do_parking_thread(void *ignore)
post_manager_event("ParkedCallTimeOut", pu->parkingexten, chan);
- if (option_verbose > 1)
+ if (option_verbose > 1) {
ast_verbose(VERBOSE_PREFIX_2 "Timeout for %s parked on %d. Returning to %s,%s,%d\n", chan->name, pu->parkingnum, chan->context, chan->exten, chan->priority);
+ }
/* Start up the PBX, or hang them up */
if (ast_pbx_start(chan)) {
ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
ast_hangup(chan);
}
/* And take them out of the parking lot */
- if (pl)
+ if (pl) {
pl->next = pu->next;
- else
+ } else {
parkinglot = pu->next;
+ }
pt = pu;
pu = pu->next;
con = ast_context_find(parking_con);
if (con) {
- if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
+ if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL)) {
ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
- else
+ } else {
notify_metermaids(pt->parkingexten, parking_con);
- } else
+ }
+ } else {
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+ }
free(pt);
} else { /* still within parking time, process descriptors */
for (x = 0; x < AST_MAX_FDS; x++) {
struct ast_frame *f;
+ int y;
- if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
+ if (chan->fds[x] == -1) {
continue; /* nothing on this descriptor */
+ }
+
+ for (y = 0; y < nfds; y++) {
+ if (fds[y].fd == chan->fds[x]) {
+ /* Found poll record! */
+ break;
+ }
+ }
+ if (y == nfds) {
+ /* Not found */
+ continue;
+ }
- if (FD_ISSET(chan->fds[x], &efds))
+ if (!(fds[y].revents & (POLLIN | POLLERR))) {
+ /* Next x */
+ continue;
+ }
+
+ if (fds[y].revents & POLLERR) {
ast_set_flag(chan, AST_FLAG_EXCEPTION);
- else
+ } else {
ast_clear_flag(chan, AST_FLAG_EXCEPTION);
+ }
chan->fdno = x;
/* See if they need servicing */
f = ast_read(chan);
if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
- if (f)
+ if (f) {
ast_frfree(f);
+ }
post_manager_event("ParkedCallGiveUp", pu->parkingexten, chan);
/* There's a problem, hang them up*/
- if (option_verbose > 1)
+ if (option_verbose > 1) {
ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
- ast_hangup(chan);
+ }
/* And take them out of the parking lot */
- if (pl)
+ if (pl) {
pl->next = pu->next;
- else
+ } else {
parkinglot = pu->next;
+ }
pt = pu;
pu = pu->next;
+
+ ast_hangup(chan);
con = ast_context_find(parking_con);
if (con) {
- if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
+ if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL)) {
ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
- else {
+ } else {
notify_metermaids(pt->parkingexten, parking_con);
}
- } else
+ } else {
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+ }
free(pt);
break;
} else {
/*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
ast_frfree(f);
if (pu->moh_trys < 3 && !chan->generatordata) {
- if (option_debug)
+ if (option_debug) {
ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
- ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
+ }
+ ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
S_OR(parkmohclass, NULL),
!ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
pu->moh_trys++;
@@ -2440,30 +2473,39 @@ static void *do_parking_thread(void *ignore)
} /* end for */
if (x >= AST_MAX_FDS) {
-std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
+std: for (x = 0; x < AST_MAX_FDS; x++) { /* mark fds for next round */
if (chan->fds[x] > -1) {
- FD_SET(chan->fds[x], &nrfds);
- FD_SET(chan->fds[x], &nefds);
- if (chan->fds[x] > max)
- max = chan->fds[x];
+ void *tmp = ast_realloc(new_fds, (new_nfds + 1) * sizeof(*new_fds));
+ if (!tmp) {
+ continue;
+ }
+ new_fds = tmp;
+ new_fds[new_nfds].fd = chan->fds[x];
+ new_fds[new_nfds].events = POLLIN | POLLERR;
+ new_fds[new_nfds].revents = 0;
+ new_nfds++;
}
}
/* Keep track of our shortest wait */
- if (tms < ms || ms < 0)
+ if (tms < ms || ms < 0) {
ms = tms;
+ }
pl = pu;
pu = pu->next;
}
}
} /* end while */
ast_mutex_unlock(&parking_lock);
- rfds = nrfds;
- efds = nefds;
- {
- struct timeval tv = ast_samp2tv(ms, 1000);
- /* Wait for something to happen */
- ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
- }
+ ast_free(fds);
+ fds = new_fds;
+ nfds = new_nfds;
+ new_fds = NULL;
+ new_nfds = 0;
+
+ tv = ast_samp2tv(ms, 1000);
+ /* Wait for something to happen */
+ ast_poll2(fds, nfds, (ms > -1) ? &tv : NULL);
+
pthread_testcancel();
}
return NULL; /* Never reached */
diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index 271779461..f67fa5a1c 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -250,10 +250,17 @@ static int ast_moh_files_next(struct ast_channel *chan)
state->samples = 0;
}
- if (!ast_openstream_full(chan, state->class->filearray[state->pos], chan->language, 1)) {
+ for (tries = 0; tries < state->class->total_files; ++tries) {
+ if (ast_openstream_full(chan, state->class->filearray[state->pos], chan->language, 1)) {
+ break;
+ }
+
ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", state->class->filearray[state->pos], strerror(errno));
state->pos++;
state->pos %= state->class->total_files;
+ }
+
+ if (tries == state->class->total_files) {
return -1;
}