From ad5cfd80c0163d087a7cb2586740a42f8ecc5251 Mon Sep 17 00:00:00 2001
From: Luigi Rizzo <rizzo@icir.org>
Date: Sun, 16 Apr 2006 15:13:39 +0000
Subject: [PATCH] simplify function __ast_request_and_dial() as follows: -
 handle immediately failures in ast_request();   This removes the need for
 checking 'chan' multiple times afterwards. - handle immediately failures in
 ast_call(), by moving the one-line   case at the top of the 'if' statement; -
 use ast_strlen_zero in several places instead of expanding it inline; - make
 outstate always a valid pointer; On passing mark an unclear statement and
 replace a magic number with sizeof(tmp).

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@20511 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 channel.c | 157 +++++++++++++++++++++++++++---------------------------
 1 file changed, 78 insertions(+), 79 deletions(-)

diff --git a/channel.c b/channel.c
index 32988bbf4a..6a560cf00e 100644
--- a/channel.c
+++ b/channel.c
@@ -2463,101 +2463,100 @@ int ast_set_write_format(struct ast_channel *chan, int fmt)
 
 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;
-				}
-				/* If done, break out */
-				if (!res)
+
+				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;
-				if (timeout > -1)
-					timeout = res;
-				f = ast_read(chan);
-				if (!f) {
-					state = AST_CONTROL_HANGUP;
-					res = 0;
+
+				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 (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;
+			ast_frfree(f);
 		}
 	}
-	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;
+
+	/* 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 (outstate)
-		*outstate = state;
-	if (chan && res <= 0) {
-		if (!chan->cdr && (chan->cdr = ast_cdr_alloc())) {
+	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);
-- 
GitLab