aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authorbbryant <bbryant@f38db490-d61c-443f-a65b-d21fe96a405b>2010-09-09 18:50:13 +0000
committerbbryant <bbryant@f38db490-d61c-443f-a65b-d21fe96a405b>2010-09-09 18:50:13 +0000
commit12ad49e444d6108b7312a46b389090d51b670a7f (patch)
treefe20338149990fed28e3936bbbd7162e69d1f938 /main
parentf8d0dcac122feafe9ebd0aba502263f829c77667 (diff)
Fixes an issue with dialplan pattern matching where the specificity for pattern ranges and pattern special characters was inconsistent.
(closes issue #16903) Reported by: Nick_Lewis Patches: pbx.c-specificity.patch uploaded by Nick Lewis (license 657) Tested by: Nick_Lewis git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.2@285710 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r--main/asterisk.c44
-rw-r--r--main/cdr.c39
-rw-r--r--main/channel.c14
-rw-r--r--main/features.c97
-rw-r--r--main/manager.c30
-rw-r--r--main/pbx.c45
-rw-r--r--main/poll.c196
-rw-r--r--main/rtp.c7
-rw-r--r--main/sched.c2
9 files changed, 286 insertions, 188 deletions
diff --git a/main/asterisk.c b/main/asterisk.c
index c8bed4a53..270668546 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 1999 - 2008, Digium, Inc.
+ * Copyright (C) 1999 - 2010, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@@ -269,6 +269,8 @@ static char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
static char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
static char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
+extern unsigned int ast_FD_SETSIZE;
+
static char *_argv[256];
static int shuttingdown;
static int restartnow;
@@ -3145,6 +3147,7 @@ int main(int argc, char *argv[])
char *buf;
const char *runuser = NULL, *rungroup = NULL;
char *remotesock = NULL;
+ struct rlimit l;
/* Remember original args for restart */
if (argc > ARRAY_LEN(_argv) - 1) {
@@ -3320,7 +3323,6 @@ int main(int argc, char *argv[])
}
if (ast_opt_dump_core) {
- struct rlimit l;
memset(&l, 0, sizeof(l));
l.rlim_cur = RLIM_INFINITY;
l.rlim_max = RLIM_INFINITY;
@@ -3329,6 +3331,44 @@ int main(int argc, char *argv[])
}
}
+ if (getrlimit(RLIMIT_NOFILE, &l)) {
+ ast_log(LOG_WARNING, "Unable to check file descriptor limit: %s\n", strerror(errno));
+ }
+
+#if !defined(CONFIGURE_RAN_AS_ROOT)
+ /* Check if select(2) will run with more file descriptors */
+ do {
+ int fd, fd2;
+ ast_fdset readers;
+ struct timeval tv = { 0, };
+
+ if (l.rlim_cur <= FD_SETSIZE) {
+ /* The limit of select()able FDs is irrelevant, because we'll never
+ * open one that high. */
+ break;
+ }
+
+ if (!(fd = open("/dev/null", O_RDONLY))) {
+ ast_log(LOG_ERROR, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
+ break; /* XXX Should we exit() here? XXX */
+ }
+
+ fd2 = (l.rlim_cur > sizeof(readers) * 8 ? sizeof(readers) * 8 : l.rlim_cur) - 1;
+ if (dup2(fd, fd2)) {
+ ast_log(LOG_WARNING, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
+ break;
+ }
+
+ FD_ZERO(&readers);
+ FD_SET(fd2, &readers);
+ if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
+ ast_log(LOG_WARNING, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
+ }
+ } while (0);
+#elif defined(HAVE_VARIABLE_FDSET)
+ ast_FD_SETSIZE = l.rlim_cur;
+#endif /* !defined(CONFIGURE_RAN_AS_ROOT) */
+
if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
rungroup = ast_config_AST_RUN_GROUP;
if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
diff --git a/main/cdr.c b/main/cdr.c
index 24a12a5e6..a7a096a35 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -78,18 +78,26 @@ static struct sched_context *sched;
static int cdr_sched = -1;
static pthread_t cdr_thread = AST_PTHREADT_NULL;
-#define BATCH_SIZE_DEFAULT 100
-#define BATCH_TIME_DEFAULT 300
-#define BATCH_SCHEDULER_ONLY_DEFAULT 0
-#define BATCH_SAFE_SHUTDOWN_DEFAULT 1
+static int enabled;
+static const int ENABLED_DEFAULT = 1;
-static int enabled; /*! Is the CDR subsystem enabled ? */
-static int unanswered;
static int batchmode;
+static const int BATCHMODE_DEFAULT = 0;
+
+static int unanswered;
+static const int UNANSWERED_DEFAULT = 0;
+
static int batchsize;
+static const int BATCH_SIZE_DEFAULT = 100;
+
static int batchtime;
+static const int BATCH_TIME_DEFAULT = 300;
+
static int batchscheduleronly;
+static const int BATCH_SCHEDULER_ONLY_DEFAULT = 0;
+
static int batchsafeshutdown;
+static const int BATCH_SAFE_SHUTDOWN_DEFAULT = 1;
AST_MUTEX_DEFINE_STATIC(cdr_batch_lock);
@@ -1409,22 +1417,27 @@ static int do_reload(int reload)
int res=0;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
- if ((config = ast_config_load2("cdr.conf", "cdr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
- return 0;
- if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEUNCHANGED || config == CONFIG_STATUS_FILEINVALID) {
+ if ((config = ast_config_load2("cdr.conf", "cdr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
return 0;
}
ast_mutex_lock(&cdr_batch_lock);
+ was_enabled = enabled;
+ was_batchmode = batchmode;
+
batchsize = BATCH_SIZE_DEFAULT;
batchtime = BATCH_TIME_DEFAULT;
batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT;
batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT;
- was_enabled = enabled;
- was_batchmode = batchmode;
- enabled = 1;
- batchmode = 0;
+ enabled = ENABLED_DEFAULT;
+ batchmode = BATCHMODE_DEFAULT;
+ unanswered = UNANSWERED_DEFAULT;
+
+ if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
+ ast_mutex_unlock(&cdr_batch_lock);
+ return 0;
+ }
/* don't run the next scheduled CDR posting while reloading */
AST_SCHED_DEL(sched, cdr_sched);
diff --git a/main/channel.c b/main/channel.c
index 23e4529e3..3a4ba57a3 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -4613,6 +4613,7 @@ int ast_do_masquerade(struct ast_channel *original)
void *t_pvt;
struct ast_callerid tmpcid;
struct ast_channel *clonechan = original->masq;
+ struct ast_channel *bridged;
struct ast_cdr *cdr;
int rformat = original->readformat;
int wformat = original->writeformat;
@@ -4877,6 +4878,15 @@ int ast_do_masquerade(struct ast_channel *original)
if (ast_test_flag(original, AST_FLAG_BLOCKING))
pthread_kill(original->blocker, SIGURG);
ast_debug(1, "Done Masquerading %s (%d)\n", original->name, original->_state);
+
+ if ((bridged = ast_bridged_channel(original))) {
+ ast_channel_lock(bridged);
+ ast_indicate(bridged, AST_CONTROL_SRCCHANGE);
+ ast_channel_unlock(bridged);
+ }
+
+ ast_indicate(original, AST_CONTROL_SRCCHANGE);
+
return 0;
}
@@ -5336,8 +5346,8 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
manager_bridge_event(1, 1, c0, c1);
/* Before we enter in and bridge these two together tell them both the source of audio has changed */
- ast_indicate(c0, AST_CONTROL_SRCUPDATE);
- ast_indicate(c1, AST_CONTROL_SRCUPDATE);
+ ast_indicate(c0, AST_CONTROL_SRCCHANGE);
+ ast_indicate(c1, AST_CONTROL_SRCCHANGE);
for (/* ever */;;) {
struct timeval now = { 0, };
diff --git a/main/features.c b/main/features.c
index d2f989835..8ebd44bbf 100644
--- a/main/features.c
+++ b/main/features.c
@@ -309,7 +309,7 @@ static void *dial_features_duplicate(void *data)
static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
static void parkinglot_unref(struct ast_parkinglot *parkinglot);
static void parkinglot_destroy(void *obj);
-int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *fs, int *max);
+int manage_parkinglot(struct ast_parkinglot *curlot, struct pollfd **pfds, int *nfds, int *fs);
struct ast_parkinglot *find_parkinglot(const char *name);
@@ -3066,9 +3066,10 @@ static char *callback_dialoptions(struct ast_flags *features_callee, struct ast_
}
/*! \brief Run management on parkinglots, called once per parkinglot */
-int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *ms, int *max)
+int manage_parkinglot(struct ast_parkinglot *curlot, struct pollfd **pfds, int *nfds, int *ms)
{
-
+ struct pollfd *new_fds = NULL;
+ int new_nfds = 0;
struct parkeduser *pu;
int res = 0;
char parkingslot[AST_MAX_EXTENSION];
@@ -3091,16 +3092,18 @@ int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds,
/* Get chan, exten from derived kludge */
if (pu->peername[0]) {
char *peername = ast_strdupa(pu->peername);
- char *cp = strrchr(peername, '-');
+ char *dash = strrchr(peername, '-');
char peername_flat[AST_MAX_EXTENSION]; /* using something like DAHDI/52 for an extension name is NOT a good idea */
int i;
- if (cp)
- *cp = 0;
- ast_copy_string(peername_flat,peername,sizeof(peername_flat));
- for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
- if (peername_flat[i] == '/')
- peername_flat[i]= '0';
+ if (dash) {
+ *dash = '\0';
+ }
+ ast_copy_string(peername_flat, peername, sizeof(peername_flat));
+ for (i = 0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
+ if (peername_flat[i] == '/') {
+ peername_flat[i] = '0';
+ }
}
con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con_dial, registrar);
if (!con) {
@@ -3172,14 +3175,33 @@ int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds,
} 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(pu->chan->fds[x], efds)))
+ if (chan->fds[x] == -1) {
+ continue; /* nothing on this descriptor */
+ }
+
+ for (y = 0; y < *nfds; y++) {
+ if ((*pfds[y]).fd == chan->fds[x]) {
+ /* Found poll record! */
+ break;
+ }
+ }
+ if (y == *nfds) {
+ /* Not found */
continue;
-
- if (FD_ISSET(chan->fds[x], efds))
+ }
+
+ if (!((*pfds[y]).revents & (POLLIN | POLLERR))) {
+ /* Next x */
+ continue;
+ }
+
+ if ((*pfds[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 */
@@ -3219,22 +3241,32 @@ int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds,
}
} /* 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;
+ }
}
}
}
AST_LIST_TRAVERSE_SAFE_END;
AST_LIST_UNLOCK(&curlot->parkings);
+
+ ast_free(*pfds);
+ *pfds = new_fds;
+ *nfds = new_nfds;
return res;
}
@@ -3248,35 +3280,26 @@ std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
*/
static void *do_parking_thread(void *ignore)
{
- fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
- fd_set nrfds, nefds; /* args for the next select */
- FD_ZERO(&rfds);
- FD_ZERO(&efds);
+ struct pollfd *pfds = NULL;
+ int nfds = 0;
for (;;) {
- int res = 0;
- int ms = -1; /* select timeout, uninitialized */
- int max = -1; /* max fd, none there yet */
struct ao2_iterator iter;
struct ast_parkinglot *curlot;
- FD_ZERO(&nrfds);
- FD_ZERO(&nefds);
+ int ms = -1; /* poll2 timeout, uninitialized */
iter = ao2_iterator_init(parkinglots, 0);
while ((curlot = ao2_iterator_next(&iter))) {
- res = manage_parkinglot(curlot, &rfds, &efds, &nrfds, &nefds, &ms, &max);
+ manage_parkinglot(curlot, &pfds, &nfds, &ms);
ao2_ref(curlot, -1);
}
+ ao2_iterator_destroy(&iter);
- rfds = nrfds;
- efds = nefds;
- {
- struct timeval wait = ast_samp2tv(ms, 1000);
- /* Wait for something to happen */
- ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &wait : NULL);
- }
+ /* Wait for something to happen */
+ ast_poll(pfds, nfds, ms);
pthread_testcancel();
}
+ /* If this WERE reached, we'd need to free(pfds) */
return NULL; /* Never reached */
}
diff --git a/main/manager.c b/main/manager.c
index d13672653..17b4dc37c 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -120,11 +120,19 @@ struct eventqent {
static AST_RWLIST_HEAD_STATIC(all_events, eventqent);
-static int displayconnects = 1;
+static const int DEFAULT_ENABLED = 0; /*!< Default setting for manager to be enabled */
+static const int DEFAULT_WEBENABLED = 0; /*!< Default setting for the web interface to be enabled */
+static const int DEFAULT_BLOCKSOCKETS = 0; /*!< Default setting for block-sockets */
+static const int DEFAULT_DISPLAYCONNECTS = 1; /*!< Default setting for displaying manager connections */
+static const int DEFAULT_TIMESTAMPEVENTS = 0; /*!< Default setting for timestampevents */
+static const int DEFAULT_HTTPTIMEOUT = 60; /*!< Default manager http timeout */
+static const int DEFAULT_BROKENEVENTSACTION = 0; /*!< Default setting for brokeneventsaction */
+
+static int displayconnects;
static int allowmultiplelogin = 1;
static int timestampevents;
-static int httptimeout = 60;
-static int broken_events_action = 0;
+static int httptimeout;
+static int broken_events_action;
static int manager_enabled = 0;
static int webmanager_enabled = 0;
@@ -4116,16 +4124,14 @@ static int __init_manager(int reload)
struct ast_config *ucfg = NULL, *cfg = NULL;
const char *val;
char *cat = NULL;
- int newhttptimeout = 60;
+ int newhttptimeout = DEFAULT_HTTPTIMEOUT;
int have_sslbindaddr = 0;
struct hostent *hp;
struct ast_hostent ahp;
struct ast_manager_user *user = NULL;
struct ast_variable *var;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
-
- manager_enabled = 0;
-
+
if (!registered) {
/* Register default actions */
ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
@@ -4170,8 +4176,14 @@ static int __init_manager(int reload)
if ((cfg = ast_config_load2("manager.conf", "manager", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
return 0;
- displayconnects = 1;
- broken_events_action = 0;
+ manager_enabled = DEFAULT_ENABLED;
+ webmanager_enabled = DEFAULT_WEBENABLED;
+ displayconnects = DEFAULT_DISPLAYCONNECTS;
+ broken_events_action = DEFAULT_BROKENEVENTSACTION;
+ block_sockets = DEFAULT_BLOCKSOCKETS;
+ timestampevents = DEFAULT_TIMESTAMPEVENTS;
+ httptimeout = DEFAULT_HTTPTIMEOUT;
+
if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf, or configuration is invalid. Asterisk management interface (AMI) disabled.\n");
return 0;
diff --git a/main/pbx.c b/main/pbx.c
index 505abf382..4a945e06a 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -1119,7 +1119,11 @@ static struct pbx_builtin {
static struct ast_context *contexts;
static struct ast_hashtab *contexts_table = NULL;
-AST_RWLOCK_DEFINE_STATIC(conlock); /*!< Lock for the ast_context list */
+/*!\brief Lock for the ast_context list
+ * This lock MUST be recursive, or a deadlock on reload may result. See
+ * https://issues.asterisk.org/view.php?id=17643
+ */
+AST_MUTEX_DEFINE_STATIC(conlock);
static AST_RWLIST_HEAD_STATIC(apps, ast_app);
@@ -1845,15 +1849,15 @@ static struct match_char *add_pattern_node(struct ast_context *con, struct match
pattern matcher. */
m->is_pattern = is_pattern;
if (specificity == 1 && is_pattern && pattern[0] == 'N')
- m->specificity = 0x0802;
+ m->specificity = 0x0832;
else if (specificity == 1 && is_pattern && pattern[0] == 'Z')
- m->specificity = 0x0901;
+ m->specificity = 0x0931;
else if (specificity == 1 && is_pattern && pattern[0] == 'X')
- m->specificity = 0x0a00;
+ m->specificity = 0x0a30;
else if (specificity == 1 && is_pattern && pattern[0] == '.')
- m->specificity = 0x10000;
+ m->specificity = 0x18000;
else if (specificity == 1 && is_pattern && pattern[0] == '!')
- m->specificity = 0x20000;
+ m->specificity = 0x28000;
else
m->specificity = specificity;
@@ -2123,10 +2127,10 @@ static int ext_cmp1(const char **p, unsigned char *bitwise)
return 0x0900 | '1';
case '.': /* wildcard */
- return 0x10000;
+ return 0x18000;
case '!': /* earlymatch */
- return 0x20000; /* less specific than NULL */
+ return 0x28000; /* less specific than NULL */
case '\0': /* empty string */
*p = NULL;
@@ -6655,7 +6659,6 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_
*/
struct timeval begintime, writelocktime, endlocktime, enddeltime;
- int wrlock_ver;
begintime = ast_tvnow();
ast_rdlock_contexts();
@@ -6664,15 +6667,6 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_
context_merge(extcontexts, exttable, tmp, registrar);
}
ast_hashtab_end_traversal(iter);
- wrlock_ver = ast_wrlock_contexts_version();
-
- ast_unlock_contexts(); /* this feels real retarded, but you must do
- what you must do If this isn't done, the following
- wrlock is a guraranteed deadlock */
- ast_wrlock_contexts();
- if (ast_wrlock_contexts_version() > wrlock_ver+1) {
- ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n");
- }
AST_RWLIST_WRLOCK(&hints);
writelocktime = ast_tvnow();
@@ -9344,32 +9338,23 @@ int load_pbx(void)
return 0;
}
-static int conlock_wrlock_version = 0;
-
-int ast_wrlock_contexts_version(void)
-{
- return conlock_wrlock_version;
-}
/*
* Lock context list functions ...
*/
int ast_wrlock_contexts()
{
- int res = ast_rwlock_wrlock(&conlock);
- if (!res)
- ast_atomic_fetchadd_int(&conlock_wrlock_version, 1);
- return res;
+ return ast_mutex_lock(&conlock);
}
int ast_rdlock_contexts()
{
- return ast_rwlock_rdlock(&conlock);
+ return ast_mutex_lock(&conlock);
}
int ast_unlock_contexts()
{
- return ast_rwlock_unlock(&conlock);
+ return ast_mutex_unlock(&conlock);
}
/*
diff --git a/main/poll.c b/main/poll.c
index e52c11709..798979267 100644
--- a/main/poll.c
+++ b/main/poll.c
@@ -10,9 +10,9 @@
struct pollfd
{
- int fd;
- short events;
- short revents;
+ int fd;
+ short events;
+ short revents;
}
int poll (struct pollfd *pArray, unsigned long n_fds, int timeout)
@@ -73,50 +73,40 @@
#include "asterisk.h"
-#include <unistd.h> /* standard Unix definitions */
-#include <sys/types.h> /* system types */
-#include <sys/time.h> /* time definitions */
-#include <assert.h> /* assertion macros */
-#include <string.h> /* string functions */
+#include <unistd.h> /* standard Unix definitions */
+#include <sys/types.h> /* system types */
+#include <sys/time.h> /* time definitions */
+#include <assert.h> /* assertion macros */
+#include <string.h> /* string functions */
+#include <errno.h>
#include "asterisk/utils.h" /* this package */
#include "asterisk/poll-compat.h" /* this package */
-#ifdef AST_POLL_COMPAT
+unsigned int ast_FD_SETSIZE = FD_SETSIZE;
/*---------------------------------------------------------------------------*\
- Private Functions
+ Private Functions
\*---------------------------------------------------------------------------*/
-static int map_poll_spec
-#if __STDC__ > 0
- (struct pollfd *pArray,
- unsigned long n_fds,
- fd_set *pReadSet,
- fd_set *pWriteSet,
- fd_set *pExceptSet)
-#else
- (pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
- struct pollfd *pArray;
- unsigned long n_fds;
- fd_set *pReadSet;
- fd_set *pWriteSet;
- fd_set *pExceptSet;
-#endif
+#if defined(AST_POLL_COMPAT)
+static int map_poll_spec(struct pollfd *pArray, unsigned long n_fds,
+ ast_fdset *pReadSet, ast_fdset *pWriteSet, ast_fdset *pExceptSet)
{
- register unsigned long i; /* loop control */
- register struct pollfd *pCur; /* current array element */
- register int max_fd = -1; /* return value */
+ register unsigned long i; /* loop control */
+ register struct pollfd *pCur; /* current array element */
+ register int max_fd = -1; /* return value */
- /*!\note
+ /*
* Map the poll() structures into the file descriptor sets required
* by select().
*/
for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) {
/* Skip any bad FDs in the array. */
- if (pCur->fd < 0)
+ if (pCur->fd < 0) {
continue;
+ }
if (pCur->events & POLLIN) {
/* "Input Ready" notification desired. */
@@ -141,34 +131,28 @@ static int map_poll_spec
return max_fd;
}
-
-static struct timeval *map_timeout
-#if __STDC__ > 0
- (int poll_timeout, struct timeval *pSelTimeout)
-#else
- (poll_timeout, pSelTimeout)
- int poll_timeout;
- struct timeval *pSelTimeout;
-#endif
+
+#ifdef AST_POLL_COMPAT
+static struct timeval *map_timeout(int poll_timeout, struct timeval *pSelTimeout)
{
struct timeval *pResult;
- /*!\note
- * Map the poll() timeout value into a select() timeout. The possible
- * values of the poll() timeout value, and their meanings, are:
- *
- * VALUE MEANING
- *
- * -1 wait indefinitely (until signal occurs)
- * 0 return immediately, don't block
- * >0 wait specified number of milliseconds
- *
- * select() uses a "struct timeval", which specifies the timeout in
- * seconds and microseconds, so the milliseconds value has to be mapped
- * accordingly.
- */
+ /*
+ Map the poll() timeout value into a select() timeout. The possible
+ values of the poll() timeout value, and their meanings, are:
+
+ VALUE MEANING
- assert(pSelTimeout != (struct timeval *) NULL);
+ -1 wait indefinitely (until signal occurs)
+ 0 return immediately, don't block
+ >0 wait specified number of milliseconds
+
+ select() uses a "struct timeval", which specifies the timeout in
+ seconds and microseconds, so the milliseconds value has to be mapped
+ accordingly.
+ */
+
+ assert(pSelTimeout != NULL);
switch (poll_timeout) {
case -1:
@@ -199,25 +183,13 @@ static struct timeval *map_timeout
return pResult;
}
+#endif /* AST_POLL_COMPAT */
-static void map_select_results
-#if __STDC__ > 0
- (struct pollfd *pArray,
- unsigned long n_fds,
- fd_set *pReadSet,
- fd_set *pWriteSet,
- fd_set *pExceptSet)
-#else
- (pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
- struct pollfd *pArray;
- unsigned long n_fds;
- fd_set *pReadSet;
- fd_set *pWriteSet;
- fd_set *pExceptSet;
-#endif
+static void map_select_results(struct pollfd *pArray, unsigned long n_fds,
+ ast_fdset *pReadSet, ast_fdset *pWriteSet, ast_fdset *pExceptSet)
{
- register unsigned long i; /* loop control */
- register struct pollfd *pCur; /* current array element */
+ register unsigned long i; /* loop control */
+ register struct pollfd *pCur; /* current array element */
for (i = 0, pCur = pArray; i < n_fds; i++, pCur++) {
/* Skip any bad FDs in the array. */
@@ -227,59 +199,105 @@ static void map_select_results
}
/* Exception events take priority over input events. */
-
pCur->revents = 0;
- if (FD_ISSET (pCur->fd, pExceptSet)) {
+ if (FD_ISSET(pCur->fd, (fd_set *) pExceptSet)) {
pCur->revents |= POLLPRI;
- } else if (FD_ISSET (pCur->fd, pReadSet)) {
+ } else if (FD_ISSET(pCur->fd, (fd_set *) pReadSet)) {
pCur->revents |= POLLIN;
}
- if (FD_ISSET (pCur->fd, pWriteSet)) {
+ if (FD_ISSET(pCur->fd, (fd_set *) pWriteSet)) {
pCur->revents |= POLLOUT;
}
}
return;
}
+#endif /* defined(AST_POLL_COMPAT) || !defined(HAVE_PPOLL) */
/*---------------------------------------------------------------------------*\
- Public Functions
+ Public Functions
\*---------------------------------------------------------------------------*/
-
+#ifdef AST_POLL_COMPAT
int ast_internal_poll(struct pollfd *pArray, unsigned long n_fds, int timeout)
{
- fd_set read_descs; /* input file descs */
- fd_set write_descs; /* output file descs */
- fd_set except_descs; /* exception descs */
+ ast_fdset read_descs; /* input file descs */
+ ast_fdset write_descs; /* output file descs */
+ ast_fdset except_descs; /* exception descs */
struct timeval stime; /* select() timeout value */
- int ready_descriptors; /* function result */
- int max_fd = 0; /* maximum fd value */
+ int ready_descriptors; /* function result */
+ int max_fd = 0; /* maximum fd value */
struct timeval *pTimeout; /* actually passed */
+ int save_errno;
- FD_ZERO (&read_descs);
- FD_ZERO (&write_descs);
- FD_ZERO (&except_descs);
+ FD_ZERO(&read_descs);
+ FD_ZERO(&write_descs);
+ FD_ZERO(&except_descs);
/* Map the poll() file descriptor list in the select() data structures. */
if (pArray) {
- max_fd = map_poll_spec (pArray, n_fds,
+ max_fd = map_poll_spec (pArray, n_fds,
&read_descs, &write_descs, &except_descs);
}
/* Map the poll() timeout value in the select() timeout structure. */
- pTimeout = map_timeout(timeout, &stime);
+
+ pTimeout = map_timeout (timeout, &stime);
/* Make the select() call. */
- ready_descriptors = select(max_fd + 1, &read_descs, &write_descs,
+
+ ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs,
&except_descs, pTimeout);
+ save_errno = errno;
+
+ if (ready_descriptors >= 0) {
+ map_select_results (pArray, n_fds,
+ &read_descs, &write_descs, &except_descs);
+ }
+
+ errno = save_errno;
+ return ready_descriptors;
+}
+#endif /* AST_POLL_COMPAT */
+
+int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv)
+{
+#if !defined(AST_POLL_COMPAT)
+ struct timeval start = ast_tvnow();
+#if defined(HAVE_PPOLL)
+ struct timespec ts = { tv ? tv->tv_sec : 0, tv ? tv->tv_usec * 1000 : 0 };
+ int res = ppoll(pArray, n_fds, tv ? &ts : NULL, NULL);
+#else
+ int res = poll(pArray, n_fds, tv ? tv->tv_sec * 1000 + tv->tv_usec / 1000 : -1);
+#endif
+ struct timeval after = ast_tvnow();
+ if (res > 0 && tv && ast_tvdiff_ms(ast_tvadd(*tv, start), after) > 0) {
+ *tv = ast_tvsub(*tv, ast_tvsub(after, start));
+ } else if (res > 0 && tv) {
+ *tv = ast_tv(0, 0);
+ }
+ return res;
+#else
+ ast_fdset read_descs, write_descs, except_descs;
+ int ready_descriptors, max_fd = 0;
+
+ FD_ZERO(&read_descs);
+ FD_ZERO(&write_descs);
+ FD_ZERO(&except_descs);
+
+ if (pArray) {
+ max_fd = map_poll_spec(pArray, n_fds, &read_descs, &write_descs, &except_descs);
+ }
+
+ ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs, &except_descs, tv);
if (ready_descriptors >= 0) {
map_select_results(pArray, n_fds, &read_descs, &write_descs, &except_descs);
}
return ready_descriptors;
+#endif
}
-#endif /* AST_POLL_COMPAT */
+
diff --git a/main/rtp.c b/main/rtp.c
index 424912202..2ed677769 100644
--- a/main/rtp.c
+++ b/main/rtp.c
@@ -656,8 +656,7 @@ int ast_stun_request(int s, struct sockaddr_in *dst,
for (retry = 0; retry < 3; retry++) { /* XXX make retries configurable */
/* send request, possibly wait for reply */
unsigned char reply_buf[1024];
- fd_set rfds;
- struct timeval to = { 3, 0 }; /* timeout, make it configurable */
+ struct pollfd pfds = { .fd = s, .events = POLLIN, };
struct sockaddr_in src;
socklen_t srclen;
@@ -669,9 +668,7 @@ int ast_stun_request(int s, struct sockaddr_in *dst,
}
if (answer == NULL)
break;
- FD_ZERO(&rfds);
- FD_SET(s, &rfds);
- res = ast_select(s + 1, &rfds, NULL, NULL, &to);
+ res = ast_poll(&pfds, 1, 3000);
if (res <= 0) /* timeout or error */
continue;
memset(&src, '\0', sizeof(src));
diff --git a/main/sched.c b/main/sched.c
index 8699cfbab..0aebb43f1 100644
--- a/main/sched.c
+++ b/main/sched.c
@@ -589,13 +589,13 @@ int ast_sched_runq(struct sched_context *con)
ast_mutex_lock(&con->lock);
+ when = ast_tvadd(ast_tvnow(), ast_tv(0, 1000));
for (numevents = 0; (current = ast_heap_peek(con->sched_heap, 1)); numevents++) {
/* schedule all events which are going to expire within 1ms.
* We only care about millisecond accuracy anyway, so this will
* help us get more than one event at one time if they are very
* close together.
*/
- when = ast_tvadd(ast_tvnow(), ast_tv(0, 1000));
if (ast_tvcmp(current->when, when) != -1) {
break;
}