[asterisk-commits] branch oej/res_auth r22315 - in /team/oej/res_auth: ./ build_tools/ channels/...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Mon Apr 24 13:28:58 MST 2006


Author: oej
Date: Mon Apr 24 15:28:57 2006
New Revision: 22315

URL: http://svn.digium.com/view/asterisk?rev=22315&view=rev
Log:
Moving on...

Modified:
    team/oej/res_auth/   (props changed)
    team/oej/res_auth/build_tools/make_defaults_h
    team/oej/res_auth/cdr.c
    team/oej/res_auth/channel.c
    team/oej/res_auth/channels/chan_alsa.c
    team/oej/res_auth/channels/chan_features.c
    team/oej/res_auth/channels/chan_local.c
    team/oej/res_auth/channels/chan_mgcp.c
    team/oej/res_auth/channels/chan_misdn.c
    team/oej/res_auth/channels/chan_nbs.c
    team/oej/res_auth/channels/chan_phone.c
    team/oej/res_auth/channels/chan_skinny.c
    team/oej/res_auth/channels/chan_vpb.c
    team/oej/res_auth/channels/chan_zap.c
    team/oej/res_auth/loader.c
    team/oej/res_auth/pbx/pbx_ael.c
    team/oej/res_auth/pbx/pbx_config.c
    team/oej/res_auth/pbx/pbx_dundi.c
    team/oej/res_auth/pbx/pbx_loopback.c
    team/oej/res_auth/pbx/pbx_realtime.c
    team/oej/res_auth/pbx/pbx_spool.c

Propchange: team/oej/res_auth/
------------------------------------------------------------------------------
    automerge = http://edvina.net/training/

Modified: team/oej/res_auth/build_tools/make_defaults_h
URL: http://svn.digium.com/view/asterisk/team/oej/res_auth/build_tools/make_defaults_h?rev=22315&r1=22314&r2=22315&view=diff
==============================================================================
--- team/oej/res_auth/build_tools/make_defaults_h (original)
+++ team/oej/res_auth/build_tools/make_defaults_h Mon Apr 24 15:28:57 2006
@@ -11,6 +11,7 @@
 #define AST_MODULE_DIR "${INSTALL_PATH}${MODULES_DIR}"
 #define AST_SPOOL_DIR  "${INSTALL_PATH}${ASTSPOOLDIR}"
 #define AST_VAR_DIR    "${INSTALL_PATH}${ASTVARLIBDIR}"
+#define AST_DATA_DIR   "${INSTALL_PATH}${ASTDATADIR}"
 #define AST_LOG_DIR    "${INSTALL_PATH}${ASTLOGDIR}"
 #define AST_AGI_DIR    "${INSTALL_PATH}${AGI_DIR}"
 #define AST_KEY_DIR    "${INSTALL_PATH}${ASTVARLIBDIR}/keys"
@@ -19,7 +20,7 @@
 
 #define AST_CONFIG_FILE "${INSTALL_PATH}${ASTCONFPATH}"
 
-#define AST_SOUNDS     "${INSTALL_PATH}${ASTVARLIBDIR}/sounds"
-#define AST_IMAGES     "${INSTALL_PATH}${ASTVARLIBDIR}/images"
+#define AST_SOUNDS     "${INSTALL_PATH}${ASTDATADIR}/sounds"
+#define AST_IMAGES     "${INSTALL_PATH}${ASTDATADIR}/images"
 
 END

Modified: team/oej/res_auth/cdr.c
URL: http://svn.digium.com/view/asterisk/team/oej/res_auth/cdr.c?rev=22315&r1=22314&r2=22315&view=diff
==============================================================================
--- team/oej/res_auth/cdr.c (original)
+++ team/oej/res_auth/cdr.c Mon Apr 24 15:28:57 2006
@@ -53,7 +53,7 @@
 #include "asterisk/sched.h"
 #include "asterisk/config.h"
 #include "asterisk/cli.h"
-#include "asterisk/module.h"
+// XXX #include "asterisk/module.h"
 #include "asterisk/stringfields.h"
 
 /*! Default AMA flag for billing records (CDR's) */
@@ -536,35 +536,37 @@
 	}
 }
 
+/* set cid info for one record */
+static void set_one_cid(struct ast_cdr *cdr, struct ast_channel *c)
+{
+	/* Grab source from ANI or normal Caller*ID */
+	const char *num = S_OR(c->cid.cid_ani, c->cid.cid_num);
+	
+	if (!ast_strlen_zero(c->cid.cid_name)) {
+		if (!ast_strlen_zero(num))	/* both name and number */
+			snprintf(cdr->clid, sizeof(cdr->clid), "\"%s\" <%s>", c->cid.cid_name, num);
+		else				/* only name */
+			ast_copy_string(cdr->clid, c->cid.cid_name, sizeof(cdr->clid));
+	} else if (!ast_strlen_zero(num)) {	/* only number */
+		ast_copy_string(cdr->clid, num, sizeof(cdr->clid));
+	} else {				/* nothing known */
+		cdr->clid[0] = '\0';
+	}
+	ast_copy_string(cdr->src, S_OR(num, ""), sizeof(cdr->src));
+
+}
 int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *c)
 {
-	char tmp[AST_MAX_EXTENSION] = "";
-
 	for (; cdr; cdr = cdr->next) {
-		if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
-			/* Grab source from ANI or normal Caller*ID */
-			char *num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num; /* XXX ast_strlen_zero ? */
-			
-			if (c->cid.cid_name && num)
-				snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num);
-			else if (c->cid.cid_name)
-				ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp));
-			else if (num)
-				ast_copy_string(tmp, num, sizeof(tmp));
-			ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid));
-			ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src));
-		}
-	}
-
-	return 0;
-}
-
+		if (ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
+			set_one_cid(cdr, c);
+	}
+	return 0;
+}
 
 int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
 {
 	char *chan;
-	char *num;
-	char tmp[AST_MAX_EXTENSION] = "";
 
 	for ( ; cdr ; cdr = cdr->next) {
 		if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
@@ -572,17 +574,7 @@
 			if (!ast_strlen_zero(cdr->channel)) 
 				ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan); 
 			ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel));
