From 0e5c761c28a4ea091d760cfabc2ed3512ee2689a Mon Sep 17 00:00:00 2001 From: Terry Wilson Date: Thu, 1 Mar 2012 22:09:18 +0000 Subject: Opaquify ast_channel typedefs, fd arrays, and softhangup flag Review: https://reviewboard.asterisk.org/r/1784/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@357721 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- main/autoservice.c | 2 +- main/channel.c | 182 ++++++++++++++------------------------ main/channel_internal_api.c | 207 +++++++++++++++++++++++++++++++++++++++++--- main/cli.c | 4 +- main/dsp.c | 2 +- main/features.c | 12 +-- main/file.c | 2 +- main/pbx.c | 12 +-- 8 files changed, 276 insertions(+), 147 deletions(-) (limited to 'main') diff --git a/main/autoservice.c b/main/autoservice.c index 35a66205a..fca180f5c 100644 --- a/main/autoservice.c +++ b/main/autoservice.c @@ -277,7 +277,7 @@ int ast_autoservice_stop(struct ast_channel *chan) /* Now autoservice thread should have no references to our entry and we can safely destroy it */ - if (!chan->_softhangup) { + if (!ast_channel_softhangup_internal_flag(chan)) { res = 0; } diff --git a/main/channel.c b/main/channel.c index 387b98bea..9222a33c6 100644 --- a/main/channel.c +++ b/main/channel.c @@ -583,14 +583,14 @@ int ast_channel_trace_disable(struct ast_channel *chan) /*! \brief Checks to see if a channel is needing hang up */ int ast_check_hangup(struct ast_channel *chan) { - if (chan->_softhangup) /* yes if soft hangup flag set */ + if (ast_channel_softhangup_internal_flag(chan)) /* yes if soft hangup flag set */ return 1; if (ast_tvzero(*ast_channel_whentohangup(chan))) /* no if no hangup scheduled */ return 0; if (ast_tvdiff_ms(*ast_channel_whentohangup(chan), ast_tvnow()) > 0) /* no if hangup time has not come yet. */ return 0; ast_debug(4, "Hangup time has come: %" PRIi64 "\n", ast_tvdiff_ms(*ast_channel_whentohangup(chan), ast_tvnow())); - chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT; /* record event */ + ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_TIMEOUT); /* record event */ return 1; } @@ -921,8 +921,6 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char const char *function, const char *name_fmt, va_list ap) { struct ast_channel *tmp; - int x; - int flags; struct varshead *headp; char *tech = "", *tech2 = NULL; struct ast_format_cap *nativeformats; @@ -960,12 +958,9 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char * the destructor can know not to close them. */ ast_channel_timingfd_set(tmp, -1); - for (x = 0; x < ARRAY_LEN(tmp->alertpipe); ++x) { - tmp->alertpipe[x] = -1; - } - for (x = 0; x < ARRAY_LEN(tmp->fds); ++x) { - tmp->fds[x] = -1; - } + ast_channel_internal_alertpipe_clear(tmp); + ast_channel_internal_fd_clear_all(tmp); + #ifdef HAVE_EPOLL ast_channel_epfd(tmp) = epoll_create(25); #endif @@ -1004,22 +999,8 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char ast_channel_timingfd_set(tmp, ast_timer_fd(ast_channel_timer(tmp))); } - if (needqueue) { - if (pipe(tmp->alertpipe)) { - ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe! Try increasing max file descriptors with ulimit -n\n"); - return ast_channel_unref(tmp); - } else { - flags = fcntl(tmp->alertpipe[0], F_GETFL); - if (fcntl(tmp->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) { - ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno)); - return ast_channel_unref(tmp); - } - flags = fcntl(tmp->alertpipe[1], F_GETFL); - if (fcntl(tmp->alertpipe[1], F_SETFL, flags | O_NONBLOCK) < 0) { - ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno)); - return ast_channel_unref(tmp); - } - } + if (needqueue && ast_channel_internal_alertpipe_init(tmp)) { + return ast_channel_unref(tmp); } /* @@ -1034,7 +1015,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char } /* Always watch the alertpipe */ - ast_channel_set_fd(tmp, AST_ALERT_FD, tmp->alertpipe[0]); + ast_channel_set_fd(tmp, AST_ALERT_FD, ast_channel_internal_alert_readfd(tmp)); /* And timing pipe */ ast_channel_set_fd(tmp, AST_TIMING_FD, ast_channel_timingfd(tmp)); @@ -1308,11 +1289,8 @@ static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, in AST_LIST_APPEND_LIST(ast_channel_readq(chan), &frames, frame_list); } - if (chan->alertpipe[1] > -1) { - int blah[new_frames]; - - memset(blah, 1, sizeof(blah)); - if (write(chan->alertpipe[1], &blah, sizeof(blah)) != (sizeof(blah))) { + if (ast_channel_alert_writable(chan)) { + if (ast_channel_alert_write(chan)) { ast_log(LOG_WARNING, "Unable to write to alert pipe on %s (qlen = %d): %s!\n", ast_channel_name(chan), queued_frames, strerror(errno)); } @@ -1343,7 +1321,7 @@ int ast_queue_hangup(struct ast_channel *chan) struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP }; /* Yeah, let's not change a lock-critical value without locking */ if (!ast_channel_trylock(chan)) { - chan->_softhangup |= AST_SOFTHANGUP_DEV; + ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV); manager_event(EVENT_FLAG_CALL, "HangupRequest", "Channel: %s\r\n" "Uniqueid: %s\r\n", @@ -1364,7 +1342,7 @@ int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause) /* Yeah, let's not change a lock-critical value without locking */ if (!ast_channel_trylock(chan)) { - chan->_softhangup |= AST_SOFTHANGUP_DEV; + ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV); if (cause < 0) f.data.uint32 = ast_channel_hangupcause(chan); @@ -2185,7 +2163,6 @@ void ast_party_redirecting_free(struct ast_party_redirecting *doomed) static void ast_channel_destructor(void *obj) { struct ast_channel *chan = obj; - int fd; #ifdef HAVE_EPOLL int i; #endif @@ -2256,17 +2233,15 @@ static void ast_channel_destructor(void *obj) ast_party_redirecting_free(ast_channel_redirecting(chan)); /* Close pipes if appropriate */ - if ((fd = chan->alertpipe[0]) > -1) - close(fd); - if ((fd = chan->alertpipe[1]) > -1) - close(fd); + ast_channel_internal_alertpipe_close(chan); if (ast_channel_timer(chan)) { ast_timer_close(ast_channel_timer(chan)); } #ifdef HAVE_EPOLL for (i = 0; i < AST_MAX_FDS; i++) { - if (chan->epfd_data[i]) - free(chan->epfd_data[i]); + if (ast_channel_internal_epfd_data(chan, i)) { + ast_free(ast_channel_internal_epfd_data(chan, i)); + } } close(ast_channel_epfd(chan)); #endif @@ -2410,9 +2385,9 @@ void ast_channel_set_fd(struct ast_channel *chan, int which, int fd) struct epoll_event ev; struct ast_epoll_data *aed = NULL; - if (chan->fds[which] > -1) { - epoll_ctl(ast_channel_epfd(chan), EPOLL_CTL_DEL, chan->fds[which], &ev); - aed = chan->epfd_data[which]; + 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 */ @@ -2420,7 +2395,7 @@ void ast_channel_set_fd(struct ast_channel *chan, int which, int fd) if (!aed && (!(aed = ast_calloc(1, sizeof(*aed))))) return; - chan->epfd_data[which] = aed; + ast_channel_internal_epfd_data_set(chan, which, aed); aed->chan = chan; aed->which = which; @@ -2429,11 +2404,11 @@ void ast_channel_set_fd(struct ast_channel *chan, int which, int fd) 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 */ - free(aed); - chan->epfd_data[which] = NULL; + ast_free(aed); + ast_channel_epfd_data_set(chan, which, NULL); } #endif - chan->fds[which] = fd; + ast_channel_internal_fd_set(chan, which, fd); return; } @@ -2449,11 +2424,12 @@ void ast_poll_channel_add(struct ast_channel *chan0, struct ast_channel *chan1) /* Iterate through the file descriptors on chan1, adding them to chan0 */ for (i = 0; i < AST_MAX_FDS; i++) { - if (chan1->fds[i] == -1) + if (!ast_channel_fd_isset(chan1, i)) { continue; + } ev.events = EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP; - ev.data.ptr = chan1->epfd_data[i]; - epoll_ctl(ast_channel_epfd(chan0), EPOLL_CTL_ADD, chan1->fds[i], &ev); + 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 @@ -2471,9 +2447,10 @@ void ast_poll_channel_del(struct ast_channel *chan0, struct ast_channel *chan1) return; for (i = 0; i < AST_MAX_FDS; i++) { - if (chan1->fds[i] == -1) + if (!ast_channel_fd_isset(chan1, i)) { continue; - epoll_ctl(ast_channel_epfd(chan0), EPOLL_CTL_DEL, chan1->fds[i], &ev); + } + epoll_ctl(ast_channel_epfd(chan0), EPOLL_CTL_DEL, ast_channel_fd(chan1, i), &ev); } #endif @@ -2484,9 +2461,9 @@ void ast_channel_clear_softhangup(struct ast_channel *chan, int flag) { ast_channel_lock(chan); - chan->_softhangup &= ~flag; + ast_channel_softhangup_internal_flag_clear(chan, flag); - if (!chan->_softhangup) { + if (!ast_channel_softhangup_internal_flag(chan)) { struct ast_frame *fr; /* If we have completely cleared the softhangup flag, @@ -2510,7 +2487,7 @@ int ast_softhangup_nolock(struct ast_channel *chan, int cause) { ast_debug(1, "Soft-Hanging up channel '%s'\n", ast_channel_name(chan)); /* Inform channel driver that we need to be hung up, if it cares */ - chan->_softhangup |= cause; + ast_channel_softhangup_internal_flag_add(chan, cause); ast_queue_frame(chan, &ast_null_frame); /* Interrupt any poll call or such */ if (ast_test_flag(chan, AST_FLAG_BLOCKING)) @@ -3012,7 +2989,7 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, diff = ast_tvsub(*ast_channel_whentohangup(c[x]), now); if (diff.tv_sec < 0 || ast_tvzero(diff)) { /* Should already be hungup */ - c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; + ast_channel_softhangup_internal_flag_add(c[x], AST_SOFTHANGUP_TIMEOUT); ast_channel_unlock(c[x]); return c[x]; } @@ -3043,7 +3020,7 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, for (y = 0; y < AST_MAX_FDS; 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], c[x]->fds[y]); + max += ast_add_fd(&pfds[max], ast_channel_fd(c[x], y)); } CHECK_BLOCKING(c[x]); } @@ -3079,7 +3056,7 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, now = ast_tvnow(); for (x = 0; x < n; x++) { if (!ast_tvzero(*ast_channel_whentohangup(c[x])) && ast_tvcmp(*ast_channel_whentohangup(c[x]), now) <= 0) { - c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; + ast_channel_softhangup_internal_flag_add(c[x], AST_SOFTHANGUP_TIMEOUT); if (winner == NULL) winner = c[x]; } @@ -3144,7 +3121,7 @@ static struct ast_channel *ast_waitfor_nandfds_simple(struct ast_channel *chan, if (!ast_tvzero(*ast_channel_whentohangup(chan))) { if ((diff = ast_tvdiff_ms(*ast_channel_whentohangup(chan), ast_tvnow())) < 0) { /* They should already be hungup! */ - chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT; + ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_TIMEOUT); ast_channel_unlock(chan); return NULL; } @@ -3177,7 +3154,7 @@ static struct ast_channel *ast_waitfor_nandfds_simple(struct ast_channel *chan, /* 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) { - chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT; + ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_TIMEOUT); winner = chan; } } @@ -3226,7 +3203,7 @@ static struct ast_channel *ast_waitfor_nandfds_complex(struct ast_channel **c, i if (whentohangup == 0) now = ast_tvnow(); if ((diff = ast_tvdiff_ms(*ast_channel_whentohangup(c[i]), now)) < 0) { - c[i]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; + ast_channel_softhangup_internal_flag_add(c[i], AST_SOFTHANGUP_TIMEOUT); ast_channel_unlock(c[i]); return c[i]; } @@ -3262,7 +3239,7 @@ static struct ast_channel *ast_waitfor_nandfds_complex(struct ast_channel **c, i 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) { - c[i]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; + ast_channel_softhangup_internal_flag_add(c[i], AST_SOFTHANGUP_TIMEOUT); if (!winner) winner = c[i]; } @@ -3576,7 +3553,6 @@ static inline int calc_monitor_jump(int samples, int sample_rate, int seek_rate) static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) { struct ast_frame *f = NULL; /* the return value */ - int blah; int prestate; int cause = 0; @@ -3609,7 +3585,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) * ast_queue_control() will be called repeatedly, but will only * queue the first end-of-Q frame. */ - if (chan->_softhangup) { + if (ast_channel_softhangup_internal_flag(chan)) { ast_queue_control(chan, AST_CONTROL_END_OF_Q); } else { goto done; @@ -3640,22 +3616,9 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) /* Read and ignore anything on the alertpipe, but read only one sizeof(blah) per frame that we send from it */ - if (chan->alertpipe[0] > -1) { - int flags = fcntl(chan->alertpipe[0], F_GETFL); - /* For some odd reason, the alertpipe occasionally loses nonblocking status, - * which immediately causes a deadlock scenario. Detect and prevent this. */ - if ((flags & O_NONBLOCK) == 0) { - ast_log(LOG_ERROR, "Alertpipe on channel %s lost O_NONBLOCK?!!\n", ast_channel_name(chan)); - if (fcntl(chan->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) { - ast_log(LOG_WARNING, "Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno)); - f = &ast_null_frame; - goto done; - } - } - if (read(chan->alertpipe[0], &blah, sizeof(blah)) < 0) { - if (errno != EINTR && errno != EAGAIN) - ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); - } + if (ast_channel_internal_alert_read(chan) == AST_ALERT_READ_FATAL) { + f = &ast_null_frame; + goto done; } if (ast_channel_timingfd(chan) > -1 && ast_channel_fdno(chan) == AST_TIMING_FD) { @@ -3693,7 +3656,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) break; } - } else if (chan->fds[AST_GENERATOR_FD] > -1 && ast_channel_fdno(chan) == AST_GENERATOR_FD) { + } else if (ast_channel_fd_isset(chan, AST_GENERATOR_FD) && ast_channel_fdno(chan) == AST_GENERATOR_FD) { /* if the AST_GENERATOR_FD is set, call the generator with args * set to -1 so it can do whatever it needs to. */ @@ -3704,7 +3667,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) f = &ast_null_frame; ast_channel_fdno_set(chan, -1); goto done; - } else if (chan->fds[AST_JITTERBUFFER_FD] > -1 && ast_channel_fdno(chan) == AST_JITTERBUFFER_FD) { + } else if (ast_channel_fd_isset(chan, AST_JITTERBUFFER_FD) && ast_channel_fdno(chan) == AST_JITTERBUFFER_FD) { ast_clear_flag(chan, AST_FLAG_EXCEPTION); } @@ -3729,14 +3692,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) if (!f) { /* There were no acceptable frames on the readq. */ f = &ast_null_frame; - if (chan->alertpipe[0] > -1) { - int poke = 0; - /* Restore the state of the alertpipe since we aren't ready for any - * of the frames in the readq. */ - if (write(chan->alertpipe[1], &poke, sizeof(poke)) != sizeof(poke)) { - ast_log(LOG_ERROR, "Failed to write to alertpipe: %s\n", strerror(errno)); - } - } + ast_channel_alert_write(chan); } /* Interpret hangup and end-of-Q frames to return NULL */ @@ -3744,7 +3700,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) if (f->frametype == AST_FRAME_CONTROL) { switch (f->subclass.integer) { case AST_CONTROL_HANGUP: - chan->_softhangup |= AST_SOFTHANGUP_DEV; + ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV); cause = f->data.uint32; /* Fall through */ case AST_CONTROL_END_OF_Q: @@ -4084,8 +4040,8 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) } } else { /* Make sure we always return NULL in the future */ - if (!chan->_softhangup) { - chan->_softhangup |= AST_SOFTHANGUP_DEV; + if (!ast_channel_softhangup_internal_flag(chan)) { + ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV); } if (cause) ast_channel_hangupcause_set(chan, cause); @@ -4908,7 +4864,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) AST_LIST_NEXT(cur, frame_list) = NULL; if (!skip) { if ((res = ast_channel_tech(chan)->write(chan, cur)) < 0) { - chan->_softhangup |= AST_SOFTHANGUP_DEV; + ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV); skip = 1; } else if (next) { /* don't do this for the last frame in the list, @@ -4946,7 +4902,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) /* Consider a write failure to force a soft hangup */ if (res < 0) { - chan->_softhangup |= AST_SOFTHANGUP_DEV; + ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV); } else { ast_channel_fout_set(chan, FRAMECOUNT_INC(ast_channel_fout(chan))); } @@ -6442,7 +6398,7 @@ static void masquerade_colp_transfer(struct ast_channel *transferee, struct xfer */ int ast_do_masquerade(struct ast_channel *original) { - int x, i; + int x; int res=0; int origstate; int visible_indication; @@ -6603,11 +6559,7 @@ int ast_do_masquerade(struct ast_channel *original) ast_channel_tech_pvt_set(clonechan, t_pvt); /* Swap the alertpipes */ - for (i = 0; i < 2; i++) { - x = original->alertpipe[i]; - original->alertpipe[i] = clonechan->alertpipe[i]; - clonechan->alertpipe[i] = x; - } + ast_channel_internal_alertpipe_swap(original, clonechan); /* * Swap the readq's. The end result should be this: @@ -6629,12 +6581,8 @@ int ast_do_masquerade(struct ast_channel *original) while ((current = AST_LIST_REMOVE_HEAD(&tmp_readq, frame_list))) { AST_LIST_INSERT_TAIL(ast_channel_readq(original), current, frame_list); - if (original->alertpipe[1] > -1) { - int poke = 0; - - if (write(original->alertpipe[1], &poke, sizeof(poke)) < 0) { - ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); - } + if (ast_channel_alert_write(original)) { + ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); } } } @@ -6648,7 +6596,7 @@ int ast_do_masquerade(struct ast_channel *original) ast_format_copy(ast_channel_rawwriteformat(original), ast_channel_rawwriteformat(clonechan)); ast_format_copy(ast_channel_rawwriteformat(clonechan), &tmp_format); - clonechan->_softhangup = AST_SOFTHANGUP_DEV; + ast_channel_softhangup_internal_flag_set(clonechan, AST_SOFTHANGUP_DEV); /* And of course, so does our current state. Note we need not call ast_setstate since the event manager doesn't really consider @@ -6689,7 +6637,7 @@ int ast_do_masquerade(struct ast_channel *original) /* Copy the FD's other than the generator fd */ for (x = 0; x < AST_MAX_FDS; x++) { if (x != AST_GENERATOR_FD) - ast_channel_set_fd(original, x, clonechan->fds[x]); + ast_channel_set_fd(original, x, ast_channel_fd(clonechan, x)); } ast_app_group_update(clonechan, original); @@ -7113,11 +7061,11 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct /* No frame received within the specified timeout - check if we have to deliver now */ if (jb_in_use) ast_jb_get_and_deliver(c0, c1); - if ((c0->_softhangup | c1->_softhangup) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */ - if (c0->_softhangup & AST_SOFTHANGUP_UNBRIDGE) { + if ((ast_channel_softhangup_internal_flag(c0) | ast_channel_softhangup_internal_flag(c1)) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */ + if (ast_channel_softhangup_internal_flag(c0) & AST_SOFTHANGUP_UNBRIDGE) { ast_channel_clear_softhangup(c0, AST_SOFTHANGUP_UNBRIDGE); } - if (c1->_softhangup & AST_SOFTHANGUP_UNBRIDGE) { + if (ast_channel_softhangup_internal_flag(c1) & AST_SOFTHANGUP_UNBRIDGE) { ast_channel_clear_softhangup(c1, AST_SOFTHANGUP_UNBRIDGE); } c0->_bridge = c1; @@ -7469,11 +7417,11 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE); } - if ((c0->_softhangup | c1->_softhangup) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */ - if (c0->_softhangup & AST_SOFTHANGUP_UNBRIDGE) { + if ((ast_channel_softhangup_internal_flag(c0) | ast_channel_softhangup_internal_flag(c1)) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */ + if (ast_channel_softhangup_internal_flag(c0) & AST_SOFTHANGUP_UNBRIDGE) { ast_channel_clear_softhangup(c0, AST_SOFTHANGUP_UNBRIDGE); } - if (c1->_softhangup & AST_SOFTHANGUP_UNBRIDGE) { + if (ast_channel_softhangup_internal_flag(c1) & AST_SOFTHANGUP_UNBRIDGE) { ast_channel_clear_softhangup(c1, AST_SOFTHANGUP_UNBRIDGE); } c0->_bridge = c1; @@ -7519,7 +7467,7 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha ast_clear_flag(c0, AST_FLAG_NBRIDGE); ast_clear_flag(c1, AST_FLAG_NBRIDGE); - if ((c0->_softhangup | c1->_softhangup) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */ + if ((ast_channel_softhangup_internal_flag(c0) | ast_channel_softhangup_internal_flag(c1)) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */ continue; } diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c index bec785fb5..0a7060e29 100644 --- a/main/channel_internal_api.c +++ b/main/channel_internal_api.c @@ -31,6 +31,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") +#include +#include + #include "asterisk/channel.h" #include "asterisk/stringfields.h" #include "asterisk/data.h" @@ -181,13 +184,13 @@ int ast_channel_data_add_structure(struct ast_data *tree, if (!data_softhangup) { return -1; } - ast_data_add_bool(data_softhangup, "dev", chan->_softhangup & AST_SOFTHANGUP_DEV); - ast_data_add_bool(data_softhangup, "asyncgoto", chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO); - ast_data_add_bool(data_softhangup, "shutdown", chan->_softhangup & AST_SOFTHANGUP_SHUTDOWN); - ast_data_add_bool(data_softhangup, "timeout", chan->_softhangup & AST_SOFTHANGUP_TIMEOUT); - ast_data_add_bool(data_softhangup, "appunload", chan->_softhangup & AST_SOFTHANGUP_APPUNLOAD); - ast_data_add_bool(data_softhangup, "explicit", chan->_softhangup & AST_SOFTHANGUP_EXPLICIT); - ast_data_add_bool(data_softhangup, "unbridge", chan->_softhangup & AST_SOFTHANGUP_UNBRIDGE); + ast_data_add_bool(data_softhangup, "dev", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_DEV); + ast_data_add_bool(data_softhangup, "asyncgoto", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO); + ast_data_add_bool(data_softhangup, "shutdown", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_SHUTDOWN); + ast_data_add_bool(data_softhangup, "timeout", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_TIMEOUT); + ast_data_add_bool(data_softhangup, "appunload", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_APPUNLOAD); + ast_data_add_bool(data_softhangup, "explicit", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_EXPLICIT); + ast_data_add_bool(data_softhangup, "unbridge", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_UNBRIDGE); /* channel flags */ data_flags = ast_data_add_node(tree, "flags"); @@ -752,27 +755,205 @@ struct varshead *ast_channel_varshead(struct ast_channel *chan) { return &chan->__do_not_use_varshead; } +void ast_channel_dtmff_set(struct ast_channel *chan, struct ast_frame *value) +{ + memcpy(&chan->__do_not_use_dtmff, value, sizeof(chan->__do_not_use_dtmff)); +} +void ast_channel_jb_set(struct ast_channel *chan, struct ast_jb *value) +{ + memcpy(&chan->__do_not_use_jb, value, sizeof(chan->__do_not_use_jb)); +} void ast_channel_caller_set(struct ast_channel *chan, struct ast_party_caller *value) { - chan->__do_not_use_caller = *value; + memcpy(&chan->__do_not_use_caller, value, sizeof(chan->__do_not_use_caller)); } void ast_channel_connected_set(struct ast_channel *chan, struct ast_party_connected_line *value) { - chan->__do_not_use_connected = *value; + memcpy(&chan->__do_not_use_connected, value, sizeof(chan->__do_not_use_connected)); } void ast_channel_dialed_set(struct ast_channel *chan, struct ast_party_dialed *value) { - chan->__do_not_use_dialed = *value; + memcpy(&chan->__do_not_use_dialed, value, sizeof(chan->__do_not_use_dialed)); } void ast_channel_redirecting_set(struct ast_channel *chan, struct ast_party_redirecting *value) { - chan->__do_not_use_redirecting = *value; + memcpy(&chan->__do_not_use_redirecting, value, sizeof(chan->__do_not_use_redirecting)); } void ast_channel_dtmf_tv_set(struct ast_channel *chan, struct timeval *value) { - chan->__do_not_use_dtmf_tv = *value; + memcpy(&chan->__do_not_use_dtmf_tv, value, sizeof(chan->__do_not_use_dtmf_tv)); } void ast_channel_whentohangup_set(struct ast_channel *chan, struct timeval *value) { - chan->__do_not_use_whentohangup = *value; + memcpy(&chan->__do_not_use_whentohangup, value, sizeof(chan->__do_not_use_whentohangup)); +} +void ast_channel_varshead_set(struct ast_channel *chan, struct varshead *value) +{ + memcpy(&chan->__do_not_use_varshead, value, sizeof(chan->__do_not_use_varshead)); +} + +/* Evil softhangup accessors */ +int ast_channel_softhangup_internal_flag(struct ast_channel * chan) +{ + return chan->__do_not_use_softhangup; +} +void ast_channel_softhangup_internal_flag_set(struct ast_channel *chan, int value) +{ + chan->__do_not_use_softhangup = value; +} +void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value) +{ + chan->__do_not_use_softhangup |= value; +} +void ast_channel_softhangup_internal_flag_clear(struct ast_channel *chan, int value) +{ + chan ->__do_not_use_softhangup &= ~value; +} + +/* Typedef accessors */ +ast_group_t ast_channel_callgroup(const struct ast_channel *chan) +{ + return chan->__do_not_use_callgroup; +} +void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value) +{ + chan->__do_not_use_callgroup = value; +} +ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan) +{ + return chan->__do_not_use_pickupgroup; +} +void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value) +{ + chan->__do_not_use_pickupgroup = value; +} + +/* Alertpipe functions */ +int ast_channel_alert_write(struct ast_channel *chan) +{ + char blah = 0x7F; + return ast_channel_alert_writable(chan) && write(chan->__do_not_use_alertpipe[1], &blah, sizeof(blah)) != sizeof(blah); +} + +ast_alert_status_t ast_channel_internal_alert_read(struct ast_channel *chan) +{ + int flags; + char blah; + + if (!ast_channel_internal_alert_readable(chan)) { + return AST_ALERT_NOT_READABLE; + } + + flags = fcntl(chan->__do_not_use_alertpipe[0], F_GETFL); + /* For some odd reason, the alertpipe occasionally loses nonblocking status, + * which immediately causes a deadlock scenario. Detect and prevent this. */ + if ((flags & O_NONBLOCK) == 0) { + ast_log(LOG_ERROR, "Alertpipe on channel %s lost O_NONBLOCK?!!\n", ast_channel_name(chan)); + if (fcntl(chan->__do_not_use_alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) { + ast_log(LOG_WARNING, "Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno)); + return AST_ALERT_READ_FATAL; + } + } + if (read(chan->__do_not_use_alertpipe[0], &blah, sizeof(blah)) < 0) { + if (errno != EINTR && errno != EAGAIN) { + ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); + return AST_ALERT_READ_FAIL; + } + } + + return AST_ALERT_READ_SUCCESS; +} + +int ast_channel_alert_writable(struct ast_channel *chan) +{ + return chan->__do_not_use_alertpipe[1] > -1; +} + +int ast_channel_internal_alert_readable(struct ast_channel *chan) +{ + return chan->__do_not_use_alertpipe[0] > -1; } + +void ast_channel_internal_alertpipe_clear(struct ast_channel *chan) +{ + chan->__do_not_use_alertpipe[0] = chan->__do_not_use_alertpipe[1] = -1; +} + +void ast_channel_internal_alertpipe_close(struct ast_channel *chan) +{ + if (ast_channel_internal_alert_readable(chan)) { + close(chan->__do_not_use_alertpipe[0]); + } + if (ast_channel_alert_writable(chan)) { + close(chan->__do_not_use_alertpipe[1]); + } +} + +int ast_channel_internal_alertpipe_init(struct ast_channel *chan) +{ + if (pipe(chan->__do_not_use_alertpipe)) { + ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe! Try increasing max file descriptors with ulimit -n\n"); + return -1; + } else { + int flags = fcntl(chan->__do_not_use_alertpipe[0], F_GETFL); + if (fcntl(chan->__do_not_use_alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) { + ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno)); + return -1; + } + flags = fcntl(chan->__do_not_use_alertpipe[1], F_GETFL); + if (fcntl(chan->__do_not_use_alertpipe[1], F_SETFL, flags | O_NONBLOCK) < 0) { + ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno)); + return -1; + } + } + return 0; +} + +int ast_channel_internal_alert_readfd(struct ast_channel *chan) +{ + return chan->__do_not_use_alertpipe[0]; +} + +void ast_channel_internal_alertpipe_swap(struct ast_channel *chan1, struct ast_channel *chan2) +{ + int i; + for (i = 0; i < ARRAY_LEN(chan1->__do_not_use_alertpipe); i++) { + SWAP(chan1->__do_not_use_alertpipe[i], chan2->__do_not_use_alertpipe[i]); + } +} + +/* file descriptor array accessors */ +void ast_channel_internal_fd_set(struct ast_channel *chan, int which, int value) +{ + chan->__do_not_use_fds[which] = value; +} +void ast_channel_internal_fd_clear(struct ast_channel *chan, int which) +{ + ast_channel_internal_fd_set(chan, which, -1); +} +void ast_channel_internal_fd_clear_all(struct ast_channel *chan) +{ + int i; + for (i = 0; i < AST_MAX_FDS; i++) { + ast_channel_internal_fd_clear(chan, i); + } +} +int ast_channel_fd(const struct ast_channel *chan, int which) +{ + return chan->__do_not_use_fds[which]; +} +int ast_channel_fd_isset(const struct ast_channel *chan, int which) +{ + return ast_channel_fd(chan, which) > -1; +} + +#ifdef HAVE_EPOLL +struct ast_epoll_data *ast_channel_internal_epfd_data(const struct ast_channel *chan, int which) +{ + return chan->__do_not_use_epfd_data[which]; +} +void ast_channel_internal_epfd_data_set(struct ast_channel *chan, int which , struct ast_epoll_data *value) +{ + chan->__do_not_use_epfd_data[which] = value; +} +#endif diff --git a/main/cli.c b/main/cli.c index bfb4d6d07..591f6d556 100644 --- a/main/cli.c +++ b/main/cli.c @@ -1490,12 +1490,12 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar ast_translate_path_to_str(ast_channel_writetrans(c), &write_transpath), ast_channel_readtrans(c) ? "Yes" : "No", ast_translate_path_to_str(ast_channel_readtrans(c), &read_transpath), - c->fds[0], + ast_channel_fd(c, 0), ast_channel_fin(c) & ~DEBUGCHAN_FLAG, (ast_channel_fin(c) & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", ast_channel_fout(c) & ~DEBUGCHAN_FLAG, (ast_channel_fout(c) & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", (long)ast_channel_whentohangup(c)->tv_sec, cdrtime, c->_bridge ? ast_channel_name(c->_bridge) : "", ast_bridged_channel(c) ? ast_channel_name(ast_bridged_channel(c)) : "", - ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), c->callgroup, c->pickupgroup, (ast_channel_appl(c) ? ast_channel_appl(c) : "(N/A)" ), + ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_callgroup(c), ast_channel_pickupgroup(c), (ast_channel_appl(c) ? ast_channel_appl(c) : "(N/A)" ), (ast_channel_data(c) ? S_OR(ast_channel_data(c), "(Empty)") : "(None)"), (ast_test_flag(c, AST_FLAG_BLOCKING) ? ast_channel_blockproc(c) : "(Not Blocking)")); diff --git a/main/dsp.c b/main/dsp.c index d934c9cf5..77f72c18e 100644 --- a/main/dsp.c +++ b/main/dsp.c @@ -1437,7 +1437,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, return ast_frisolate(&dsp->f); } if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) { - chan->_softhangup |= AST_SOFTHANGUP_DEV; + ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV); memset(&dsp->f, 0, sizeof(dsp->f)); dsp->f.frametype = AST_FRAME_CONTROL; dsp->f.subclass.integer = AST_CONTROL_BUSY; diff --git a/main/features.c b/main/features.c index aa2810d18..03627ee38 100644 --- a/main/features.c +++ b/main/features.c @@ -4138,7 +4138,7 @@ int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct a * but it doesn't hurt to check AST_SOFTHANGUP_UNBRIDGE either. */ ast_channel_lock(chan); - if (chan->_softhangup & (AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE)) { + if (ast_channel_softhangup_internal_flag(chan) & (AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE)) { ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); } ast_channel_unlock(chan); @@ -4726,12 +4726,12 @@ static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds, struct ast_frame *f; int y; - if (chan->fds[x] == -1) { + if (!ast_channel_fd_isset(chan, x)) { continue; /* nothing on this descriptor */ } for (y = 0; y < nfds; y++) { - if (pfds[y].fd == chan->fds[x]) { + if (pfds[y].fd == ast_channel_fd(chan, x)) { /* Found poll record! */ break; } @@ -4792,7 +4792,7 @@ static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds, } /* End for */ if (x >= AST_MAX_FDS) { std: for (x = 0; x < AST_MAX_FDS; x++) { /* mark fds for next round */ - if (chan->fds[x] > -1) { + if (ast_channel_fd_isset(chan, x)) { void *tmp = ast_realloc(*new_pfds, (*new_nfds + 1) * sizeof(struct pollfd)); @@ -4800,7 +4800,7 @@ std: for (x = 0; x < AST_MAX_FDS; x++) { /* mark fds for next round */ continue; } *new_pfds = tmp; - (*new_pfds)[*new_nfds].fd = chan->fds[x]; + (*new_pfds)[*new_nfds].fd = ast_channel_fd(chan, x); (*new_pfds)[*new_nfds].events = POLLIN | POLLERR | POLLPRI; (*new_pfds)[*new_nfds].revents = 0; (*new_nfds)++; @@ -7249,7 +7249,7 @@ static int find_channel_by_group(void *obj, void *arg, void *data, int flags) struct ast_channel *chan = data;/*!< Channel wanting to pickup call */ ast_channel_lock(target); - if (chan != target && (chan->pickupgroup & target->callgroup) + if (chan != target && (ast_channel_pickupgroup(chan) & ast_channel_callgroup(target)) && ast_can_pickup(target)) { /* Return with the channel still locked on purpose */ return CMP_MATCH | CMP_STOP; diff --git a/main/file.c b/main/file.c index 588dfe2f7..82f2aab86 100644 --- a/main/file.c +++ b/main/file.c @@ -1381,7 +1381,7 @@ static int waitstream_core(struct ast_channel *c, const char *breakon, ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); - return (err || c->_softhangup) ? -1 : 0; + return (err || ast_channel_softhangup_internal_flag(c)) ? -1 : 0; } int ast_waitstream_fr(struct ast_channel *c, const char *breakon, const char *forward, const char *reverse, int ms) diff --git a/main/pbx.c b/main/pbx.c index a5a2c08fd..d848fc3b6 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -5079,7 +5079,7 @@ static int collect_digits(struct ast_channel *c, int waittime, char *buf, int bu /* As long as we're willing to wait, and as long as it's not defined, keep reading digits until we can't possibly get a right answer anymore. */ digit = ast_waitfordigit(c, waittime); - if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { + if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) { ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); } else { if (!digit) /* No entry */ @@ -5155,11 +5155,11 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c, } /* Check softhangup flags. */ - if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { + if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) { ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); continue; } - if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { + if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) { if (ast_exists_extension(c, ast_channel_context(c), "T", 1, S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) { set_ext_pri(c, "T", 1); @@ -5222,11 +5222,11 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c, } } - if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) { + if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) { ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO); continue; } - if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { + if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) { if (ast_exists_extension(c, ast_channel_context(c), "T", 1, S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) { set_ext_pri(c, "T", 1); @@ -5283,7 +5283,7 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c, error = 1; /* we know what to do with it */ break; } - } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) { + } else if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) { /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */ ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT); } else { /* keypress received, get more digits for a full extension */ -- cgit v1.2.3