Add support for new PING/PONG on zaptel which reduces the # of file descriptors on...
authorMark Spencer <markster@digium.com>
Fri, 19 Mar 2004 04:23:20 +0000 (04:23 +0000)
committerMark Spencer <markster@digium.com>
Fri, 19 Mar 2004 04:23:20 +0000 (04:23 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2467 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channel.c

index 521742c..02e0049 100755 (executable)
--- 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 */