-			/* Grab source from ANI or normal Caller*ID */
-			num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num;
-			
-			if (c->cid.cid_name && num)
-				snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num);
-			else if (c->cid.cid_name)
-				ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp));
-			else if (num)
-				ast_copy_string(tmp, num, sizeof(tmp));
-			ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid));
-			ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src));
+			set_one_cid(cdr, c);
 
 			cdr->disposition = (c->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NOANSWER;
 			cdr->amaflags = c->amaflags ? c->amaflags :  ast_default_amaflags;
@@ -608,10 +600,7 @@
 			cdr->disposition = AST_CDR_FAILED;
 		} else
 			cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
-		if (!ast_tvzero(cdr->answer))
-			cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec;
-		else
-			cdr->billsec = 0;
+		cdr->billsec = ast_tvzero(cdr->answer) ? 0 : cdr->end.tv_sec - cdr->answer.tv_sec;
 	}
 }
 
@@ -697,21 +686,10 @@
 int ast_cdr_update(struct ast_channel *c)
 {
 	struct ast_cdr *cdr = c->cdr;
-	char *num;
-	char tmp[AST_MAX_EXTENSION] = "";
 
 	for ( ; cdr ; cdr = cdr->next) {
 		if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
-			num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num;
-			
-			if (c->cid.cid_name && num)
-				snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num);
-			else if (c->cid.cid_name)
-				ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp));
-			else if (num)
-				ast_copy_string(tmp, num, sizeof(tmp));
-			ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid));
-			ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src));
+			set_one_cid(cdr, c);
 
 			/* Copy account code et-al */	
 			ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));

Modified: team/oej/res_auth/channel.c
URL: http://svn.digium.com/view/asterisk/team/oej/res_auth/channel.c?rev=22315&r1=22314&r2=22315&view=diff
==============================================================================
--- team/oej/res_auth/channel.c (original)
+++ team/oej/res_auth/channel.c Mon Apr 24 15:28:57 2006
@@ -401,7 +401,7 @@
 		}
 	}
 	
-	if (!(chan = ast_malloc(sizeof(*chan)))) {
+	if (!(chan = ast_calloc(1, sizeof(*chan)))) {
 		AST_LIST_UNLOCK(&channels);
 		return -1;
 	}
@@ -793,60 +793,48 @@
 					       const char *context, const char *exten)
 {
 	const char *msg = prev ? "deadlock" : "initial deadlock";
-	int retries, done;
+	int retries;
 	struct ast_channel *c;
 
 	for (retries = 0; retries < 10; retries++) {
+		int done;
 		AST_LIST_LOCK(&channels);
 		AST_LIST_TRAVERSE(&channels, c, chan_list) {
-			if (!prev) {
-				/* want head of list */
-				if (!name && !exten)
-					break;
-				if (name) {
-					/* want match by full name */
-					if (!namelen) {
-						if (!strcasecmp(c->name, name))
-							break;
-						else
-							continue;
-					}
-					/* want match by name prefix */
-					if (!strncasecmp(c->name, name, namelen))
-						break;
-				} else if (exten) {
-					/* want match by context and exten */
-					if (context && (strcasecmp(c->context, context) &&
-							strcasecmp(c->macrocontext, context)))
-						continue;
-					/* match by exten */
-					if (strcasecmp(c->exten, exten) &&
-					    strcasecmp(c->macroexten, exten))
-						continue;
-					else
-						break;
-				}
-			} else if (c == prev) { /* found, return c->next */
+			if (prev) {	/* look for next item */
+				if (c != prev)	/* not this one */
+					continue;
+				/* found, prepare to return c->next */
 				c = AST_LIST_NEXT(c, chan_list);
-				break;
+			} else if (name) { /* want match by name */
+				if ( (!namelen && strcasecmp(c->name, name)) ||
+				     (namelen && strncasecmp(c->name, name, namelen)) )
+					continue;	/* name match failed */
+			} else if (exten) {
+				if (context && strcasecmp(c->context, context) &&
+						strcasecmp(c->macrocontext, context))
+					continue;	/* context match failed */
+				if (strcasecmp(c->exten, exten) &&
+						strcasecmp(c->macroexten, exten))
+					continue;	/* exten match failed */
 			}
+			/* if we get here, c points to the desired record */
+			break;
 		}
 		/* exit if chan not found or mutex acquired successfully */
-		done = (c == NULL) || (ast_mutex_trylock(&c->lock) == 0);
-		/* this is slightly unsafe, as we _should_ hold the lock to access c->name */
-		if (!done && c)
-			ast_log(LOG_DEBUG, "Avoiding %s for '%s'\n", msg, c->name);
+		done = c == NULL || ast_mutex_trylock(&c->lock) == 0;
+		if (!done)
+			ast_log(LOG_DEBUG, "Avoiding %s for channel '%p'\n", msg, c);
 		AST_LIST_UNLOCK(&channels);
 		if (done)
 			return c;
-		usleep(1);
+		usleep(1);	/* give other threads a chance before retrying */
 	}
 	/*
  	 * c is surely not null, but we don't have the lock so cannot
 	 * access c->name
 	 */
-	ast_log(LOG_WARNING, "Avoided %s for '%p', %d retries!\n",
-		msg, c, retries);
+	ast_log(LOG_WARNING, "Failure, could not lock '%p' after %d retries!\n",
+		c, retries);
 
 	return NULL;
 }
@@ -1270,13 +1258,15 @@
 {
 	struct ast_frame *translated_frame = NULL;
 	struct ast_channel_spy *spy;
-	struct ast_channel_spy_queue *queue;
 	struct channel_spy_trans *trans;
-	struct ast_frame *last;
 
 	trans = (dir == SPY_READ) ? &chan->spies->read_translator : &chan->spies->write_translator;
 
 	AST_LIST_TRAVERSE(&chan->spies->list, spy, list) {
+		struct ast_frame *last;
+		struct ast_frame *f1;	/* the frame to append */
+		struct ast_channel_spy_queue *queue;
+
 		ast_mutex_lock(&spy->lock);
 
 		queue = (dir == SPY_READ) ? &spy->read_queue : &spy->write_queue;
@@ -1306,12 +1296,7 @@
 					break;
 				}
 			}
-
-			for (last = queue->head; last && last->next; last = last->next);
-			if (last)
-				last->next = ast_frdup(translated_frame);
-			else
-				queue->head = ast_frdup(translated_frame);
+			f1 = translated_frame;
 		} else {
 			if (f->subclass != queue->format) {
 				ast_log(LOG_WARNING, "Spy '%s' on channel '%s' wants format '%s', but frame is '%s', dropping\n",
@@ -1320,13 +1305,17 @@
 				ast_mutex_unlock(&spy->lock);
 				continue;
 			}
-
-			for (last = queue->head; last && last->next; last = last->next);
-			if (last)
-				last->next = ast_frdup(f);
-			else
-				queue->head = ast_frdup(f);
-		}
+			f1 = f;
+		}
+		/* duplicate and append f1 to the tail */
+		f1 = ast_frdup(f1);
+
+		for (last = queue->head; last && last->next; last = last->next)
+			;
+		if (last)
+			last->next = f1;
+		else
+			queue->head = f1;
 
 		queue->samples += f->samples;
 
