[asterisk-commits] file: trunk r78683 - in /trunk: ./ apps/ channels/ include/asterisk/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Aug 8 16:45:00 CDT 2007


Author: file
Date: Wed Aug  8 16:44:58 2007
New Revision: 78683

URL: http://svn.digium.com/view/asterisk?view=rev&rev=78683
Log:
Add support for using epoll instead of poll. This should increase scalability and is done in such a way that we should be able to add support for other poll() replacements.

Modified:
    trunk/apps/app_dial.c
    trunk/channels/chan_agent.c
    trunk/channels/chan_alsa.c
    trunk/channels/chan_features.c
    trunk/channels/chan_gtalk.c
    trunk/channels/chan_h323.c
    trunk/channels/chan_jingle.c
    trunk/channels/chan_mgcp.c
    trunk/channels/chan_misdn.c
    trunk/channels/chan_nbs.c
    trunk/channels/chan_oss.c
    trunk/channels/chan_phone.c
    trunk/channels/chan_sip.c
    trunk/channels/chan_skinny.c
    trunk/channels/chan_zap.c
    trunk/configure
    trunk/configure.ac
    trunk/include/asterisk/autoconfig.h.in
    trunk/include/asterisk/channel.h
    trunk/main/channel.c
    trunk/main/rtp.c

Modified: trunk/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/trunk/apps/app_dial.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/apps/app_dial.c (original)
+++ trunk/apps/app_dial.c Wed Aug  8 16:44:58 2007
@@ -560,6 +560,9 @@
 	struct ast_channel *peer = NULL;
 	/* single is set if only one destination is enabled */
 	int single = outgoing && !outgoing->next && !ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
+#ifdef HAVE_EPOLL
+	struct chanlist *epollo;
+#endif
 	
 	if (single) {
 		/* Turn off hold music, etc */
@@ -567,7 +570,11 @@
 		/* If we are calling a single channel, make them compatible for in-band tone purpose */
 		ast_channel_make_compatible(outgoing->chan, in);
 	}
-	
+
+#ifdef HAVE_EPOLL
+	for (epollo = outgoing; epollo; epollo = epollo->next)
+		ast_poll_channel_add(in, epollo->chan);
+#endif	
 	
 	while (*to && !peer) {
 		struct chanlist *o;
@@ -814,6 +821,11 @@
 		
 	}
 
+#ifdef HAVE_EPOLL
+	for (epollo = outgoing; epollo; epollo = epollo->next)
+		ast_poll_channel_del(in, epollo->chan);
+#endif
+
 	return peer;
 }
 

Modified: trunk/channels/chan_agent.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_agent.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_agent.c (original)
+++ trunk/channels/chan_agent.c Wed Aug  8 16:44:58 2007
@@ -207,9 +207,9 @@
 	if (p->chan) { \
 		for (x=0;x<AST_MAX_FDS;x++) {\
 			if (x != AST_TIMING_FD) \
-				ast->fds[x] = p->chan->fds[x]; \
+				ast_channel_set_fd(ast, x, p->chan->fds[x]); \
 		} \
-		ast->fds[AST_AGENT_FD] = p->chan->fds[AST_TIMING_FD]; \
+		ast_channel_set_fd(ast, AST_AGENT_FD, p->chan->fds[AST_TIMING_FD]); \
 	} \
 } while(0)
 

Modified: trunk/channels/chan_alsa.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_alsa.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_alsa.c (original)
+++ trunk/channels/chan_alsa.c Wed Aug  8 16:44:58 2007
@@ -789,7 +789,7 @@
 		return NULL;
 
 	tmp->tech = &alsa_tech;
-	tmp->fds[0] = readdev;
+	ast_channel_set_fd(tmp, 0, readdev);
 	tmp->nativeformats = AST_FORMAT_SLINEAR;
 	tmp->readformat = AST_FORMAT_SLINEAR;
 	tmp->writeformat = AST_FORMAT_SLINEAR;

Modified: trunk/channels/chan_features.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_features.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_features.c (original)
+++ trunk/channels/chan_features.c Wed Aug  8 16:44:58 2007
@@ -171,8 +171,8 @@
 	p->subs[index].owner->timingfd = p->subs[index].timingfdbackup;
 	p->subs[index].owner->alertpipe[0] = p->subs[index].alertpipebackup[0];
 	p->subs[index].owner->alertpipe[1] = p->subs[index].alertpipebackup[1];
-	p->subs[index].owner->fds[AST_ALERT_FD] = p->subs[index].alertpipebackup[0];
-	p->subs[index].owner->fds[AST_TIMING_FD] = p->subs[index].timingfdbackup;
+	ast_channel_set_fd(p->subs[index].owner, AST_ALERT_FD, p->subs[index].alertpipebackup[0]);
+	ast_channel_set_fd(p->subs[index].owner, AST_TIMING_FD, p->subs[index].timingfdbackup);
 }
 
 static void update_features(struct feature_pvt *p, int index)
