summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorTerry Wilson <twilson@digium.com>2012-03-01 22:09:18 +0000
committerTerry Wilson <twilson@digium.com>2012-03-01 22:09:18 +0000
commit0e5c761c28a4ea091d760cfabc2ed3512ee2689a (patch)
treea9d5d359a27a013ac9e3cdf4162c2f32eea90324 /main
parente291318df2c7ed5ebbaec059d73271976c792091 (diff)
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
Diffstat (limited to 'main')
-rw-r--r--main/autoservice.c2
-rw-r--r--main/channel.c182
-rw-r--r--main/channel_internal_api.c207
-rw-r--r--main/cli.c4
-rw-r--r--main/dsp.c2
-rw-r--r--main/features.c12
-rw-r--r--main/file.c2
-rw-r--r--main/pbx.c12
8 files changed, 276 insertions, 147 deletions
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 <unistd.h>
+#include <fcntl.h>
+
#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) : "<none>", ast_bridged_channel(c) ? ast_channel_name(ast_bridged_channel(c)) : "<none>",
- 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 */