@@ -1408,7 +1397,7 @@
 
 	/* Don't actually hang up a channel that will masquerade as someone else, or
 	   if someone is going to masquerade as us */
-	ast_mutex_lock(&chan->lock);
+	ast_channel_lock(chan);
 
 	detach_spies(chan);		/* get rid of spies */
 
@@ -1419,14 +1408,14 @@
 
 	if (chan->masq) {
 		ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name);
-		ast_mutex_unlock(&chan->lock);
+		ast_channel_unlock(chan);
 		return 0;
 	}
 	/* If this channel is one which will be masqueraded into something,
 	   mark it as a zombie already, so we know to free it later */
 	if (chan->masqr) {
 		ast_set_flag(chan, AST_FLAG_ZOMBIE);
-		ast_mutex_unlock(&chan->lock);
+		ast_channel_unlock(chan);
 		return 0;
 	}
 	free_translation(chan);
@@ -1464,7 +1453,7 @@
 			ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name);
 	}
 			
-	ast_mutex_unlock(&chan->lock);
+	ast_channel_unlock(chan);
 	manager_event(EVENT_FLAG_CALL, "Hangup",
 			"Channel: %s\r\n"
 			"Uniqueid: %s\r\n"
@@ -1482,7 +1471,7 @@
 int ast_answer(struct ast_channel *chan)
 {
 	int res = 0;
-	ast_mutex_lock(&chan->lock);
+	ast_channel_lock(chan);
 	/* Stop if we're a zombie or need a soft hangup */
 	if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) {
 		ast_mutex_unlock(&chan->lock);
@@ -1496,16 +1485,14 @@
 		ast_setstate(chan, AST_STATE_UP);
 		if (chan->cdr)
 			ast_cdr_answer(chan->cdr);
-		ast_mutex_unlock(&chan->lock);
-		return res;
 		break;
 	case AST_STATE_UP:
 		if (chan->cdr)
 			ast_cdr_answer(chan->cdr);
 		break;
 	}
-	ast_mutex_unlock(&chan->lock);
-	return 0;
+	ast_channel_unlock(chan);
+	return res;
 }
 
 void ast_deactivate_generator(struct ast_channel *chan)
@@ -1546,7 +1533,7 @@
 {
 	int res = 0;
 
-	ast_mutex_lock(&chan->lock);
+	ast_channel_lock(chan);
 
 	if (chan->generatordata) {
 		if (chan->generator && chan->generator->release)
@@ -1564,7 +1551,7 @@
 		chan->generator = gen;
 	}
 
-	ast_mutex_unlock(&chan->lock);
+	ast_channel_unlock(chan);
 
 	return res;
 }
@@ -1609,12 +1596,12 @@
 	
 	/* Perform any pending masquerades */
 	for (x=0; x < n; x++) {
-		ast_mutex_lock(&c[x]->lock);
+		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_mutex_unlock(&c[x]->lock);
+				ast_channel_unlock(c[x]);
 				return NULL;
 			}
 		}
@@ -1625,13 +1612,13 @@
 			if (diff < 1) {
 				/* Should already be hungup */
 				c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
-				ast_mutex_unlock(&c[x]->lock);
+				ast_channel_unlock(c[x]);
 				return c[x];
 			}
 			if (!whentohangup || (diff < whentohangup))
 				whentohangup = diff;
 		}
-		ast_mutex_unlock(&c[x]->lock);
+		ast_channel_unlock(c[x]);
 	}
 	/* Wait full interval */
 	rms = *ms;
@@ -1735,7 +1722,7 @@
 
 int ast_waitfor(struct ast_channel *c, int ms)
 {
-	int oldms = ms;
+	int oldms = ms;	/* -1 if no timeout */
 
 	ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms);
 	if ((ms < 0) && (oldms < 0))