@@ -181,9 +181,9 @@
 	if (p->subs[index].owner) {
 		for (x=0; x<AST_MAX_FDS; x++) {
 			if (index) 
-				p->subs[index].owner->fds[x] = -1;
+				ast_channel_set_fd(p->subs[index].owner, x, -1);
 			else
-				p->subs[index].owner->fds[x] = p->subchan->fds[x];
+				ast_channel_set_fd(p->subs[index].owner, x, p->subchan->fds[x]);
 		}
 		if (!index) {
 			/* Copy timings from master channel */

Modified: trunk/channels/chan_gtalk.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_gtalk.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_gtalk.c (original)
+++ trunk/channels/chan_gtalk.c Wed Aug  8 16:44:58 2007
@@ -934,13 +934,13 @@
 
 	if (i->rtp) {
 		ast_rtp_setstun(i->rtp, 1);
-		tmp->fds[0] = ast_rtp_fd(i->rtp);
-		tmp->fds[1] = ast_rtcp_fd(i->rtp);
+		ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp));
+		ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp));
 	}
 	if (i->vrtp) {
 		ast_rtp_setstun(i->rtp, 1);
-		tmp->fds[2] = ast_rtp_fd(i->vrtp);
-		tmp->fds[3] = ast_rtcp_fd(i->vrtp);
+		ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp));
+		ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp));
 	}
 	if (state == AST_STATE_RING)
 		tmp->rings = 1;

Modified: trunk/channels/chan_h323.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_h323.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_h323.c (original)
+++ trunk/channels/chan_h323.c Wed Aug  8 16:44:58 2007
@@ -396,8 +396,8 @@
 	if (pvt->update_rtp_info > 0) {
 		if (pvt->rtp) {
 			ast_jb_configure(c, &global_jbconf);
-			c->fds[0] = ast_rtp_fd(pvt->rtp);
-			c->fds[1] = ast_rtcp_fd(pvt->rtp);
+			ast_channel_set_fd(c, 0, ast_rtp_fd(pvt->rtp));
+			ast_channel_set_fd(c, 1, ast_rtcp_fd(pvt->rtp));
 			ast_queue_frame(pvt->owner, &ast_null_frame);	/* Tell Asterisk to apply changes */
 		}
 		pvt->update_rtp_info = -1;
@@ -995,8 +995,8 @@
 
 	if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
 		ast_jb_configure(pvt->owner, &global_jbconf);
-		pvt->owner->fds[0] = ast_rtp_fd(pvt->rtp);
-		pvt->owner->fds[1] = ast_rtcp_fd(pvt->rtp);
+		ast_channel_set_fd(pvt->owner, 0, ast_rtp_fd(pvt->rtp));
+		ast_channel_set_fd(pvt->owner, 1, ast_rtcp_fd(pvt->rtp));
 		ast_queue_frame(pvt->owner, &ast_null_frame);	/* Tell Asterisk to apply changes */
 		ast_channel_unlock(pvt->owner);
 	} else
@@ -1040,18 +1040,18 @@
 		ch->readformat = fmt;
 		ch->rawreadformat = fmt;
 #if 0
-		ch->fds[0] = ast_rtp_fd(pvt->rtp);
-		ch->fds[1] = ast_rtcp_fd(pvt->rtp);
+		ast_channel_set_fd(ch, 0, ast_rtp_fd(pvt->rtp));
+		ast_channel_set_fd(ch, 1, ast_rtcp_fd(pvt->rtp));
 #endif
 #ifdef VIDEO_SUPPORT
 		if (pvt->vrtp) {
-			ch->fds[2] = ast_rtp_fd(pvt->vrtp);
-			ch->fds[3] = ast_rtcp_fd(pvt->vrtp);
+			ast_channel_set_fd(ch, 2, ast_rtp_fd(pvt->vrtp));
+			ast_channel_set_fd(ch, 3, ast_rtcp_fd(pvt->vrtp));
 		}
 #endif
 #ifdef T38_SUPPORT
 		if (pvt->udptl) {
-			ch->fds[4] = ast_udptl_fd(pvt->udptl);
+			ast_channel_set_fd(ch, 4, ast_udptl_fd(pvt->udptl));
 		}
 #endif
 		if (state == AST_STATE_RING) {

Modified: trunk/channels/chan_jingle.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_jingle.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_jingle.c (original)
+++ trunk/channels/chan_jingle.c Wed Aug  8 16:44:58 2007
@@ -795,12 +795,12 @@
 	fmt = ast_best_codec(tmp->nativeformats);
 
 	if (i->rtp) {
-		tmp->fds[0] = ast_rtp_fd(i->rtp);
-		tmp->fds[1] = ast_rtcp_fd(i->rtp);
+		ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp));
+		ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp));
 	}
 	if (i->vrtp) {
-		tmp->fds[2] = ast_rtp_fd(i->vrtp);
-		tmp->fds[3] = ast_rtcp_fd(i->vrtp);
+		ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp));
+		ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp));
 	}
 	if (state == AST_STATE_RING)
 		tmp->rings = 1;

Modified: trunk/channels/chan_mgcp.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_mgcp.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_mgcp.c (original)
+++ trunk/channels/chan_mgcp.c Wed Aug  8 16:44:58 2007
@@ -1456,7 +1456,7 @@
 		fmt = ast_best_codec(tmp->nativeformats);
 		ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
 		if (sub->rtp)
