[svn-commits] rmudgett: trunk r358861 - /trunk/main/channel.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Mar 13 12:01:57 CDT 2012


Author: rmudgett
Date: Tue Mar 13 12:01:55 2012
New Revision: 358861

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=358861
Log:
Fix crash caused by opaquification change -r356042.

The set_format() function was more subtle in how it modified the
struct ast_channel readtrans/writetrans values.

* Fixed ast_activate_generator() conversion correctly.

(closes issue ASTERISK-19434)
Reported by: Birger Harzenetter
Tested by: rmudgett

Modified:
    trunk/main/channel.c

Modified: trunk/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel.c?view=diff&rev=358861&r1=358860&r2=358861
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Tue Mar 13 12:01:55 2012
@@ -2912,19 +2912,17 @@
 
 	ast_channel_lock(chan);
 	if (ast_channel_generatordata(chan)) {
-		if (ast_channel_generator(chan) && ast_channel_generator(chan)->release)
+		if (ast_channel_generator(chan) && ast_channel_generator(chan)->release) {
 			ast_channel_generator(chan)->release(chan, ast_channel_generatordata(chan));
-		ast_channel_generatordata_set(chan, NULL);
+		}
 	}
 	if (gen->alloc && !(generatordata = gen->alloc(chan, params))) {
 		res = -1;
 	}
-	if (generatordata) {
-		ast_channel_generator_set(chan, gen);
-	}
+	ast_channel_generatordata_set(chan, generatordata);
 	if (!res) {
 		ast_settimeout(chan, 50, generator_force, chan);
-		ast_channel_generatordata_set(chan, generatordata);
+		ast_channel_generator_set(chan, gen);
 	}
 	ast_channel_unlock(chan);
 
@@ -4928,13 +4926,29 @@
 	return res;
 }
 