@@ -1743,33 +1730,10 @@
 	return ms;
 }
 
+/* XXX never to be called with ms = -1 */
 int ast_waitfordigit(struct ast_channel *c, int ms)
 {
-	/* XXX Should I be merged with waitfordigit_full XXX */
-	struct ast_frame *f;
-	int result = 0;
-
-	/* Stop if we're a zombie or need a soft hangup */
-	if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c))
-		return -1;
-
-	/* Wait for a digit, no more than ms milliseconds total. */
-	while(ms && !result) {
-		ms = ast_waitfor(c, ms);
-		if (ms < 0) /* Error */
-			result = -1;
-		else if (ms > 0) {
-			/* Read something */
-			f = ast_read(c);
-			if (f) {
-				if (f->frametype == AST_FRAME_DTMF)
-					result = f->subclass;
-				ast_frfree(f);
-			} else
-				result = -1;
-		}
-	}
-	return result;
+	return ast_waitfordigit_full(c, ms, -1, -1);
 }
 
 int ast_settimeout(struct ast_channel *c, int samples, int (*func)(void *data), void *data)
@@ -1792,19 +1756,18 @@
 
 int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int cmdfd)
 {
-	struct ast_frame *f;
-	struct ast_channel *rchan;
-	int outfd;
-	int res;
 
 	/* Stop if we're a zombie or need a soft hangup */
 	if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c))
 		return -1;
 	/* Wait for a digit, no more than ms milliseconds total. */
-	while(ms) {
+	while (ms) {
+		struct ast_channel *rchan;
+		int outfd;
+
 		errno = 0;
 		rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
-		if ((!rchan) && (outfd < 0) && (ms)) {
+		if (!rchan && outfd < 0 && ms) {
 			if (errno == 0 || errno == EINTR)
 				continue;
 			ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
@@ -1813,10 +1776,10 @@
 			/* The FD we were watching has something waiting */
 			return 1;
 		} else if (rchan) {
-			f = ast_read(c);
-			if(!f) {
+			int res;
+			struct ast_frame *f = ast_read(c);
+			if (!f)
 				return -1;
-			}
 
 			switch(f->frametype) {
 			case AST_FRAME_DTMF:
@@ -1849,31 +1812,28 @@
 
 static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
 {
-	struct ast_frame *f = NULL;
+	struct ast_frame *f = NULL;	/* the return value */
 	int blah;
 	int prestate;
-#ifdef ZAPTEL_OPTIMIZATIONS
-	int (*func)(void *);
-	void *data;
-	int res;
-#endif
-	ast_mutex_lock(&chan->lock);
+
+	/* this function is very long so make sure there is only one return
+	 * point at the end (there is only one exception to this).
+	 */
+	ast_channel_lock(chan);
 	if (chan->masq) {
 		if (ast_do_masquerade(chan)) {
 			ast_log(LOG_WARNING, "Failed to perform masquerade\n");
-			f = NULL;
-		} else
+		} else {
 			f =  &ast_null_frame;
-		ast_mutex_unlock(&chan->lock);
-		return f;
+		}
+		goto done;
 	}
 
 	/* Stop if we're a zombie or need a soft hangup */
 	if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) {
 		if (chan->generator)
 			ast_deactivate_generator(chan);
-		ast_mutex_unlock(&chan->lock);
-		return NULL;
+		goto done;
 	}
 	prestate = chan->_state;
 
@@ -1881,19 +1841,21 @@
 		/* We have DTMF that has been deferred.  Return it now */
 		chan->dtmff.frametype = AST_FRAME_DTMF;
 		chan->dtmff.subclass = chan->dtmfq[0];
-		/* Drop first digit */
+		/* Drop first digit from the buffer */
 		memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1);
-		ast_mutex_unlock(&chan->lock);
-		return &chan->dtmff;
+		f = &chan->dtmff;
+		goto done;
 	}
 	
 	/* 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) {
+	if (chan->alertpipe[0] > -1)
 		read(chan->alertpipe[0], &blah, sizeof(blah));
-	}
+
 #ifdef ZAPTEL_OPTIMIZATIONS
 	if (chan->timingfd > -1 && chan->fdno == AST_TIMING_FD && ast_test_flag(chan, AST_FLAG_EXCEPTION)) {
+		int res;
+
 		ast_clear_flag(chan, AST_FLAG_EXCEPTION);
 		blah = -1;
 		/* IF we can't get event, assume it's an expired as-per the old interface */
@@ -1902,48 +1864,42 @@
 			blah = ZT_EVENT_TIMER_EXPIRED;
 
 		if (blah == ZT_EVENT_TIMER_PING) {
-#if 0
-			ast_log(LOG_NOTICE, "Oooh, there's a PING!\n");
-#endif			
 			if (!chan->readq || !chan->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);
-			if (func) {
-#if 0
-				ast_log(LOG_DEBUG, "Calling private function\n");
-#endif			
+			if (chan->timingfunc) {
+				/* save a copy of func/data before unlocking the channel */
+				int (*func)(void *) = chan->timingfunc;
+				void *data = chan->timingdata;
+				ast_channel_unlock(chan);
 				func(data);
 			} else {
 				blah = 0;
-				ast_mutex_lock(&chan->lock);
 				ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah);
 				chan->timingdata = NULL;
-				ast_mutex_unlock(&chan->lock);
+				ast_channel_unlock(chan);
 			}
+			/* cannot 'goto done' because the channel is already unlocked */
 			return &ast_null_frame;
 		} else
 			ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name);
 	} else
 #endif