-			tmp->fds[0] = ast_rtp_fd(sub->rtp);
+			ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp));
 		if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
 			i->dsp = ast_dsp_new();
 			ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
@@ -2588,7 +2588,7 @@
 	/* Allocate the RTP now */
 	sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
 	if (sub->rtp && sub->owner)
-		sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
+		ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp));
 	if (sub->rtp)
 		ast_rtp_setnat(sub->rtp, sub->nat);
 #if 0

Modified: trunk/channels/chan_misdn.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_misdn.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_misdn.c (original)
+++ trunk/channels/chan_misdn.c Wed Aug  8 16:44:58 2007
@@ -3220,7 +3220,7 @@
 		if (pipe(chlist->pipe) < 0)
 			ast_log(LOG_ERROR, "Pipe failed\n");
 
-		tmp->fds[0] = chlist->pipe[0];
+		ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
 
 		if (state == AST_STATE_RING)
 			tmp->rings = 1;

Modified: trunk/channels/chan_nbs.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_nbs.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_nbs.c (original)
+++ trunk/channels/chan_nbs.c Wed Aug  8 16:44:58 2007
@@ -232,7 +232,7 @@
 	tmp = ast_channel_alloc(1, state, 0, 0, "", "s", context, 0, "NBS/%s", i->stream);
 	if (tmp) {
 		tmp->tech = &nbs_tech;
-		tmp->fds[0] = nbs_fd(i->nbs);
+		ast_channel_set_fd(tmp, 0, nbs_fd(i->nbs));
 		tmp->nativeformats = prefformat;
 		tmp->rawreadformat = prefformat;
 		tmp->rawwriteformat = prefformat;

Modified: trunk/channels/chan_oss.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_oss.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_oss.c (original)
+++ trunk/channels/chan_oss.c Wed Aug  8 16:44:58 2007
@@ -692,7 +692,7 @@
 		return -1;
 	}
 	if (o->owner)
-		o->owner->fds[0] = fd;
+		ast_channel_set_fd(o->owner, 0, fd);
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 	fmt = AFMT_S16_LE;
@@ -1026,7 +1026,7 @@
 	c->tech = &oss_tech;
 	if (o->sounddev < 0)
 		setformat(o, O_RDWR);
-	c->fds[0] = o->sounddev;	/* -1 if device closed, override later */
+	ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */
 	c->nativeformats = AST_FORMAT_SLINEAR;
 	c->readformat = AST_FORMAT_SLINEAR;
 	c->writeformat = AST_FORMAT_SLINEAR;

Modified: trunk/channels/chan_phone.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_phone.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_phone.c (original)
+++ trunk/channels/chan_phone.c Wed Aug  8 16:44:58 2007
@@ -855,7 +855,7 @@
 	tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, 0, "Phone/%s", i->dev + 5);
 	if (tmp) {
 		tmp->tech = cur_tech;
-		tmp->fds[0] = i->fd;
+		ast_channel_set_fd(tmp, 0, i->fd);
 		/* XXX Switching formats silently causes kernel panics XXX */
 		if (i->mode == MODE_FXS &&
 		    ioctl(i->fd, PHONE_QUERY_CODEC, &codec) == 0) {

Modified: trunk/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_sip.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Wed Aug  8 16:44:58 2007
@@ -4553,18 +4553,18 @@
 			ast_dsp_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
 	}
 	if (i->rtp) {
-		tmp->fds[0] = ast_rtp_fd(i->rtp);
-		tmp->fds[1] = ast_rtcp_fd(i->rtp);
+		ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp));
+		ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp));
 	}
 	if (needvideo && i->vrtp) {
-		tmp->fds[2] = ast_rtp_fd(i->vrtp);
-		tmp->fds[3] = ast_rtcp_fd(i->vrtp);
+		ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp));
+		ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp));
 	}
 	if (needtext && i->trtp) {
-		tmp->fds[4] = ast_rtp_fd(i->trtp);
+		ast_channel_set_fd(tmp, 4, ast_rtp_fd(i->trtp));
 	}
 	if (i->udptl) {
-		tmp->fds[5] = ast_udptl_fd(i->udptl);
+		ast_channel_set_fd(tmp, 5, ast_udptl_fd(i->udptl));
 	}
 	if (state == AST_STATE_RING)
 		tmp->rings = 1;

