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
1.0
Mark Spencer 22 years ago
parent 687b0ebe6e
commit 2524d2c413

@ -38,6 +38,9 @@
#ifdef ZAPTEL_OPTIMIZATIONS #ifdef ZAPTEL_OPTIMIZATIONS
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/zaptel.h> #include <linux/zaptel.h>
#ifndef ZT_TIMERPING
#error "You need newer zaptel! Please cvs update zaptel"
#endif
#endif #endif
/* uncomment if you have problems with 'monitoring' synchronized files */ /* uncomment if you have problems with 'monitoring' synchronized files */
@ -284,6 +287,18 @@ struct ast_channel *ast_channel_alloc(int needqueue)
if (tmp->sched) { if (tmp->sched) {
for (x=0;x<AST_MAX_FDS - 1;x++) for (x=0;x<AST_MAX_FDS - 1;x++)
tmp->fds[x] = -1; 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 && if (needqueue &&
pipe(pvt->alertpipe)) { pipe(pvt->alertpipe)) {
ast_log(LOG_WARNING, "Alert pipe creation failed!\n"); ast_log(LOG_WARNING, "Alert pipe creation failed!\n");
@ -292,19 +307,14 @@ struct ast_channel *ast_channel_alloc(int needqueue)
tmp = NULL; tmp = NULL;
pvt = NULL; pvt = NULL;
} else { } else {
/* Make sure we've got it done right if they don't */
if (needqueue) { if (needqueue) {
flags = fcntl(pvt->alertpipe[0], F_GETFL); flags = fcntl(pvt->alertpipe[0], F_GETFL);
fcntl(pvt->alertpipe[0], F_SETFL, flags | O_NONBLOCK); fcntl(pvt->alertpipe[0], F_SETFL, flags | O_NONBLOCK);
flags = fcntl(pvt->alertpipe[1], F_GETFL); flags = fcntl(pvt->alertpipe[1], F_GETFL);
fcntl(pvt->alertpipe[1], F_SETFL, flags | O_NONBLOCK); 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; 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 */ /* Always watch the alertpipe */
tmp->fds[AST_MAX_FDS-1] = pvt->alertpipe[0]; tmp->fds[AST_MAX_FDS-1] = pvt->alertpipe[0];
/* And timing pipe */ /* 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)) 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", 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)); 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) { } else if (chan->blocking) {
pthread_kill(chan->blocker, SIGURG); pthread_kill(chan->blocker, SIGURG);
} }
@ -1023,6 +1037,7 @@ struct ast_frame *ast_read(struct ast_channel *chan)
#ifdef ZAPTEL_OPTIMIZATIONS #ifdef ZAPTEL_OPTIMIZATIONS
int (*func)(void *); int (*func)(void *);
void *data; void *data;
int res;
#endif #endif
static struct ast_frame null_frame = 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) { if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && chan->exception) {
chan->exception = 0; chan->exception = 0;
blah = -1; blah = -1;
ioctl(chan->timingfd, ZT_TIMERACK, &blah); /* IF we can't get event, assume it's an expired as-per the old interface */
func = chan->timingfunc; res = ioctl(chan->timingfd, ZT_GETEVENT, &blah);
data = chan->timingdata; if (res)
ast_mutex_unlock(&chan->lock); blah = ZT_EVENT_TIMER_EXPIRED;
if (func) {
if (blah == ZT_EVENT_TIMER_PING) {
#if 0 #if 0
ast_log(LOG_DEBUG, "Calling private function\n"); ast_log(LOG_NOTICE, "Oooh, there's a PING!\n");
#endif #endif
func(data); if (!chan->pvt->readq || !chan->pvt->readq->next) {
} else { /* Acknowledge PONG unless we need it again */
blah = 0; #if 0
ast_mutex_lock(&chan->lock); ast_log(LOG_NOTICE, "Sending a PONG!\n");
ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah); #endif
chan->timingdata = NULL; 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); ast_mutex_unlock(&chan->lock);
} if (func) {
f = &null_frame; #if 0
return f; 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 #endif
/* Check for pending read queue */ /* Check for pending read queue */

Loading…
Cancel
Save