-	/* Check for AST_GENERATOR_FD if not null.  If so, call generator with -1
-	   arguments now so it can do whatever it needs to. */
 	if (chan->fds[AST_GENERATOR_FD] > -1 && chan->fdno == 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.
+		 */
 		void *tmp = chan->generatordata;
 		chan->generatordata = NULL;     /* reset to let ast_write get through */
 		chan->generator->generate(chan, tmp, -1, -1);
 		chan->generatordata = tmp;
-		return &ast_null_frame;
+		f = &ast_null_frame;
+		goto done;
 	}
 
 	/* Check for pending read queue */
@@ -1952,7 +1908,7 @@
 		chan->readq = f->next;
 		f->next = NULL;
 		/* Interpret hangup and return NULL */
-		if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
+		if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
 			ast_frfree(f);
 			f = NULL;
 		}
@@ -1967,12 +1923,10 @@
 			}
 			/* Clear the exception flag */
 			ast_clear_flag(chan, AST_FLAG_EXCEPTION);
-		} else {
-			if (chan->tech->read)
-				f = chan->tech->read(chan);
-			else
-				ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
-		}
+		} else if (chan->tech->read)
+			f = chan->tech->read(chan);
+		else
+			ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
 	}
 
 	if (f) {
@@ -2051,17 +2005,14 @@
 					}
 				}
 
-				if (chan->readtrans) {
-					if (!(f = ast_translate(chan->readtrans, f, 1)))
-						f = &ast_null_frame;
-				}
+				if (chan->readtrans && (f = ast_translate(chan->readtrans, f, 1)) == NULL)
+					f = &ast_null_frame;
 
 				/* Run generator sitting on the line if timing device not available
 				* and synchronous generation of outgoing frames is necessary       */
 				if (chan->generatordata &&  !ast_internal_timing_enabled(chan)) {
-					void *tmp;
+					void *tmp = chan->generatordata;
 					int res;
-					int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
 
 					if (chan->timingfunc) {
 						if (option_debug > 1)
@@ -2069,10 +2020,8 @@
 						ast_settimeout(chan, 0, NULL, NULL);
 					}
 
-					tmp = chan->generatordata;
-					chan->generatordata = NULL;
-					generate = chan->generator->generate;
-					res = generate(chan, tmp, f->datalen, f->samples);
+					chan->generatordata = NULL;	/* reset, to let writes go through */
+					res = chan->generator->generate(chan, tmp, f->datalen, f->samples);
 					chan->generatordata = tmp;
 					if (res) {
 						if (option_debug > 1)
@@ -2100,14 +2049,12 @@
 	}
 
 	/* High bit prints debugging */
-	if (chan->fin & 0x80000000)
+	if (chan->fin & DEBUGCHAN_FLAG)
 		ast_frame_dump(chan->name, f, "<<");
-	if ((chan->fin & 0x7fffffff) == 0x7fffffff)
-		chan->fin &= 0x80000000;
-	else
-		chan->fin++;
+	chan->fin = FRAMECOUNT_INC(chan->fin);
+
+done:
 	ast_mutex_unlock(&chan->lock);
-
 	return f;
 }
 
@@ -2133,21 +2080,23 @@
 {
 	int res = -1;
 
-	ast_mutex_lock(&chan->lock);
+	ast_channel_lock(chan);
 	/* Stop if we're a zombie or need a soft hangup */
 	if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) {
-		ast_mutex_unlock(&chan->lock);
+		ast_channel_unlock(chan);
 		return -1;
 	}
 	if (chan->tech->indicate)
 		res = chan->tech->indicate(chan, condition);
-	ast_mutex_unlock(&chan->lock);
+	ast_channel_unlock(chan);
 	if (!chan->tech->indicate || res) {
 		/*
 		 * Device does not support (that) indication, lets fake
 		 * it by doing our own tone generation. (PM2002)
 		 */
-		if (condition >= 0) {
+		if (condition < 0)
+			ast_playtones_stop(chan);
+		else {
 			const struct tone_zone_sound *ts = NULL;
 			switch (condition) {
 			case AST_CONTROL_RINGING:
@@ -2180,7 +2129,6 @@
 				res = -1;
 			}
 		}
-		else ast_playtones_stop(chan);
 	}
 	return res;
 }
@@ -2318,34 +2266,31 @@
 {
 	int res = -1;
 	struct ast_frame *f = NULL;
+
 	/* Stop if we're a zombie or need a soft hangup */
-	ast_mutex_lock(&chan->lock);
-	if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan))  {
-		ast_mutex_unlock(&chan->lock);
-		return -1;
-	}
+	ast_channel_lock(chan);
+	if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan))
+		goto done;
+
 	/* Handle any pending masquerades */