Modified: trunk/channels/chan_skinny.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_skinny.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_skinny.c (original)
+++ trunk/channels/chan_skinny.c Wed Aug  8 16:44:58 2007
@@ -2515,12 +2515,12 @@
 		sub->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
 	
 	if (sub->rtp && sub->owner) {
-		sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
-		sub->owner->fds[1] = ast_rtcp_fd(sub->rtp);
+		ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp));
+		ast_channel_set_fd(sub->owner, 1, ast_rtcp_fd(sub->rtp));
 	}
 	if (hasvideo && sub->vrtp && sub->owner) {
-		sub->owner->fds[2] = ast_rtp_fd(sub->vrtp);
-		sub->owner->fds[3] = ast_rtcp_fd(sub->vrtp);
+		ast_channel_set_fd(sub->owner, 2, ast_rtp_fd(sub->vrtp));
+		ast_channel_set_fd(sub->owner, 3, ast_rtcp_fd(sub->vrtp));
 	}
 	if (sub->rtp) {
 		ast_rtp_setnat(sub->rtp, l->nat);
@@ -3070,7 +3070,7 @@
 		if (skinnydebug)
 			ast_verbose("skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
 		if (sub->rtp) {
-			tmp->fds[0] = ast_rtp_fd(sub->rtp);
+			ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp));
 		}
 		if (state == AST_STATE_RING) {
 			tmp->rings = 1;

Modified: trunk/channels/chan_zap.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_zap.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/channels/chan_zap.c (original)
+++ trunk/channels/chan_zap.c Wed Aug  8 16:44:58 2007
@@ -1013,9 +1013,9 @@
 	p->subs[b].inthreeway = tinthreeway;
 
 	if (p->subs[a].owner) 
-		p->subs[a].owner->fds[0] = p->subs[a].zfd;
+		ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].zfd);
 	if (p->subs[b].owner) 
-		p->subs[b].owner->fds[0] = p->subs[b].zfd;
+		ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].zfd);
 	wakeup_sub(p, a, NULL);
 	wakeup_sub(p, b, NULL);
 }
@@ -2595,7 +2595,7 @@
 	bearer->realcall = crv;
 	crv->subs[SUB_REAL].zfd = bearer->subs[SUB_REAL].zfd;
 	if (crv->subs[SUB_REAL].owner)
-		crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].zfd;
+		ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].zfd);
 	crv->bearer = bearer;
 	crv->call = bearer->call;
 	crv->pri = pri;
@@ -5515,7 +5515,7 @@
 		else
 			deflaw = AST_FORMAT_ULAW;
 	}
-	tmp->fds[0] = i->subs[index].zfd;
+	ast_channel_set_fd(tmp, 0, i->subs[index].zfd);
 	tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
 	/* Start out assuming ulaw since it's smaller :) */
 	tmp->rawreadformat = deflaw;
@@ -8977,7 +8977,7 @@
 							       "Zap/%d:%d-%d", pri->trunkgroup,
 							       pri->pvts[principle]->channel, 1);
 					pri->pvts[principle]->owner->tech_pvt = pri->pvts[principle];
-					pri->pvts[principle]->owner->fds[0] = pri->pvts[principle]->subs[SUB_REAL].zfd;
+					ast_channel_set_fd(pri->pvts[principle]->owner, 0, pri->pvts[principle]->subs[SUB_REAL].zfd);
 					pri->pvts[principle]->subs[SUB_REAL].owner = pri->pvts[x]->subs[SUB_REAL].owner;
 				} else
 					ast_log(LOG_WARNING, "Whoa, there's no  owner, and we're having to fix up channel %d to channel %d\n", pri->pvts[x]->channel, pri->pvts[principle]->channel);

Modified: trunk/configure
URL: http://svn.digium.com/view/asterisk/trunk/configure?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/configure (original)
+++ trunk/configure Wed Aug  8 16:44:58 2007
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.ac Revision: 77878 .
+# From configure.ac Revision: 60612 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.61.
 #
@@ -15624,6 +15624,60 @@
     fi
 
 
