summaryrefslogtreecommitdiff
path: root/channel.c
diff options
context:
space:
mode:
authorMark Spencer <markster@digium.com>2004-03-19 04:23:20 +0000
committerMark Spencer <markster@digium.com>2004-03-19 04:23:20 +0000
commit2524d2c4135d62d97fc79e975f944a1c5ad316b0 (patch)
tree0ea72a42235ee6d7cef2a47b0abdf5f1a5079e7c /channel.c
parent687b0ebe6e0ba90d6032d78cddfb9c71b53d528b (diff)
Add support for new PING/PONG on zaptel which reduces the # of file descriptors on SIP/IAX channels (when zaptel interface is available) by 2 per channel
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2467 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channel.c')
-rwxr-xr-xchannel.c80
1 files changed, 58 insertions, 22 deletions
diff --git a/channel.c b/channel.c
index 521742cd5..02e004935 100755
--- a/channel.c
+++ b/channel.c
@@ -38,6 +38,9 @@
#ifdef ZAPTEL_OPTIMIZATIONS
#include <sys/ioctl.h>
#include <linux/zaptel.h>
+#ifndef ZT_TIMERPING
+#error "You need newer zaptel! Please cvs update zaptel"
+#endif
#endif
/* uncomment if you have problems with 'monitoring' synchronized files */
@@ -284,6 +287,18 @@ struct ast_channel *ast_channel_alloc(int needqueue)
if (tmp->sched) {
for (x=0;x<AST_MAX_FDS - 1;x++)
tmp->fds[x] = -1;
+#ifdef ZAPTEL_OPTIMIZATIONS
+ tmp->timingfd = open("/dev/zap/timer", O_RDWR);
+ if (tmp->timingfd > -1) {
+ /* Check if timing interface supports new
+ ping/pong scheme */
+ flags = 1;
+ if (!ioctl(tmp->timingfd, ZT_TIMERPONG, &flags))
+ needqueue = 0;
+ }
+#else
+ tmp->timingfd = -1;
+#endif
if (needqueue &&
pipe(pvt->alertpipe)) {
ast_log(LOG_WARNING, "Alert pipe creation failed!\n");
@@ -292,19 +307,14 @@ struct ast_channel *ast_channel_alloc(int needqueue)
tmp = NULL;
pvt = NULL;
} else {
- /* Make sure we've got it done right if they don't */
if (needqueue) {
flags = fcntl(pvt->alertpipe[0], F_GETFL);
fcntl(pvt->alertpipe[0], F_SETFL, flags | O_NONBLOCK);
flags = fcntl(pvt->alertpipe[1], F_GETFL);
fcntl(pvt->alertpipe[1], F_SETFL, flags | O_NONBLOCK);
- } else
+ } else
+ /* Make sure we've got it done right if they don't */
pvt->alertpipe[0] = pvt->alertpipe[1] = -1;
-#ifdef ZAPTEL_OPTIMIZATIONS
- tmp->timingfd = open("/dev/zap/timer", O_RDWR);
-#else
- tmp->timingfd = -1;
-#endif
/* Always watch the alertpipe */
tmp->fds[AST_MAX_FDS-1] = pvt->alertpipe[0];
/* And timing pipe */
@@ -392,6 +402,10 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
if (write(chan->pvt->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah))
ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n",
chan->name, f->frametype, f->subclass, qlen, strerror(errno));
+#ifdef ZAPTEL_OPTIMIZATIONS
+ } else if (chan->timingfd > -1) {
+ ioctl(chan->timingfd, ZT_TIMERPING, &blah);
+#endif
} else if (chan->blocking) {
pthread_kill(chan->blocker, SIGURG);
}
@@ -1023,6 +1037,7 @@ struct ast_frame *ast_read(struct ast_channel *chan)
#ifdef ZAPTEL_OPTIMIZATIONS
int (*func)(void *);
void *data;
+ int res;
#endif
static struct ast_frame null_frame =
{
@@ -1067,24 +1082,45 @@ struct ast_frame *ast_read(struct ast_channel *chan)
if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && chan->exception) {
chan->exception = 0;
blah = -1;
- ioctl(chan->timingfd, ZT_TIMERACK, &blah);
- func = chan->timingfunc;
- data = chan->timingdata;
- ast_mutex_unlock(&chan->lock);
- if (func) {
+ /* IF we can't get event, assume it's an expired as-per the old interface */
+ res = ioctl(chan->timingfd, ZT_GETEVENT, &blah);
+ if (res)
+ blah = ZT_EVENT_TIMER_EXPIRED;
+
+ if (blah == ZT_EVENT_TIMER_PING) {
#if 0
- ast_log(LOG_DEBUG, "Calling private function\n");
+ ast_log(LOG_NOTICE, "Oooh, there's a PING!\n");
#endif
- func(data);
- } else {
- blah = 0;
- ast_mutex_lock(&chan->lock);
- ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah);
- chan->timingdata = NULL;
+ if (!chan->pvt->readq || !chan->pvt->readq->next) {
+ /* Acknowledge PONG unless we need it again */
+#if 0
+ ast_log(LOG_NOTICE, "Sending a PONG!\n");
+#endif
+ if (ioctl(chan->timingfd, ZT_TIMERPONG, &blah)) {
+ ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno));
+ }
+ }
+ } else if (blah == ZT_EVENT_TIMER_EXPIRED) {
+ ioctl(chan->timingfd, ZT_TIMERACK, &blah);
+ func = chan->timingfunc;
+ data = chan->timingdata;
ast_mutex_unlock(&chan->lock);
- }
- f = &null_frame;
- return f;
+ if (func) {
+#if 0
+ ast_log(LOG_DEBUG, "Calling private function\n");
+#endif
+ func(data);
+ } else {
+ blah = 0;
+ ast_mutex_lock(&chan->lock);
+ ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah);
+ chan->timingdata = NULL;
+ ast_mutex_unlock(&chan->lock);
+ }
+ f = &null_frame;
+ return f;
+ } else
+ ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name);
}
#endif
/* Check for pending read queue */