-	if (chan->masq) {
-		if (ast_do_masquerade(chan)) {
-			ast_log(LOG_WARNING, "Failed to perform masquerade\n");
-			ast_mutex_unlock(&chan->lock);
-			return -1;
-		}
+	if (chan->masq && ast_do_masquerade(chan)) {
+		ast_log(LOG_WARNING, "Failed to perform masquerade\n");
+		goto done;
 	}
 	if (chan->masqr) {
-		ast_mutex_unlock(&chan->lock);
-		return 0;
+		res = 0;	/* XXX explain, why 0 ? */
+		goto done;
 	}
 	if (chan->generatordata) {
 		if (ast_test_flag(chan, AST_FLAG_WRITE_INT))
 			ast_deactivate_generator(chan);
 		else {
-			ast_mutex_unlock(&chan->lock);
-			return 0;
+			res = 0;	/* XXX explain, why 0 ? */
+			goto done;
 		}
 	}
 	/* High bit prints debugging */
-	if (chan->fout & 0x80000000)
+	if (chan->fout & DEBUGCHAN_FLAG)
 		ast_frame_dump(chan->name, fr, ">>");
 	CHECK_BLOCKING(chan);
 	switch(fr->frametype) {
@@ -2354,98 +2299,90 @@
 		ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
 		break;
 	case AST_FRAME_DTMF_BEGIN:
-		if (chan->tech->send_digit_begin)
-			res = chan->tech->send_digit_begin(chan, fr->subclass);
-		else
-			res = 0;
+		res = (chan->tech->send_digit_begin == NULL) ? 0 :
+			chan->tech->send_digit_begin(chan, fr->subclass);
 		break;
 	case AST_FRAME_DTMF_END:
-		if (chan->tech->send_digit_end)
-			res = chan->tech->send_digit_end(chan);
-		else
-			res = 0;
+		res = (chan->tech->send_digit_end == NULL) ? 0 :
+			chan->tech->send_digit_end(chan);
 		break;
 	case AST_FRAME_DTMF:
 		ast_clear_flag(chan, AST_FLAG_BLOCKING);
-		ast_mutex_unlock(&chan->lock);
+		ast_channel_unlock(chan);
 		res = do_senddigit(chan,fr->subclass);
-		ast_mutex_lock(&chan->lock);
+		ast_channel_lock(chan);
 		CHECK_BLOCKING(chan);
 		break;
 	case AST_FRAME_TEXT:
-		if (chan->tech->send_text)
-			res = chan->tech->send_text(chan, (char *) fr->data);
-		else
-			res = 0;
+		res = (chan->tech->send_text == NULL) ? 0 :
+			chan->tech->send_text(chan, (char *) fr->data);
 		break;
 	case AST_FRAME_HTML:
-		if (chan->tech->send_html)
-			res = chan->tech->send_html(chan, fr->subclass, (char *) fr->data, fr->datalen);
-		else
-			res = 0;
+		res = (chan->tech->send_html == NULL) ? 0 :
+			chan->tech->send_html(chan, fr->subclass, (char *) fr->data, fr->datalen);
 		break;
 	case AST_FRAME_VIDEO:
 		/* XXX Handle translation of video codecs one day XXX */
-		if (chan->tech->write_video)
-			res = chan->tech->write_video(chan, fr);
-		else
-			res = 0;
+		res = (chan->tech->write_video == NULL) ? 0 :
+			chan->tech->write_video(chan, fr);
 		break;
 	case AST_FRAME_VOICE:
-		if (chan->tech->write) {
-			/* Bypass translator if we're writing format in the raw write format.  This
-			   allows mixing of native / non-native formats */
-			if (fr->subclass == chan->rawwriteformat)
-				f = fr;
-			else
-				f = (chan->writetrans) ? ast_translate(chan->writetrans, fr, 0) : fr;
-			if (f) {
-				if (chan->spies)
-					queue_frame_to_spies(chan, f, SPY_WRITE);
-
-				if (chan->monitor && chan->monitor->write_stream) {
+		if (chan->tech->write == NULL)
+			break;	/*! \todo XXX should return 0 maybe ? */
+
+		/* Bypass translator if we're writing format in the raw write format.  This
+		   allows mixing of native / non-native formats */
+		if (fr->subclass == chan->rawwriteformat)
+			f = fr;
+		else
+			f = (chan->writetrans) ? ast_translate(chan->writetrans, fr, 0) : fr;
+		if (f == NULL) {
+			res = 0;
+		} else {
+			if (chan->spies)
+				queue_frame_to_spies(chan, f, SPY_WRITE);
+
+			if (chan->monitor && chan->monitor->write_stream) {
+				/* XXX must explain this code */
 #ifndef MONITOR_CONSTANT_DELAY
-					int jump = chan->insmpl - chan->outsmpl - 4 * f->samples;
-					if (jump >= 0) {
-						if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1)
-							ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
-						chan->outsmpl += jump + 4 * f->samples;
-					} else
-						chan->outsmpl += f->samples;
+				int jump = chan->insmpl - chan->outsmpl - 4 * f->samples;
+				if (jump >= 0) {
+					if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1)
+						ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
+					chan->outsmpl += jump + 4 * f->samples;
+				} else
+					chan->outsmpl += f->samples;
 #else
-					int jump = chan->insmpl - chan->outsmpl;
-					if (jump - MONITOR_DELAY >= 0) {
-						if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
-							ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
-						chan->outsmpl += jump;
-					} else
-						chan->outsmpl += f->samples;
+				int jump = chan->insmpl - chan->outsmpl;
+				if (jump - MONITOR_DELAY >= 0) {
+					if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
+						ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
+					chan->outsmpl += jump;
+				} else
+					chan->outsmpl += f->samples;
 #endif
-					if (chan->monitor->state == AST_MONITOR_RUNNING) {
-						if (ast_writestream(chan->monitor->write_stream, f) < 0)
-							ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
-					}
+				if (chan->monitor->state == AST_MONITOR_RUNNING) {
+					if (ast_writestream(chan->monitor->write_stream, f) < 0)
+						ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
 				}
-
-				res = chan->tech->write(chan, f);
-			} else
-				res = 0;
-		}
-	}
-
-	if (f && (f != fr))
+			}
+
+			res = chan->tech->write(chan, f);
+		}
+		break;	
+	}
+
+	if (f && f != fr)
 		ast_frfree(f);
 	ast_clear_flag(chan, AST_FLAG_BLOCKING);
 	/* Consider a write failure to force a soft hangup */
 	if (res < 0)
 		chan->_softhangup |= AST_SOFTHANGUP_DEV;
 	else {
-		if ((chan->fout & 0x7fffffff) == 0x7fffffff)
-			chan->fout &= 0x80000000;
-		else
-			chan->fout++;
-	}
-	ast_mutex_unlock(&chan->lock);
+		chan->fout = FRAMECOUNT_INC(chan->fout);
+	}
+done:
+	ast_channel_unlock(chan);
 	return res;
 }
 