+{ echo "$as_me:$LINENO: checking for working epoll support" >&5
+echo $ECHO_N "checking for working epoll support... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/epoll.h>
+int
+main ()
+{
+epoll_create(10);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_EPOLL 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	{ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+
 { echo "$as_me:$LINENO: checking for compiler atomic operations" >&5
 echo $ECHO_N "checking for compiler atomic operations... $ECHO_C" >&6; }
 cat >conftest.$ac_ext <<_ACEOF

Modified: trunk/configure.ac
URL: http://svn.digium.com/view/asterisk/trunk/configure.ac?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/configure.ac (original)
+++ trunk/configure.ac Wed Aug  8 16:44:58 2007
@@ -331,6 +331,14 @@
 
 AST_C_DEFINE_CHECK([PTHREAD_RWLOCK_INITIALIZER], [PTHREAD_RWLOCK_INITIALIZER], [pthread.h])
 AST_C_DEFINE_CHECK([PTHREAD_RWLOCK_PREFER_WRITER_NP], [PTHREAD_RWLOCK_PREFER_WRITER_NP], [pthread.h])
+
+AC_MSG_CHECKING(for working epoll support)
+AC_LINK_IFELSE(
+AC_LANG_PROGRAM([#include <sys/epoll.h>], [epoll_create(10);]),
+AC_MSG_RESULT(yes)
+AC_DEFINE([HAVE_EPOLL], 1, [Define to 1 if your system has working epoll support.]),
+AC_MSG_RESULT(no)
+)
 
 AC_MSG_CHECKING(for compiler atomic operations)
 AC_LINK_IFELSE(

Modified: trunk/include/asterisk/autoconfig.h.in
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/autoconfig.h.in?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/include/asterisk/autoconfig.h.in (original)
+++ trunk/include/asterisk/autoconfig.h.in Wed Aug  8 16:44:58 2007
@@ -113,6 +113,9 @@
 
 /* Define to 1 if you have the `endpwent' function. */
 #undef HAVE_ENDPWENT
+
+/* Define to 1 if your system has working epoll support. */
+#undef HAVE_EPOLL
 
 /* Define this to indicate the ${EXP10_DESCRIP} library */
 #undef HAVE_EXP10

Modified: trunk/include/asterisk/channel.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/channel.h?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/include/asterisk/channel.h (original)
+++ trunk/include/asterisk/channel.h Wed Aug  8 16:44:58 2007
@@ -316,6 +316,8 @@
 	int (* func_channel_write)(struct ast_channel *chan, const char *function, char *data, const char *value);
 };
 
+struct ast_epoll_data;
+
 /*!
  * The high bit of the frame count is used as a debug marker, so
  * increments of the counters must be done with care.
@@ -490,6 +492,11 @@
 
 	/*! \brief Data stores on the channel */
 	AST_LIST_HEAD_NOLOCK(datastores, ast_datastore) datastores;
+
+#ifdef HAVE_EPOLL
+	int epfd;
+	struct ast_epoll_data *epfd_data[AST_MAX_FDS];
+#endif
 };
 
 /*! \brief ast_channel_tech Properties */
@@ -1184,6 +1191,15 @@
 
 void ast_set_callerid(struct ast_channel *chan, const char *cidnum, const char *cidname, const char *ani);
 
+/*! Set the file descriptor on the channel */
+void ast_channel_set_fd(struct ast_channel *chan, int which, int fd);
+
+/*! Add a channel to an optimized waitfor */
+void ast_poll_channel_add(struct ast_channel *chan0, struct ast_channel *chan1);
+
+/*! Delete a channel from an optimized waitfor */
+void ast_poll_channel_del(struct ast_channel *chan0, struct ast_channel *chan1);
+
 /*! Start a tone going */
 int ast_tonepair_start(struct ast_channel *chan, int freq1, int freq2, int duration, int vol);
 /*! Stop a tone from playing */

Modified: trunk/main/channel.c
URL: http://svn.digium.com/view/asterisk/trunk/main/channel.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Wed Aug  8 16:44:58 2007
@@ -66,6 +66,15 @@
 #include "asterisk/threadstorage.h"
 #include "asterisk/slinfactory.h"
 #include "asterisk/audiohook.h"
+
+#ifdef HAVE_EPOLL
+#include <sys/epoll.h>
+#endif
+
+struct ast_epoll_data {
+	struct ast_channel *chan;
+	int which;
+};
 
 /* uncomment if you have problems with 'monitoring' synchronized files */
 #if 0
@@ -631,11 +640,16 @@
 		return NULL;
 	}
 
-	/* Don't bother initializing the last two FD here, because they
-	   will *always* be set just a few lines down (AST_TIMING_FD,
-	   AST_ALERT_FD). */
-	for (x = 0; x < AST_MAX_FDS - 2; x++)
+#ifdef HAVE_EPOLL
+	tmp->epfd = epoll_create(25);
+#endif
+
+	for (x = 0; x < AST_MAX_FDS; x++) {
 		tmp->fds[x] = -1;
+#ifdef HAVE_EPOLL
+		tmp->epfd_data[x] = NULL;
+#endif
+	}
 
 #ifdef HAVE_ZAPTEL
 	tmp->timingfd = open("/dev/zap/timer", O_RDWR);
@@ -666,9 +680,9 @@
 		tmp->alertpipe[0] = tmp->alertpipe[1] = -1;
 
 	/* Always watch the alertpipe */
-	tmp->fds[AST_ALERT_FD] = tmp->alertpipe[0];
+	ast_channel_set_fd(tmp, AST_ALERT_FD, tmp->alertpipe[0]);
 	/* And timing pipe */
-	tmp->fds[AST_TIMING_FD] = tmp->timingfd;
+	ast_channel_set_fd(tmp, AST_TIMING_FD, tmp->timingfd);
 	ast_string_field_set(tmp, name, "**Unknown**");
 
 	/* Initial state */
@@ -1065,6 +1079,9 @@
 void ast_channel_free(struct ast_channel *chan)
 {
 	int fd;
+#ifdef HAVE_EPOLL
+	int i;
+#endif
 	struct ast_var_t *vardata;
 	struct ast_frame *f;
 	struct varshead *headp;
@@ -1116,6 +1133,13 @@
 		close(fd);
 	if ((fd = chan->timingfd) > -1)
 		close(fd);
+#ifdef HAVE_EPOLL
+	for (i = 0; i < AST_MAX_FDS; i++) {
+		if (chan->epfd_data[i])
+			free(chan->epfd_data[i]);
+	}
+	close(chan->epfd);
+#endif
 	while ((f = AST_LIST_REMOVE_HEAD(&chan->readq, frame_list)))
 		ast_frfree(f);
 	
@@ -1254,6 +1278,83 @@
 	AST_LIST_TRAVERSE_SAFE_END
 
 	return datastore;
+}
+
+/*! Set the file descriptor on the channel */
+void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
+{
+#ifdef HAVE_EPOLL
+	struct epoll_event ev;
+	struct ast_epoll_data *aed = NULL;
+
+	if (chan->fds[which] > -1) {
+		epoll_ctl(chan->epfd, EPOLL_CTL_DEL, chan->fds[which], &ev);
+		aed = chan->epfd_data[which];
+	}
+
+	/* If this new fd is valid, add it to the epoll */
+	if (fd > -1) {
+		if (!aed && (!(aed = ast_calloc(1, sizeof(*aed)))))
+			return;
+		
+		chan->epfd_data[which] = aed;
+		aed->chan = chan;
+		aed->which = which;
+		
+		ev.events = EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP;
+		ev.data.ptr = aed;
+		epoll_ctl(chan->epfd, 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;
+	}
+#endif
+	chan->fds[which] = fd;
+	return;
+}
+
+/*! Add a channel to an optimized waitfor */
+void ast_poll_channel_add(struct ast_channel *chan0, struct ast_channel *chan1)
+{
+#ifdef HAVE_EPOLL
+	struct epoll_event ev;
+	int i = 0;
+
+	if (chan0->epfd == -1)
+		return;
+
+	/* Iterate through the file descriptors on chan1, adding them to chan0 */
+	for (i = 0; i < AST_MAX_FDS; i++) {
+		if (chan1->fds[i] == -1)
+			continue;
+		ev.events = EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP;
+		ev.data.ptr = chan1->epfd_data[i];
+		epoll_ctl(chan0->epfd, EPOLL_CTL_ADD, chan1->fds[i], &ev);
+	}
+
+#endif
+	return;
+}
+
+/*! Delete a channel from an optimized waitfor */
+void ast_poll_channel_del(struct ast_channel *chan0, struct ast_channel *chan1)
+{
+#ifdef HAVE_EPOLL
+	struct epoll_event ev;
+	int i = 0;
+
+	if (chan0->epfd == -1)
+		return;
+
+	for (i = 0; i < AST_MAX_FDS; i++) {
+		if (chan1->fds[i] == -1)
+			continue;
+		epoll_ctl(chan0->epfd, EPOLL_CTL_DEL, chan1->fds[i], &ev);
+	}
+
+#endif
+	return;
 }
 
 /*! \brief Softly hangup a channel, don't lock */
@@ -1437,7 +1538,7 @@
 			chan->generator->release(chan, chan->generatordata);
 		chan->generatordata = NULL;
 		chan->generator = NULL;
-		chan->fds[AST_GENERATOR_FD] = -1;
+		ast_channel_set_fd(chan, AST_GENERATOR_FD, -1);
 		ast_clear_flag(chan, AST_FLAG_WRITE_INT);
 		ast_settimeout(chan, 0, NULL, NULL);
 	}
@@ -1499,8 +1600,13 @@
 }
 
 /*! \brief Wait for x amount of time on a file descriptor to have input.  */
+#ifdef HAVE_EPOLL
+static struct ast_channel *ast_waitfor_nandfds_classic(struct ast_channel **c, int n, int *fds, int nfds,
+					int *exception, int *outfd, int *ms)
+#else
 struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds,
-	int *exception, int *outfd, int *ms)
+					int *exception, int *outfd, int *ms)
+#endif
 {
 	struct timeval start = { 0 , 0 };
 	struct pollfd *pfds;
@@ -1526,15 +1632,13 @@
 		*exception = 0;
 	
 	/* Perform any pending masquerades */
-	for (x=0; x < n; x++) {
+	for (x = 0; x < n; x++) {
 		ast_channel_lock(c[x]);
-		if (c[x]->masq) {
-			if (ast_do_masquerade(c[x])) {
-				ast_log(LOG_WARNING, "Masquerade failed\n");
-				*ms = -1;
-				ast_channel_unlock(c[x]);
-				return NULL;
-			}
+		if (c[x]->masq && ast_do_masquerade(c[x])) {
+			ast_log(LOG_WARNING, "Masquerade failed\n");
+			*ms = -1;
+			ast_channel_unlock(c[x]);
+			return NULL;
 		}
 		if (c[x]->whentohangup) {
 			if (!whentohangup)
@@ -1564,8 +1668,8 @@
 	 * individual fd's must have priority over channel fds.
 	 */
 	max = 0;
-	for (x=0; x<n; x++) {
-		for (y=0; y<AST_MAX_FDS; y++) {
+	for (x = 0; x < n; x++) {
+		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]);
@@ -1573,7 +1677,7 @@
 		CHECK_BLOCKING(c[x]);
 	}
 	/* Add the individual fds */
-	for (x=0; x<nfds; x++) {
+	for (x = 0; x < nfds; x++) {
 		fdmap[max].chan = -1;
 		max += ast_add_fd(&pfds[max], fds[x]);
 	}
@@ -1593,7 +1697,7 @@
 	} else {
 		res = poll(pfds, max, rms);
 	}
-	for (x=0; x<n; x++)
+	for (x = 0; x < n; x++)
 		ast_clear_flag(c[x], AST_FLAG_BLOCKING);
 	if (res < 0) { /* Simulate a timeout if we were interrupted */
 		if (errno != EINTR)
@@ -1602,7 +1706,7 @@
 	}
 	if (whentohangup) {   /* if we have a timeout, check who expired */
 		time(&now);
-		for (x=0; x<n; x++) {
+		for (x = 0; x < n; x++) {
 			if (c[x]->whentohangup && now >= c[x]->whentohangup) {
 				c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
 				if (winner == NULL)
@@ -1645,6 +1749,200 @@
 	}
 	return winner;
 }
+
+#ifdef HAVE_EPOLL
+static struct ast_channel *ast_waitfor_nandfds_simple(struct ast_channel *chan, int *ms)
+{
+	struct timeval start = { 0 , 0 };
+	int res = 0;
+	struct epoll_event ev[1];
+	long whentohangup = 0, rms = *ms;
+	time_t now;
+	struct ast_channel *winner = NULL;
+	struct ast_epoll_data *aed = NULL;
+
+	ast_channel_lock(chan);
+
+	/* See if this channel needs to be masqueraded */
+	if (chan->masq && ast_do_masquerade(chan)) {
+		ast_log(LOG_WARNING, "Failed to perform masquerade on %s\n", chan->name);
+		*ms = -1;
+		ast_channel_unlock(chan);
+		return NULL;
+	}
+
+	/* Figure out their timeout */
+	if (chan->whentohangup) {
+		time(&now);
+		if ((whentohangup = chan->whentohangup - now) < 1) {
+			/* They should already be hungup! */
+			chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
+			ast_channel_unlock(chan);
+			return NULL;
+		}
+		/* If this value is smaller then the current one... make it priority */
+		whentohangup *= 1000;
+		if (rms > whentohangup)
+			rms = whentohangup;
+	}
+
+	ast_channel_unlock(chan);
+
+	/* Time to make this channel block... */
+	CHECK_BLOCKING(chan);
+
+	if (*ms > 0)
+		start = ast_tvnow();
+
+	/* We don't have to add any file descriptors... they are already added, we just have to wait! */
+	res = epoll_wait(chan->epfd, ev, 1, rms);
+
+	/* Stop blocking */
+	ast_clear_flag(chan, AST_FLAG_BLOCKING);
+
+	/* Simulate a timeout if we were interrupted */
+	if (res < 0) {
+		if (errno != EINTR)
+			*ms = -1;
+		return NULL;
+	}
+
+	/* If this channel has a timeout see if it expired */
+	if (chan->whentohangup) {
+		time(&now);
+		if (now >= chan->whentohangup) {
+			chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
+			winner = chan;
+		}
+	}
+
+	/* No fd ready, reset timeout and be done for now */
+	if (!res) {
+		*ms = 0;
+		return winner;
+	}
+
+	/* See what events are pending */
+	aed = ev[0].data.ptr;
+	chan->fdno = aed->which;
+	if (ev[0].events & EPOLLPRI)
+		ast_set_flag(chan, AST_FLAG_EXCEPTION);
+	else
+		ast_clear_flag(chan, AST_FLAG_EXCEPTION);
+
+	if (*ms > 0) {
+		*ms -= ast_tvdiff_ms(ast_tvnow(), start);
+		if (*ms < 0)
+			*ms = 0;
+	}
+
+	return chan;
+}
+
+static struct ast_channel *ast_waitfor_nandfds_complex(struct ast_channel **c, int n, int *ms)
+{
+	struct timeval start = { 0 , 0 };
+	int res = 0, i;
+	struct epoll_event ev[25] = { { 0, } };
+	long whentohangup = 0, diff, rms = *ms;
+	time_t now;
+	struct ast_channel *winner = NULL;
+
+	for (i = 0; i < n; i++) {
+		ast_channel_lock(c[i]);
+		if (c[i]->masq && ast_do_masquerade(c[i])) {
+			ast_log(LOG_WARNING, "Masquerade failed\n");
+			*ms = -1;
+			ast_channel_unlock(c[i]);
+			return NULL;
+		}
+		if (c[i]->whentohangup) {
+			if (!whentohangup)
+				time(&now);
+			if ((diff = c[i]->whentohangup - now) < 1) {
+				c[i]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
+				ast_channel_unlock(c[i]);
+				return c[i];
+			}
+			if (!whentohangup || (diff < whentohangup))
+				whentohangup = diff;
+		}
+		ast_channel_unlock(c[i]);
+		CHECK_BLOCKING(c[i]);
+	}
+
+	rms = *ms;
+	if (whentohangup) {
+		rms = whentohangup * 1000;
+		if (*ms >= 0 && *ms < rms)
+			rms = *ms;
+	}
+
+	if (*ms > 0)
+		start = ast_tvnow();
+
+	res = epoll_wait(c[0]->epfd, ev, 25, rms);
+
+	for (i = 0; i < n; i++)
+		ast_clear_flag(c[i], AST_FLAG_BLOCKING);
+
+	if (res < 0) {
+		if (errno != EINTR)
+			*ms = -1;
+		return NULL;
+	}
+
+	if (whentohangup) {
+		time(&now);
+		for (i = 0; i < n; i++) {
+			if (c[i]->whentohangup && now >= c[i]->whentohangup) {
+				c[i]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
+				if (!winner)
+					winner = c[i];
+			}
+		}
+	}
+
+	if (!res) {
+		*ms = 0;
+		return winner;
+	}
+
+	for (i = 0; i < 25; i++) {
+		struct ast_epoll_data *aed = ev[i].data.ptr;
+
+		if (!ev[i].events || !aed)
+			continue;
+
+		winner = aed->chan;
+		if (ev[i].events & EPOLLPRI)
+			ast_set_flag(winner, AST_FLAG_EXCEPTION);
+		else
+			ast_clear_flag(winner, AST_FLAG_EXCEPTION);
+		winner->fdno = aed->which;
+	}
+
+	if (*ms > 0) {
+		*ms -= ast_tvdiff_ms(ast_tvnow(), start);
+		if (*ms < 0)
+			*ms = 0;
+	}
+
+	return winner;
+}
+
+struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds,
+					int *exception, int *outfd, int *ms)
+{
+	/* If no epoll file descriptor is available resort to classic nandfds */
+	if (!n || nfds || c[0]->epfd == -1)
+		return ast_waitfor_nandfds_classic(c, n, fds, nfds, exception, outfd, ms);
+	else if (!nfds && n == 1)
+		return ast_waitfor_nandfds_simple(c[0], ms);
+	else
+		return ast_waitfor_nandfds_complex(c, n, ms);
+}
+#endif
 
 struct ast_channel *ast_waitfor_n(struct ast_channel **c, int n, int *ms)
 {
@@ -3259,7 +3557,7 @@
 	/* Copy the FD's other than the generator fd */
 	for (x = 0; x < AST_MAX_FDS; x++) {
 		if (x != AST_GENERATOR_FD)
-			original->fds[x] = clone->fds[x];
+			ast_channel_set_fd(original, x, clone->fds[x]);
 	}
 
 	ast_app_group_update(clone, original);
@@ -3290,7 +3588,7 @@
 	clone->cid = tmpcid;
 	
 	/* Restore original timing file descriptor */
-	original->fds[AST_TIMING_FD] = original->timingfd;
+	ast_channel_set_fd(original, AST_TIMING_FD, original->timingfd);
 	
 	/* Our native formats are different now */
 	original->nativeformats = clone->nativeformats;
@@ -3486,6 +3784,8 @@
 
 	/* Check the need of a jitterbuffer for each channel */
 	jb_in_use = ast_jb_do_usecheck(c0, c1);
+
+	ast_poll_channel_add(c0, c1);
 
 	for (;;) {
 		struct ast_channel *who, *other;
@@ -3591,11 +3891,16 @@
 		/* XXX do we want to pass on also frames not matched above ? */
 		ast_frfree(f);
 
+#ifndef HAVE_EPOLL
 		/* Swap who gets priority */
 		cs[2] = cs[0];
 		cs[0] = cs[1];
 		cs[1] = cs[2];
-	}
+#endif
+	}
+
+	ast_poll_channel_del(c0, c1);
+
 	return res;
 }
 

Modified: trunk/main/rtp.c
URL: http://svn.digium.com/view/asterisk/trunk/main/rtp.c?view=diff&rev=78683&r1=78682&r2=78683
==============================================================================
--- trunk/main/rtp.c (original)
+++ trunk/main/rtp.c Wed Aug  8 16:44:58 2007
@@ -3212,6 +3212,8 @@
 	ast_channel_unlock(c0);
 	ast_channel_unlock(c1);
 
+	ast_poll_channel_add(c0, c1);
+
 	/* Throw our channels into the structure and enter the loop */
 	cs[0] = c0;
 	cs[1] = c1;
@@ -3228,6 +3230,7 @@
 			if (c1->tech_pvt == pvt1)
 				if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
 					ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
+			ast_poll_channel_del(c0, c1);
 			return AST_BRIDGE_RETRY;
 		}
 
@@ -3313,6 +3316,7 @@
 			if (c1->tech_pvt == pvt1)
 				if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
 					ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
+			ast_poll_channel_del(c0, c1);
 			return AST_BRIDGE_COMPLETE;
 		} else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
 			if ((fr->subclass == AST_CONTROL_HOLD) ||
@@ -3353,10 +3357,14 @@
 			ast_frfree(fr);
 		}
 		/* Swap priority */
+#ifndef HAVE_EPOLL
 		cs[2] = cs[0];
 		cs[0] = cs[1];
 		cs[1] = cs[2];
-	}
+#endif
+	}
+
+	ast_poll_channel_del(c0, c1);
 
 	if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
 		ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
@@ -3487,6 +3495,8 @@
 	/* Now let go of the channel locks and be on our way */
 	ast_channel_unlock(c0);
 	ast_channel_unlock(c1);
+
+	ast_poll_channel_add(c0, c1);
 
 	/* Go into a loop forwarding frames until we don't need to anymore */
 	cs[0] = c0;
@@ -3591,6 +3601,8 @@
 	p2p_set_bridge(p0, NULL);
 	p2p_set_bridge(p1, NULL);
 
+	ast_poll_channel_del(c0, c1);
+
 	return res;
 }
 




More information about the asterisk-commits mailing list