summaryrefslogtreecommitdiff
path: root/main/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/channel.c')
-rw-r--r--main/channel.c336
1 files changed, 20 insertions, 316 deletions
diff --git a/main/channel.c b/main/channel.c
index 15c7fa406..31f363938 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -78,21 +78,12 @@
/*** DOCUMENTATION
***/
-#ifdef HAVE_EPOLL
-#include <sys/epoll.h>
-#endif
-
#if defined(KEEP_TILL_CHANNEL_PARTY_NUMBER_INFO_NEEDED)
#if defined(HAVE_PRI)
#include "libpri.h"
#endif /* defined(HAVE_PRI) */
#endif /* defined(KEEP_TILL_CHANNEL_PARTY_NUMBER_INFO_NEEDED) */
-struct ast_epoll_data {
- struct ast_channel *chan;
- int which;
-};
-
/* uncomment if you have problems with 'monitoring' synchronized files */
#if 0
#define MONITOR_CONSTANT_DELAY
@@ -850,10 +841,6 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
ast_channel_internal_alertpipe_clear(tmp);
ast_channel_internal_fd_clear_all(tmp);
-#ifdef HAVE_EPOLL
- ast_channel_epfd_set(tmp, epoll_create(25));
-#endif
-
if (!(schedctx = ast_sched_context_create())) {
ast_log(LOG_WARNING, "Channel allocation failed: Unable to create schedule context\n");
/* See earlier channel creation abort comment above. */
@@ -1058,9 +1045,6 @@ struct ast_channel *__ast_dummy_channel_alloc(const char *file, int line, const
ast_channel_timingfd_set(tmp, -1);
ast_channel_internal_alertpipe_clear(tmp);
ast_channel_internal_fd_clear_all(tmp);
-#ifdef HAVE_EPOLL
- ast_channel_epfd_set(tmp, -1);
-#endif
ast_channel_hold_state_set(tmp, AST_CONTROL_UNHOLD);
@@ -2223,9 +2207,6 @@ void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
static void ast_channel_destructor(void *obj)
{
struct ast_channel *chan = obj;
-#ifdef HAVE_EPOLL
- int i;
-#endif
struct ast_var_t *vardata;
struct ast_frame *f;
struct varshead *headp;
@@ -2323,14 +2304,6 @@ static void ast_channel_destructor(void *obj)
ast_timer_close(ast_channel_timer(chan));
ast_channel_timer_set(chan, NULL);
}
-#ifdef HAVE_EPOLL
- for (i = 0; i < AST_MAX_FDS; i++) {
- if (ast_channel_internal_epfd_data(chan, i)) {
- ast_free(ast_channel_internal_epfd_data(chan, i));
- }
- }
- close(ast_channel_epfd(chan));
-#endif
while ((f = AST_LIST_REMOVE_HEAD(ast_channel_readq(chan), frame_list)))
ast_frfree(f);
@@ -2481,82 +2454,10 @@ struct ast_datastore *ast_channel_datastore_find(struct ast_channel *chan, const
/*! Set the file descriptor on the channel */
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
{
-#ifdef HAVE_EPOLL
- struct epoll_event ev;
- struct ast_epoll_data *aed = NULL;
-
- if (ast_channel_fd_isset(chan, which)) {
- epoll_ctl(ast_channel_epfd(chan), EPOLL_CTL_DEL, ast_channel_fd(chan, which), &ev);
- aed = ast_channel_internal_epfd_data(chan, which);
- }
-
- /* If this new fd is valid, add it to the epoll */
- if (fd > -1) {
- if (!aed && (!(aed = ast_calloc(1, sizeof(*aed)))))
- return;
-
- ast_channel_internal_epfd_data_set(chan, which, aed);
- aed->chan = chan;
- aed->which = which;
-
- ev.events = EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP;
- ev.data.ptr = aed;
- epoll_ctl(ast_channel_epfd(chan), EPOLL_CTL_ADD, fd, &ev);
- } else if (aed) {
- /* We don't have to keep around this epoll data structure now */
- ast_free(aed);
- ast_channel_epfd_data_set(chan, which, NULL);
- }
-#endif
ast_channel_internal_fd_set(chan, which, fd);
return;
}
-/*! Add a channel to an optimized waitfor */
-void ast_poll_channel_add(struct ast_channel *chan0, struct ast_channel *chan1)
-{
-#ifdef HAVE_EPOLL
- struct epoll_event ev;
- int i = 0;
-
- if (ast_channel_epfd(chan0) == -1)
- return;
-
- /* Iterate through the file descriptors on chan1, adding them to chan0 */
- for (i = 0; i < AST_MAX_FDS; i++) {
- if (!ast_channel_fd_isset(chan1, i)) {
- continue;
- }
- ev.events = EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP;
- ev.data.ptr = ast_channel_internal_epfd_data(chan1, i);
- epoll_ctl(ast_channel_epfd(chan0), EPOLL_CTL_ADD, ast_channel_fd(chan1, i), &ev);
- }
-
-#endif
- return;
-}
-
-/*! Delete a channel from an optimized waitfor */
-void ast_poll_channel_del(struct ast_channel *chan0, struct ast_channel *chan1)
-{
-#ifdef HAVE_EPOLL
- struct epoll_event ev;
- int i = 0;
-
- if (ast_channel_epfd(chan0) == -1)
- return;
-
- for (i = 0; i < AST_MAX_FDS; i++) {
- if (!ast_channel_fd_isset(chan1, i)) {
- continue;
- }
- epoll_ctl(ast_channel_epfd(chan0), EPOLL_CTL_DEL, ast_channel_fd(chan1, i), &ev);
- }
-
-#endif
- return;
-}
-
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
{
ast_channel_lock(chan);
@@ -3061,20 +2962,15 @@ int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
}
/*! \brief Wait for x amount of time on a file descriptor to have input. */
-#ifdef HAVE_EPOLL
-static struct ast_channel *ast_waitfor_nandfds_classic(struct ast_channel **c, int n, int *fds, int nfds,
- int *exception, int *outfd, int *ms)
-#else
struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds,
int *exception, int *outfd, int *ms)
-#endif
{
struct timeval start = { 0 , 0 };
struct pollfd *pfds = NULL;
int res;
long rms;
int x, y, max;
- int sz;
+ int sz = nfds;
struct timeval now = { 0, 0 };
struct timeval whentohangup = { 0, 0 }, diff;
struct ast_channel *winner = NULL;
@@ -3090,14 +2986,6 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
*exception = 0;
}
- if ((sz = n * AST_MAX_FDS + nfds)) {
- pfds = ast_alloca(sizeof(*pfds) * sz);
- fdmap = ast_alloca(sizeof(*fdmap) * sz);
- } else {
- /* nothing to allocate and no FDs to check */
- return NULL;
- }
-
for (x = 0; x < n; x++) {
ast_channel_lock(c[x]);
if (!ast_tvzero(*ast_channel_whentohangup(c[x]))) {
@@ -3114,8 +3002,17 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
if (ast_tvzero(whentohangup) || ast_tvcmp(diff, whentohangup) < 0)
whentohangup = diff;
}
+ sz += ast_channel_fd_count(c[x]);
ast_channel_unlock(c[x]);
}
+
+ if (!sz) {
+ return NULL;
+ }
+
+ pfds = ast_alloca(sizeof(*pfds) * sz);
+ fdmap = ast_alloca(sizeof(*fdmap) * sz);
+
/* Wait full interval */
rms = *ms;
/* INT_MAX, not LONG_MAX, because it matters on 64-bit */
@@ -3135,12 +3032,12 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
*/
max = 0;
for (x = 0; x < n; x++) {
- for (y = 0; y < AST_MAX_FDS; y++) {
+ ast_channel_lock(c[x]);
+ for (y = 0; y < ast_channel_fd_count(c[x]); y++) {
fdmap[max].fdno = y; /* fd y is linked to this pfds */
fdmap[max].chan = x; /* channel x is linked to this pfds */
max += ast_add_fd(&pfds[max], ast_channel_fd(c[x], y));
}
- ast_channel_lock(c[x]);
CHECK_BLOCKING(c[x]);
ast_channel_unlock(c[x]);
}
@@ -3234,205 +3131,6 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
return winner;
}
-#ifdef HAVE_EPOLL
-static struct ast_channel *ast_waitfor_nandfds_simple(struct ast_channel *chan, int *ms)
-{
- struct timeval start = { 0 , 0 };
- int res = 0;
- struct epoll_event ev[1];
- long diff, rms = *ms;
- struct ast_channel *winner = NULL;
- struct ast_epoll_data *aed = NULL;
-
- ast_channel_lock(chan);
- /* Figure out their timeout */
- if (!ast_tvzero(*ast_channel_whentohangup(chan))) {
- if ((diff = ast_tvdiff_ms(*ast_channel_whentohangup(chan), ast_tvnow())) < 0) {
- /* They should already be hungup! */
- ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_TIMEOUT);
- ast_channel_unlock(chan);
- return NULL;
- }
- /* If this value is smaller then the current one... make it priority */
- if (rms > diff) {
- rms = diff;
- }
- }
-
- ast_channel_unlock(chan);
-
- /* Time to make this channel block... */
- CHECK_BLOCKING(chan);
-
- if (*ms > 0) {
- start = ast_tvnow();
- }
-
- /* We don't have to add any file descriptors... they are already added, we just have to wait! */
- res = epoll_wait(ast_channel_epfd(chan), ev, 1, rms);
-
- /* Stop blocking */
- ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING);
-
- /* Simulate a timeout if we were interrupted */
- if (res < 0) {
- if (errno != EINTR) {
- *ms = -1;
- }
- return NULL;
- }
-
- /* If this channel has a timeout see if it expired */
- if (!ast_tvzero(*ast_channel_whentohangup(chan))) {
- if (ast_tvdiff_ms(ast_tvnow(), *ast_channel_whentohangup(chan)) >= 0) {
- ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_TIMEOUT);
- winner = chan;
- }
- }
-
- /* No fd ready, reset timeout and be done for now */
- if (!res) {
- *ms = 0;
- return winner;
- }
-
- /* See what events are pending */
- aed = ev[0].data.ptr;
- ast_channel_fdno_set(chan, aed->which);
- if (ev[0].events & EPOLLPRI) {
- ast_set_flag(ast_channel_flags(chan), AST_FLAG_EXCEPTION);
- } else {
- ast_clear_flag(ast_channel_flags(chan), AST_FLAG_EXCEPTION);
- }
-
- if (*ms > 0) {
- *ms -= ast_tvdiff_ms(ast_tvnow(), start);
- if (*ms < 0) {
- *ms = 0;
- }
- }
-
- return chan;
-}
-
-static struct ast_channel *ast_waitfor_nandfds_complex(struct ast_channel **c, int n, int *ms)
-{
- struct timeval start = { 0 , 0 };
- int res = 0, i;
- struct epoll_event ev[25] = { { 0, } };
- struct timeval now = { 0, 0 };
- long whentohangup = 0, diff = 0, rms = *ms;
- struct ast_channel *winner = NULL;
-
- for (i = 0; i < n; i++) {
- ast_channel_lock(c[i]);
- if (!ast_tvzero(*ast_channel_whentohangup(c[i]))) {
- if (whentohangup == 0) {
- now = ast_tvnow();
- }
- if ((diff = ast_tvdiff_ms(*ast_channel_whentohangup(c[i]), now)) < 0) {
- ast_channel_softhangup_internal_flag_add(c[i], AST_SOFTHANGUP_TIMEOUT);
- ast_channel_unlock(c[i]);
- return c[i];
- }
- if (!whentohangup || whentohangup > diff) {
- whentohangup = diff;
- }
- }
- ast_channel_unlock(c[i]);
- CHECK_BLOCKING(c[i]);
- }
-
- rms = *ms;
- if (whentohangup) {
- rms = whentohangup;
- if (*ms >= 0 && *ms < rms) {
- rms = *ms;
- }
- }
-
- if (*ms > 0) {
- start = ast_tvnow();
- }
-
- res = epoll_wait(ast_channel_epfd(c[0]), ev, 25, rms);
-
- for (i = 0; i < n; i++) {
- ast_clear_flag(ast_channel_flags(c[i]), AST_FLAG_BLOCKING);
- }
-
- if (res < 0) {
- if (errno != EINTR) {
- *ms = -1;
- }
- return NULL;
- }
-
- if (whentohangup) {
- now = ast_tvnow();
- for (i = 0; i < n; i++) {
- if (!ast_tvzero(*ast_channel_whentohangup(c[i])) && ast_tvdiff_ms(now, *ast_channel_whentohangup(c[i])) >= 0) {
- ast_channel_softhangup_internal_flag_add(c[i], AST_SOFTHANGUP_TIMEOUT);
- if (!winner) {
- winner = c[i];
- }
- }
- }
- }
-
- if (!res) {
- *ms = 0;
- return winner;
- }
-
- for (i = 0; i < res; i++) {
- struct ast_epoll_data *aed = ev[i].data.ptr;
-
- if (!ev[i].events || !aed) {
- continue;
- }
-
- winner = aed->chan;
- if (ev[i].events & EPOLLPRI) {
- ast_set_flag(ast_channel_flags(winner), AST_FLAG_EXCEPTION);
- } else {
- ast_clear_flag(ast_channel_flags(winner), AST_FLAG_EXCEPTION);
- }
- ast_channel_fdno_set(winner, aed->which);
- }
-
- if (*ms > 0) {
- *ms -= ast_tvdiff_ms(ast_tvnow(), start);
- if (*ms < 0) {
- *ms = 0;
- }
- }
-
- return winner;
-}
-
-struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds,
- int *exception, int *outfd, int *ms)
-{
- /* Clear all provided values in one place. */
- if (outfd) {
- *outfd = -99999;
- }
- if (exception) {
- *exception = 0;
- }
-
- /* If no epoll file descriptor is available resort to classic nandfds */
- if (!n || nfds || ast_channel_epfd(c[0]) == -1) {
- return ast_waitfor_nandfds_classic(c, n, fds, nfds, exception, outfd, ms);
- } else if (!nfds && n == 1) {
- return ast_waitfor_nandfds_simple(c[0], ms);
- } else {
- return ast_waitfor_nandfds_complex(c, n, ms);
- }
-}
-#endif
-
struct ast_channel *ast_waitfor_n(struct ast_channel **c, int n, int *ms)
{
return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms);
@@ -6852,6 +6550,7 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
int origstate;
unsigned int orig_disablestatecache;
unsigned int clone_disablestatecache;
+ int generator_fd;
int visible_indication;
int clone_hold_state;
int moh_is_playing;
@@ -7042,8 +6741,13 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
/* Keep the same parkinglot. */
ast_channel_parkinglot_set(original, ast_channel_parkinglot(clonechan));
- /* Copy the FD's other than the generator fd */
- for (x = 0; x < AST_MAX_FDS; x++) {
+ /* Clear all existing file descriptors but retain the generator */
+ generator_fd = ast_channel_fd(original, AST_GENERATOR_FD);
+ ast_channel_internal_fd_clear_all(original);
+ ast_channel_set_fd(original, AST_GENERATOR_FD, generator_fd);
+
+ /* Copy all file descriptors present on clonechan to original, skipping generator */
+ for (x = 0; x < ast_channel_fd_count(clonechan); x++) {
if (x != AST_GENERATOR_FD)
ast_channel_set_fd(original, x, ast_channel_fd(clonechan, x));
}