@@ -2474,7 +2411,7 @@
 	}
 	
 	/* Now we have a good choice for both. */
-	ast_mutex_lock(&chan->lock);
+	ast_channel_lock(chan);
 	*rawformat = native;
 	/* User perspective is fmt */
 	*format = fmt;
@@ -2488,7 +2425,7 @@
 	else
 		/* writing */
 		*trans = ast_translator_build_path(*rawformat, *format);
-	ast_mutex_unlock(&chan->lock);
+	ast_channel_unlock(chan);
 	if (option_debug)
 		ast_log(LOG_DEBUG, "Set channel %s to %s format %s\n", chan->name,
 			direction ? "write" : "read", ast_getformatname(fmt));
@@ -2509,101 +2446,100 @@
 
 struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh)
 {
-	int state = 0;
+	int dummy_outstate;
 	int cause = 0;
 	struct ast_channel *chan;
-	struct ast_frame *f;
 	int res = 0;
 	
+	if (outstate)
+		*outstate = 0;
+	else
+		outstate = &dummy_outstate;	/* make outstate always a valid pointer */
+
 	chan = ast_request(type, format, data, &cause);
-	if (chan) {
-		if (oh) {
-			if (oh->vars)	
-				ast_set_variables(chan, oh->vars);
-			if (oh->cid_num && *oh->cid_num && oh->cid_name && *oh->cid_name)
-				ast_set_callerid(chan, oh->cid_num, oh->cid_name, oh->cid_num);
-			if (oh->parent_channel)
-				ast_channel_inherit_variables(oh->parent_channel, chan);
-			if (oh->account)
-				ast_cdr_setaccount(chan, oh->account);	
-		}
-		ast_set_callerid(chan, cid_num, cid_name, cid_num);
-
-		if (!ast_call(chan, data, 0)) {
-			res = 1;	/* in case chan->_state is already AST_STATE_UP */
-			while (timeout && (chan->_state != AST_STATE_UP)) {
-				res = ast_waitfor(chan, timeout);
-				if (res < 0) {
-					/* Something not cool, or timed out */
+	if (!chan) {
+		ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
+		/* compute error and return */
+		if (cause == AST_CAUSE_BUSY)
+			*outstate = AST_CONTROL_BUSY;
+		else if (cause == AST_CAUSE_CONGESTION)
+			*outstate = AST_CONTROL_CONGESTION;
+		return NULL;
+	}
+
+	if (oh) {
+		if (oh->vars)	
+			ast_set_variables(chan, oh->vars);
+		/* XXX why is this necessary, for the parent_channel perhaps ? */
+		if (!ast_strlen_zero(oh->cid_num) && !ast_strlen_zero(oh->cid_name))
+			ast_set_callerid(chan, oh->cid_num, oh->cid_name, oh->cid_num);
+		if (oh->parent_channel)
+			ast_channel_inherit_variables(oh->parent_channel, chan);
+		if (oh->account)
+			ast_cdr_setaccount(chan, oh->account);	
+	}
+	ast_set_callerid(chan, cid_num, cid_name, cid_num);
+
+	if (ast_call(chan, data, 0)) {	/* ast_call failed... */
+		ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
+	} else {
+		res = 1;	/* mark success in case chan->_state is already AST_STATE_UP */
+		while (timeout && chan->_state != AST_STATE_UP) {
+			struct ast_frame *f;
+			res = ast_waitfor(chan, timeout);
+			if (res <= 0) /* error, timeout, or done */
+				break;
+			if (timeout > -1)
+				timeout = res;
+			f = ast_read(chan);
+			if (!f) {
+				*outstate = AST_CONTROL_HANGUP;
+				res = 0;
+				break;
+			}
+			if (f->frametype == AST_FRAME_CONTROL) {
+				switch (f->subclass) {
+				case AST_CONTROL_RINGING:	/* record but keep going */
+					*outstate = f->subclass;
 					break;
+
+				case AST_CONTROL_BUSY:
+				case AST_CONTROL_CONGESTION:
+				case AST_CONTROL_ANSWER:
+					*outstate = f->subclass;
+					timeout = 0;		/* trick to force exit from the while() */
+					break;
+
+				case AST_CONTROL_PROGRESS:	/* Ignore */
+				case -1:			/* Ignore -- just stopping indications */
+					break;
+
+				default:
+					ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass);
 				}
-				/* If done, break out */
-				if (!res)
-					break;
-				if (timeout > -1)
-					timeout = res;
-				f = ast_read(chan);
-				if (!f) {
-					state = AST_CONTROL_HANGUP;
-					res = 0;
-					break;
-				}
-				if (f->frametype == AST_FRAME_CONTROL) {
-					if (f->subclass == AST_CONTROL_RINGING)
-						state = AST_CONTROL_RINGING;
-					else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
-						state = f->subclass;
-						ast_frfree(f);
-						break;
-					} else if (f->subclass == AST_CONTROL_ANSWER) {
-						state = f->subclass;
-						ast_frfree(f);
-						break;
-					} else if (f->subclass == AST_CONTROL_PROGRESS) {
-						/* Ignore */
-					} else if (f->subclass == -1) {
-						/* Ignore -- just stopping indications */
-					} else {
-						ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass);
-					}
-				}
-				ast_frfree(f);
 			}
-		} else
-			ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
-	} else {
-		ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
-		switch(cause) {
-		case AST_CAUSE_BUSY:
-			state = AST_CONTROL_BUSY;
-			break;
-		case AST_CAUSE_CONGESTION:
-			state = AST_CONTROL_CONGESTION;
-			break;
-		}
-	}
-	if (chan) {
-		/* Final fixups */
-		if (oh) {
-			if (oh->context && *oh->context)
-				ast_copy_string(chan->context, oh->context, sizeof(chan->context));
-			if (oh->exten && *oh->exten)
-				ast_copy_string(chan->exten, oh->exten, sizeof(chan->exten));
-			if (oh->priority)	
-				chan->priority = oh->priority;
-		}
-		if (chan->_state == AST_STATE_UP)
-			state = AST_CONTROL_ANSWER;
-	}
-	if (outstate)
-		*outstate = state;
-	if (chan && res <= 0) {
-		if (!chan->cdr && (chan->cdr = ast_cdr_alloc())) {
+			ast_frfree(f);
+		}
+	}
+
+	/* Final fixups */
+	if (oh) {
+		if (!ast_strlen_zero(oh->context))
+			ast_copy_string(chan->context, oh->context, sizeof(chan->context));
+		if (!ast_strlen_zero(oh->exten))
+			ast_copy_string(chan->exten, oh->exten, sizeof(chan->exten));
+		if (oh->priority)	
+			chan->priority = oh->priority;
+	}
+	if (chan->_state == AST_STATE_UP)
+		*outstate = AST_CONTROL_ANSWER;
+
+	if (res <= 0) {
+		if (!chan->cdr && (chan->cdr = ast_cdr_alloc()))
 			ast_cdr_init(chan->cdr, chan);
-		}
 		if (chan->cdr) {
 			char tmp[256];
-			snprintf(tmp, 256, "%s/%s", type, (char *)data);
+			snprintf(tmp, sizeof(tmp), "%s/%s", type, (char *)data);
 			ast_cdr_setapp(chan->cdr,"Dial",tmp);
 			ast_cdr_update(chan);
 			ast_cdr_start(chan->cdr);
@@ -2668,8 +2604,8 @@
 				      "CallerIDName: %s\r\n"
 				      "Uniqueid: %s\r\n",
 				      c->name, ast_state2str(c->_state),
-				      c->cid.cid_num ? c->cid.cid_num : "<unknown>",
-				      c->cid.cid_name ? c->cid.cid_name : "<unknown>",
+				      S_OR(c->cid.cid_num, "<unknown>"),
+				      S_OR(c->cid.cid_name, "<unknown>"),
 				      c->uniqueid);
 		}
 		return c;
@@ -2724,56 +2660,21 @@
 
 int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders)
 {
-	int pos=0;
+	return ast_readstring_full(c, s, len, timeout, ftimeout, enders, -1, -1);
+}
+
+int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd)
+{
+	int pos = 0;	/* index in the buffer where we accumulate digits */
 	int to = ftimeout;
-	int d;
-
-	/* XXX Merge with full version? XXX */
+
 	/* Stop if we're a zombie or need a soft hangup */
 	if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c))
 		return -1;
 	if (!len)
 		return -1;