+struct set_format_trans_access {
+	struct ast_trans_pvt *(*get)(const struct ast_channel *chan);
+	void (*set)(struct ast_channel *chan, struct ast_trans_pvt *value);
+};
+
+static const struct set_format_trans_access set_format_readtrans = {
+	.get = ast_channel_readtrans,
+	.set = ast_channel_readtrans_set,
+};
+
+static const struct set_format_trans_access set_format_writetrans = {
+	.get = ast_channel_writetrans,
+	.set = ast_channel_writetrans_set,
+};
+
 static int set_format(struct ast_channel *chan,
 	struct ast_format_cap *cap_set,
 	struct ast_format *rawformat,
 	struct ast_format *format,
-	struct ast_trans_pvt **trans,
+	const struct set_format_trans_access *trans,
 	const int direction)
 {
+	struct ast_trans_pvt *trans_pvt;
 	struct ast_format_cap *cap_native = ast_channel_nativeformats(chan);
 	struct ast_format best_set_fmt;
 	struct ast_format best_native_fmt;
@@ -4954,10 +4968,12 @@
 		ast_format_cap_set(ast_channel_nativeformats(chan), &best_set_fmt);
 		ast_channel_unlock(chan);
 
-		if (*trans) {
-			ast_translator_free_path(*trans);
-		}
-		*trans = NULL;
+		trans_pvt = trans->get(chan);
+		if (trans_pvt) {
+			ast_translator_free_path(trans_pvt);
+			trans->set(chan, NULL);
+		}
+
 		/* If there is a generator on the channel, it needs to know about this
 		 * change if it is the write format. */
 		if (direction && ast_channel_generatordata(chan)) {
@@ -4987,7 +5003,7 @@
 
 	if ((ast_format_cmp(rawformat, &best_native_fmt) != AST_FORMAT_CMP_NOT_EQUAL) &&
 		(ast_format_cmp(format, &best_set_fmt) != AST_FORMAT_CMP_NOT_EQUAL) &&
-		((ast_format_cmp(rawformat, format) != AST_FORMAT_CMP_NOT_EQUAL) || (*trans))) {
+		((ast_format_cmp(rawformat, format) != AST_FORMAT_CMP_NOT_EQUAL) || trans->get(chan))) {
 		/* the channel is already in these formats, so nothing to do */
 		ast_channel_unlock(chan);
 		return 0;
@@ -4997,10 +5013,11 @@
 	/* User perspective is fmt */
 	ast_format_copy(format, &best_set_fmt);
 
-	/* Free any read translation we have right now */
-	if (*trans) {
-		ast_translator_free_path(*trans);
-		*trans = NULL;
+	/* Free any translation we have right now */
+	trans_pvt = trans->get(chan);
+	if (trans_pvt) {
+		ast_translator_free_path(trans_pvt);
+		trans->set(chan, NULL);
 	}
 
 	/* Build a translation path from the raw format to the desired format */
@@ -5014,12 +5031,13 @@
 	} else {
 		if (!direction) {
 			/* reading */
-			*trans = ast_translator_build_path(format, rawformat);
+			trans_pvt = ast_translator_build_path(format, rawformat);
 		} else {
 			/* writing */
-			*trans = ast_translator_build_path(rawformat, format);
-		}
-		res = *trans ? 0 : -1;
+			trans_pvt = ast_translator_build_path(rawformat, format);
+		}
+		trans->set(chan, trans_pvt);
+		res = trans_pvt ? 0 : -1;
 	}
 	ast_channel_unlock(chan);
 
@@ -5039,8 +5057,8 @@
 int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
 {
 	struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
-	struct ast_trans_pvt *trans = NULL;
 	int res;
+
 	if (!cap) {
 		return -1;
 	}
@@ -5050,10 +5068,9 @@
 		cap,
 		ast_channel_rawreadformat(chan),
 		ast_channel_readformat(chan),
-		&trans,
+		&set_format_readtrans,
 		0);
 
-	ast_channel_readtrans_set(chan, trans);
 	ast_format_cap_destroy(cap);
 	return res;
 }
@@ -5062,8 +5079,8 @@
 {
 	struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
 	struct ast_format tmp_format;
-	struct ast_trans_pvt *trans = NULL;
 	int res;
+
 	if (!cap) {
 		return -1;
 	}
@@ -5073,33 +5090,28 @@
 		cap,
 		ast_channel_rawreadformat(chan),
 		ast_channel_readformat(chan),
-		&trans,
+		&set_format_readtrans,
 		0);
 
-	ast_channel_readtrans_set(chan, trans);
 	ast_format_cap_destroy(cap);
 	return res;
 }
 
 int ast_set_read_format_from_cap(struct ast_channel *chan, struct ast_format_cap *cap)
 {
-	struct ast_trans_pvt *trans = NULL;
-	int res;
-	res = set_format(chan,
+	return set_format(chan,
 		cap,
 		ast_channel_rawreadformat(chan),
 		ast_channel_readformat(chan),
-		&trans,
+		&set_format_readtrans,
 		0);
-	ast_channel_readtrans_set(chan, trans);
-	return res;
 }
 
 int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
 {
 	struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
-	struct ast_trans_pvt *trans = NULL;
 	int res;
+
 	if (!cap) {
 		return -1;
 	}
@@ -5109,10 +5121,9 @@
 		cap,
 		ast_channel_rawwriteformat(chan),
 		ast_channel_writeformat(chan),
-		&trans,
+		&set_format_writetrans,
 		1);
 
-	ast_channel_writetrans_set(chan, trans);
 	ast_format_cap_destroy(cap);
 	return res;
 }
@@ -5121,8 +5132,8 @@
 {
 	struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
 	struct ast_format tmp_format;
-	struct ast_trans_pvt *trans = NULL;
 	int res;
+
 	if (!cap) {
 		return -1;
 	}
@@ -5132,26 +5143,21 @@
 		cap,
 		ast_channel_rawwriteformat(chan),
 		ast_channel_writeformat(chan),
-		&trans,
+		&set_format_writetrans,
 		1);
 
-	ast_channel_writetrans_set(chan, trans);
 	ast_format_cap_destroy(cap);
 	return res;
 }
 
 int ast_set_write_format_from_cap(struct ast_channel *chan, struct ast_format_cap *cap)
 {
-	struct ast_trans_pvt *trans = NULL;
-	int res;
-	res = set_format(chan,
+	return set_format(chan,
 		cap,
 		ast_channel_rawwriteformat(chan),
 		ast_channel_writeformat(chan),
-		&trans,
+		&set_format_writetrans,
 		1);
-	ast_channel_writetrans_set(chan, trans);
-	return res;
 }
 
 const char *ast_channel_reason2str(int reason)




More information about the svn-commits mailing list