-	do {
-		if (c->stream) {
-			d = ast_waitstream(c, AST_DIGIT_ANY);
-			ast_stopstream(c);
-			usleep(1000);
-			if (!d)
-				d = ast_waitfordigit(c, to);
-		} else {
-			d = ast_waitfordigit(c, to);
-		}
-		if (d < 0)
-			return -1;
-		if (d == 0) {
-			s[pos]='\0';
-			return 1;
-		}
-		if (!strchr(enders, d))
-			s[pos++] = d;
-		if (strchr(enders, d) || (pos >= len)) {
-			s[pos]='\0';
-			return 0;
-		}
-		to = timeout;
-	} while(1);
-	/* Never reached */
-	return 0;
-}
-
-int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd)
-{
-	int pos=0;
-	int to = ftimeout;
-	int d;
-
-	/* Stop if we're a zombie or need a soft hangup */
-	if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c))
-		return -1;
-	if (!len)
-		return -1;
-	do {
+	for (;;) {
+		int d;
 		if (c->stream) {
 			d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd);
 			ast_stopstream(c);
@@ -2800,16 +2701,14 @@
 			return 0;
 		}
 		to = timeout;
-	} while(1);
+	}
 	/* Never reached */
 	return 0;
 }
 
 int ast_channel_supports_html(struct ast_channel *chan)
 {
-	if (chan->tech->send_html)
-		return 1;
-	return 0;
+	return (chan->tech->send_html) ? 1 : 0;
 }
 
 int ast_channel_sendhtml(struct ast_channel *chan, int subclass, const char *data, int datalen)
@@ -2821,9 +2720,7 @@
 
 int ast_channel_sendurl(struct ast_channel *chan, const char *url)
 {
-	if (chan->tech->send_html)
-		return chan->tech->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
-	return -1;
+	return ast_channel_sendhtml(chan, AST_HTML_URL, url, strlen(url) + 1);
 }
 
 int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
@@ -2841,8 +2738,10 @@
 
 	/* if the best path is not 'pass through', then
 	   transcoding is needed; if desired, force transcode path
-	   to use SLINEAR between channels */
-	if ((src != dst) && ast_opt_transcode_via_slin)
+	   to use SLINEAR between channels, but only if there is
+	   no direct conversion available */
+	if ((src != dst) && ast_opt_transcode_via_slin &&
+	    (ast_translate_path_steps(dst, src) != 1))
 		dst = AST_FORMAT_SLINEAR;
 	if (ast_set_read_format(chan, dst) < 0) {
 		ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, dst);
@@ -2860,10 +2759,13 @@

[... 3240 lines stripped ...]


More information about the asterisk-commits mailing list