[asterisk-commits] irroot: branch irroot/t38gateway-1.8 r339503 - /team/irroot/t38gateway-1.8/res/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Oct 5 02:32:26 CDT 2011


Author: irroot
Date: Wed Oct  5 02:32:23 2011
New Revision: 339503

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=339503
Log:
Fully backport res_fax from trunk


Modified:
    team/irroot/t38gateway-1.8/res/res_fax.c

Modified: team/irroot/t38gateway-1.8/res/res_fax.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/res/res_fax.c?view=diff&rev=339503&r1=339502&r2=339503
==============================================================================
--- team/irroot/t38gateway-1.8/res/res_fax.c (original)
+++ team/irroot/t38gateway-1.8/res/res_fax.c Wed Oct  5 02:32:23 2011
@@ -98,6 +98,9 @@
 					<option name="f">
 						<para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
 					</option>
+					<option name="F">
+						<para>Force usage of audio mode on T.38 capable channels.</para>
+					</option>
 					<option name="s">
 						<para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
 					</option>
@@ -130,6 +133,9 @@
 					</option>
 					<option name="f">
 						<para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
+					</option>
+					<option name="F">
+						<para>Force usage of audio mode on T.38 capable channels.</para>
 					</option>
 					<option name="s">
 						<para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
@@ -187,7 +193,7 @@
 						<para>R/W T38 fax gateway, with optional fax activity timeout in seconds (yes[,timeout]/no)</para>
 					</enum>
 					<enum name="faxdetect">
-						<para>R/W Enable FAX detect with optional timeout in seconds (yes[,timeout]/no)</para>
+						<para>R/W Enable FAX detect with optional timeout in seconds (yes,t38,cng[,timeout]/no)</para>
 					</enum>
 					<enum name="pages">
 						<para>R/O Number of pages transferred.</para>
@@ -275,13 +281,16 @@
 	struct ast_dsp *dsp;
 	/*! \brief original audio formats */
 	unsigned int orig_format;
-	/*! \brief Noise limit to end faxdetect */
-	int noiselim;
-	/*! \brief result of the framehook e[CED]/f[CNG]/n[Noise]/t[T38] */
-	int result;
 	/*! \brief fax session details */
 	struct ast_fax_session_details *details;
+	/*! \brief mode */
+	int flags;
 };
+
+/*! \brief FAX Detect flags */
+#define FAX_DETECT_MODE_CNG	(1 << 0)
+#define FAX_DETECT_MODE_T38	(1 << 1)
+#define FAX_DETECT_MODE_BOTH	(FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38)
 
 static int fax_logger_level = -1;
 
@@ -342,6 +351,7 @@
 	OPT_STATUS      = (1 << 3),
 	OPT_ALLOWAUDIO  = (1 << 5),
 	OPT_REQUEST_T38 = (1 << 6),
+	OPT_FORCE_AUDIO = (1 << 7),
 };
 
 AST_APP_OPTIONS(fax_exec_options, BEGIN_OPTIONS
@@ -349,6 +359,7 @@
 	AST_APP_OPTION('c', OPT_CALLERMODE),
 	AST_APP_OPTION('d', OPT_DEBUG),
 	AST_APP_OPTION('f', OPT_ALLOWAUDIO),
+	AST_APP_OPTION('F', OPT_FORCE_AUDIO),
 	AST_APP_OPTION('s', OPT_STATUS),
 	AST_APP_OPTION('z', OPT_REQUEST_T38),
 END_OPTIONS);
@@ -577,7 +588,6 @@
 	}
 	return 0;
 }
-
 static char *ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
 {
 	char *out = buf;
@@ -623,9 +633,10 @@
 		if (!first) {
 			ast_build_string(&buf, &size, ",");
 		}
-		ast_build_string(&buf, &size, "T38_GATEWAY");
+		ast_build_string(&buf, &size, "GATEWAY");
 		first = 0;
 	}
+
 
 	return out;
 }
@@ -840,6 +851,9 @@
 	}
 
 	if (s->details) {
+		if (s->details->caps & AST_FAX_TECH_GATEWAY) {
+			s->details->caps &= ~AST_FAX_TECH_GATEWAY;
+		}
 		ao2_ref(s->details, -1);
 	}
 	
@@ -877,7 +891,6 @@
 {
 	struct ast_fax_session *s;
 	struct fax_module *faxmod;
-	char caps[128] = "";
 
 	if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
 		return NULL;
@@ -903,6 +916,7 @@
 	AST_RWLIST_UNLOCK(&faxmodules);
 
 	if (!faxmod) {
+		char caps[128] = "";
 		ast_log(LOG_ERROR, "Could not locate a FAX technology module with capabilities (%s)\n", ast_fax_caps_to_str(details->caps, caps, sizeof(caps)));
 		ao2_ref(s, -1);
 		return NULL;
@@ -944,7 +958,6 @@
 {
 	struct ast_fax_session *s = NULL;
 	struct fax_module *faxmod;
-	char caps[128] = "";
 
 	if (reserved) {
 		s = reserved;
@@ -1020,6 +1033,7 @@
 		AST_RWLIST_UNLOCK(&faxmodules);
 
 		if (!faxmod) {
+			char caps[128] = "";
 			ast_log(LOG_ERROR, "Could not locate a FAX technology module with capabilities (%s)\n", ast_fax_caps_to_str(details->caps, caps, sizeof(caps)));
 			ao2_ref(s, -1);
 			return NULL;
@@ -1498,10 +1512,9 @@
 
 	set_channel_variables(chan, details);
 
+	ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
 	if (!strcasecmp(details->result, "FAILED")) {
 		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
-	} else {
-		ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
 	}
 
 	if (fax) {
@@ -1702,14 +1715,9 @@
 	pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
 	pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
 
-	/* if we ran receivefax then we attempted to receive a fax, even if we
-	 * never start a fax session */
-	ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
-
 	/* Get a FAX session details structure from the channel's FAX datastore and create one if
 	 * it does not already exist. */
 	if (!(details = find_or_create_details(chan))) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
 		pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
 		ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
@@ -1721,7 +1729,7 @@
 	ast_string_field_set(details, error, "INIT_ERROR");
 	set_channel_variables(chan, details);
 
-	if ((details->caps & AST_FAX_TECH_GATEWAY) && (details->gateway_id > 0)) {
+	if (details->gateway_id > 0) {
 		ast_string_field_set(details, resultstr, "can't receive a fax on a channel with a T.38 gateway");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
@@ -1730,7 +1738,6 @@
 	}
 
 	if (details->maxrate < details->minrate) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "maxrate is less than minrate");
 		set_channel_variables(chan, details);
@@ -1740,7 +1747,6 @@
 	}
 
 	if (check_modem_rate(details->modems, details->minrate)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
 		ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
@@ -1751,7 +1757,6 @@
 	}
 
 	if (check_modem_rate(details->modems, details->maxrate)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
 		ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
@@ -1762,7 +1767,6 @@
 	}
 
 	if (ast_strlen_zero(data)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
@@ -1775,7 +1779,6 @@
 
 	if (!ast_strlen_zero(args.options) &&
 	    ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
@@ -1783,7 +1786,6 @@
 		return -1;
 	}
 	if (ast_strlen_zero(args.filename)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
@@ -1794,7 +1796,6 @@
 
 	/* check for unsupported FAX application options */
 	if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
@@ -1802,12 +1803,13 @@
 		ao2_ref(details, -1);
 		return -1;
 	}
+	
+	ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
 
 	pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
 	pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
 
 	if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, error, "MEMORY_ERROR");
 		ast_string_field_set(details, resultstr, "error allocating memory");
 		set_channel_variables(chan, details);
@@ -1835,12 +1837,12 @@
 
 	t38state = ast_channel_get_t38_state(chan);
 	if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
-	    ast_test_flag(&opts, OPT_ALLOWAUDIO)) {
+	    ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
+	    ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
 		details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
 	}
 
 	if (!(s = fax_session_reserve(details, &token))) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, resultstr, "error reserving fax session");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
@@ -1851,7 +1853,6 @@
 	/* make sure the channel is up */
 	if (chan->_state != AST_STATE_UP) {
 		if (ast_answer(chan)) {
-			ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 			ast_string_field_set(details, resultstr, "error answering channel");
 			set_channel_variables(chan, details);
 			ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
@@ -1862,20 +1863,22 @@
 		}
 	}
 
-	if (set_fax_t38_caps(chan, details)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
-		ast_string_field_set(details, error, "T38_NEG_ERROR");
-		ast_string_field_set(details, resultstr, "error negotiating T.38");
-		set_channel_variables(chan, details);
-		fax_session_release(s, token);
-		ao2_ref(s, -1);
-		ao2_ref(details, -1);
-		return -1;
-	}
-
-	if (details->caps & AST_FAX_TECH_T38) {
+	if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
+		if (set_fax_t38_caps(chan, details)) {
+			ast_string_field_set(details, error, "T38_NEG_ERROR");
+			ast_string_field_set(details, resultstr, "error negotiating T.38");
+			set_channel_variables(chan, details);
+			fax_session_release(s, token);
+			ao2_ref(s, -1);
+			ao2_ref(details, -1);
+			return -1;
+		}
+	} else {
+		details->caps |= AST_FAX_TECH_AUDIO;
+	}
+
+	if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
 		if (receivefax_t38_init(chan, details)) {
-			ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 			ast_string_field_set(details, error, "T38_NEG_ERROR");
 			ast_string_field_set(details, resultstr, "error negotiating T.38");
 			set_channel_variables(chan, details);
@@ -2182,14 +2185,9 @@
 	pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
 	pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
 
-	/* if we ran sendfax then we attempted to send a fax, even if we never
-	 * start a fax session */
-	ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
-
 	/* Get a requirement structure and set it.  This structure is used
 	 * to tell the FAX technology module about the higher level FAX session */
 	if (!(details = find_or_create_details(chan))) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
 		pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
 		ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
@@ -2201,7 +2199,7 @@
 	ast_string_field_set(details, error, "INIT_ERROR");
 	set_channel_variables(chan, details);
 
-	if ((details->caps & AST_FAX_TECH_GATEWAY) && (details->gateway_id > 0)) {
+	if (details->gateway_id > 0) {
 		ast_string_field_set(details, resultstr, "can't send a fax on a channel with a T.38 gateway");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "executing SendFAX on a channel with a T.38 Gateway is not supported\n");
@@ -2210,7 +2208,6 @@
 	}
 
 	if (details->maxrate < details->minrate) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "maxrate is less than minrate");
 		set_channel_variables(chan, details);
@@ -2220,7 +2217,6 @@
 	}
 
 	if (check_modem_rate(details->modems, details->minrate)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
 		ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
@@ -2231,7 +2227,6 @@
 	}
 
 	if (check_modem_rate(details->modems, details->maxrate)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
 		ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
@@ -2242,7 +2237,6 @@
 	}
 
 	if (ast_strlen_zero(data)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
@@ -2256,7 +2250,6 @@
 
 	if (!ast_strlen_zero(args.options) &&
 	    ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
@@ -2264,7 +2257,6 @@
 		return -1;
 	}
 	if (ast_strlen_zero(args.filenames)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
@@ -2275,7 +2267,6 @@
 	
 	/* check for unsupported FAX application options */
 	if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
@@ -2284,11 +2275,12 @@
 		return -1;
 	}
 
+	ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
+
 	file_count = 0;
 	filenames = args.filenames;
 	while ((c = strsep(&filenames, "&"))) {
 		if (access(c, (F_OK | R_OK)) < 0) {
-			ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 			ast_string_field_set(details, error, "FILE_ERROR");
 			ast_string_field_set(details, resultstr, "error reading file");
 			set_channel_variables(chan, details);
@@ -2298,7 +2290,6 @@
 		}
 
 		if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
-			ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 			ast_string_field_set(details, error, "MEMORY_ERROR");
 			ast_string_field_set(details, resultstr, "error allocating memory");
 			set_channel_variables(chan, details);
@@ -2312,10 +2303,6 @@
 		file_count++;
 	}
 
-	if (file_count > 1) {
-		details->caps |= AST_FAX_TECH_MULTI_DOC;
-	}
-
 	ast_verb(3, "Channel '%s' sending FAX:\n", chan->name);
 	AST_LIST_TRAVERSE(&details->documents, doc, next) {
 		ast_verb(3, "   %s\n", doc->filename);
@@ -2323,6 +2310,10 @@
 
 	details->caps = AST_FAX_TECH_SEND;
 
+	if (file_count > 1) {
+		details->caps |= AST_FAX_TECH_MULTI_DOC;
+	}
+
 	/* check for debug */
 	if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
 		details->option.debug = AST_FAX_OPTFLAG_TRUE;
@@ -2335,7 +2326,8 @@
 
 	t38state = ast_channel_get_t38_state(chan);
 	if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
-	    ast_test_flag(&opts, OPT_ALLOWAUDIO)) {
+	    ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
+	    ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
 		details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
 	}
 
@@ -2344,7 +2336,6 @@
 	}
 
 	if (!(s = fax_session_reserve(details, &token))) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 		ast_string_field_set(details, resultstr, "error reserving fax session");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
@@ -2355,7 +2346,6 @@
 	/* make sure the channel is up */
 	if (chan->_state != AST_STATE_UP) {
 		if (ast_answer(chan)) {
-			ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 			ast_string_field_set(details, resultstr, "error answering channel");
 			set_channel_variables(chan, details);
 			ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
@@ -2366,20 +2356,22 @@
 		}
 	}
 
-	if (set_fax_t38_caps(chan, details)) {
-		ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
-		ast_string_field_set(details, error, "T38_NEG_ERROR");
-		ast_string_field_set(details, resultstr, "error negotiating T.38");
-		set_channel_variables(chan, details);
-		fax_session_release(s, token);
-		ao2_ref(s, -1);
-		ao2_ref(details, -1);
-		return -1;
-	}
-
-	if (details->caps & AST_FAX_TECH_T38) {
+	if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
+		if (set_fax_t38_caps(chan, details)) {
+			ast_string_field_set(details, error, "T38_NEG_ERROR");
+			ast_string_field_set(details, resultstr, "error negotiating T.38");
+			set_channel_variables(chan, details);
+			fax_session_release(s, token);
+			ao2_ref(s, -1);
+			ao2_ref(details, -1);
+			return -1;
+		}
+	} else {
+		details->caps |= AST_FAX_TECH_AUDIO;
+	}
+
+	if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
 		if (sendfax_t38_init(chan, details)) {
-			ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
 			ast_string_field_set(details, error, "T38_NEG_ERROR");
 			ast_string_field_set(details, resultstr, "error negotiating T.38");
 			set_channel_variables(chan, details);
@@ -2464,7 +2456,6 @@
 	if (gateway->s) {
 		fax_session_release(gateway->s, gateway->token);
 		gateway->token = NULL;
-		gateway->s->details->caps |= ~AST_FAX_TECH_GATEWAY;
 
 		ao2_lock(faxregistry.container);
 		ao2_unlink(faxregistry.container, gateway->s);
@@ -2508,7 +2499,7 @@
 
 	details->caps = AST_FAX_TECH_GATEWAY;
 	if (details->gateway_timeout && !(gateway->s = fax_session_reserve(details, &gateway->token))) {
-		details->caps |= ~AST_FAX_TECH_GATEWAY;
+		details->caps &= ~AST_FAX_TECH_GATEWAY;
 		ast_log(LOG_ERROR, "Can't reserve a FAX session, gateway attempt failed.\n");
 		ao2_ref(gateway, -1);
 		return NULL;
@@ -3170,19 +3161,17 @@
 /*! \brief Create a new fax detect object.
  * \param chan the channel attaching to
  * \param timeout remove framehook in this time if set
- * \param noiselim end faxdetect when noiselim ms of noise is detected
- * \param dsp_detect_flag dsp faxmode detect flags
+ * \param flags required options
  * \return NULL or a fax gateway object
  */
-static struct fax_detect *fax_detect_new(struct ast_channel *chan, int timeout, int noiselim, int dsp_detect_flag)
+static struct fax_detect *fax_detect_new(struct ast_channel *chan, int timeout, int flags)
 {
 	struct fax_detect *faxdetect = ao2_alloc(sizeof(*faxdetect), destroy_faxdetect);
 	if (!faxdetect) {
 		return NULL;
 	}
 
-	faxdetect->noiselim = noiselim;
-	faxdetect->result = 0;
+	faxdetect->flags = flags;
 
 	if (timeout) {
 		faxdetect->timeout_start = ast_tvnow();
@@ -3191,15 +3180,18 @@
 		faxdetect->timeout_start.tv_usec = 0;
 	}
 
-	faxdetect->dsp = ast_dsp_new();
-	if (!faxdetect->dsp) {
-		ao2_ref(faxdetect, -1);
-		return NULL;
-	}
-
-	ast_dsp_set_features(faxdetect->dsp, DSP_FEATURE_FAX_DETECT);
-	ast_dsp_set_faxmode(faxdetect->dsp, dsp_detect_flag || DSP_FAXMODE_DETECT_SQUELCH);
-	ast_dsp_set_threshold(faxdetect->dsp, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
+	if (faxdetect->flags & FAX_DETECT_MODE_CNG) {
+		faxdetect->dsp = ast_dsp_new();
+		if (!faxdetect->dsp) {
+			ao2_ref(faxdetect, -1);
+			return NULL;
+		}
+		ast_dsp_set_features(faxdetect->dsp, DSP_FEATURE_FAX_DETECT);
+		ast_dsp_set_faxmode(faxdetect->dsp, DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_SQUELCH);
+	} else {
+		faxdetect->dsp = NULL;
+	}
+
 	return faxdetect;
 }
 
@@ -3227,7 +3219,7 @@
 	struct ast_fax_session_details *details;
 	struct ast_control_t38_parameters *control_params;
 	struct ast_channel *peer;
-	int dspnoise;
+	int result = 0;
 
 	details = faxdetect->details;
 
@@ -3272,9 +3264,13 @@
 		return f;
 	}
 
-	/* only handle VOICE/DTMF and CONTROL frames*/
+	/* only handle VOICE and CONTROL frames*/
 	switch (f->frametype) {
 	case AST_FRAME_VOICE:
+		/* we have no DSP this means we not detecting CNG */
+		if (!faxdetect->dsp) {
+			break;
+		}
 		/* We can only process some formats*/
 		switch (f->subclass.codec) {
 			case AST_FORMAT_SLINEAR:
@@ -3284,12 +3280,8 @@
 		}
 		break;
 	case AST_FRAME_CONTROL:
-		if (f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
-			break;
-		}
-		return f;
-	case AST_FRAME_DTMF:
-		if ((f->subclass.integer == 'f') || (f->subclass.integer == 'e')) {
+		if ((f->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
+		    (faxdetect->flags & FAX_DETECT_MODE_T38)) {
 			break;
 		}
 		return f;
@@ -3300,30 +3292,23 @@
 	if (f->frametype == AST_FRAME_VOICE) {
 		f = ast_dsp_process(chan, faxdetect->dsp, f);
 		if (f->frametype == AST_FRAME_DTMF) {
-			faxdetect->result = f->subclass.integer;
-		} else if ((f->frametype == AST_FRAME_VOICE) && (faxdetect->noiselim > 0)) {
-			ast_dsp_noise(faxdetect->dsp, f, &dspnoise);
-			if (dspnoise > faxdetect->noiselim) {
-				faxdetect->result = 'n';
-			}
+			result = f->subclass.integer;
 		}
 	} else if ((f->frametype == AST_FRAME_CONTROL) && (f->datalen == sizeof(struct ast_control_t38_parameters))) {
 		control_params = f->data.ptr;
 		switch (control_params->request_response) {
 		case AST_T38_NEGOTIATED:
 		case AST_T38_REQUEST_NEGOTIATE:
-			faxdetect->result = 't';
+			result = 't';
 			break;
 		default:
 			break;
 		}
-	} else if (f->frametype == AST_FRAME_DTMF) {
-		faxdetect->result = f->subclass.integer;
-	}
-
-	if (faxdetect->result) {
+	}
+
+	if (result) {
 		const char *target_context = S_OR(chan->macrocontext, chan->context);
-		switch (faxdetect->result) {
+		switch (result) {
 		case 'f':
 		case 't':
 			ast_channel_unlock(chan);
@@ -3331,7 +3316,7 @@
 			    S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 				ast_channel_lock(chan);
 				ast_verbose(VERBOSE_PREFIX_2 "Redirecting '%s' to fax extension due to %s detection\n",
-					chan->name, (faxdetect->result == 'f') ? "CNG" : "T38");
+					chan->name, (result == 'f') ? "CNG" : "T38");
 				pbx_builtin_setvar_helper(chan, "FAXEXTEN", chan->exten);
 				if (ast_async_goto(chan, target_context, "fax", 1)) {
 					ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", chan->name, target_context);
@@ -3340,8 +3325,8 @@
 				f = &ast_null_frame;
 			} else {
 				ast_channel_lock(chan);
-				ast_log(LOG_NOTICE, "FAX %s detected but no fax extension\n",
-					(faxdetect->result == 'f') ? "CNG" : "T38");
+				ast_log(LOG_NOTICE, "FAX %s detected but no fax extension in context (%s)\n",
+					(result == 'f') ? "CNG" : "T38", target_context);
 			}
 		}
 		ast_framehook_detach(chan, details->faxdetect_id);
@@ -3354,12 +3339,11 @@
 /*! \brief Attach a faxdetect framehook object to a channel.
  * \param chan the channel to attach to
  * \param timeout remove framehook in this time if set
- * \param noiselim end faxdetect when noiselim ms of noise is detected
- * \param dsp_detect_flag dsp faxmode detect flags
  * \return the faxdetect structure or NULL on error
+ * \param flags required options
  * \retval -1 error
  */
-static struct fax_detect* fax_detect_attach(struct ast_channel *chan, int timeout, int noiselim, int dsp_detect_flags)
+static int fax_detect_attach(struct ast_channel *chan, int timeout, int flags)
 {
 	struct fax_detect *faxdetect;
 	struct ast_fax_session_details *details;
@@ -3371,14 +3355,14 @@
 
 	if (!(details = find_or_create_details(chan))) {
 		ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
-		return NULL;
+		return -1;
 	}
 
 	/* set up the frame hook*/
-	faxdetect = fax_detect_new(chan, timeout, noiselim, dsp_detect_flags);
+	faxdetect = fax_detect_new(chan, timeout, flags);
 	if (!faxdetect) {
 		ao2_ref(details, -1);
-		return NULL;
+		return -1;
 	}
 
 	fr_hook.data = faxdetect;
@@ -3388,14 +3372,10 @@
 	ast_channel_unlock(chan);
 
 	if (details->faxdetect_id < 0) {
-		ao2_ref(details, -1);
 		ao2_ref(faxdetect, -1);
-		return NULL;
-	}
-
-	/* return it with ref held in framhook and return*/
-	ao2_ref(faxdetect, 1);
-	return faxdetect;
+	}
+
+	return details->faxdetect_id;
 }
 
 /*! \brief hash callback for ao2 */
@@ -3916,27 +3896,38 @@
 		const char *val = ast_skip_blanks(value);
 		char *timeout = strchr(val, ',');
 		unsigned int fdtimeout = 0;
-		struct fax_detect *faxdetect;
+		int flags;
+		int faxdetect;
 
 		if (timeout) {
 			*timeout++ = '\0';
 		}
 
-		if (ast_true(val)) {
+		if (ast_true(val) || !strcasecmp(val, "t38") || !strcasecmp(val, "cng")) {
 			if (details->faxdetect_id < 0) {
 				if (timeout && (sscanf(timeout, "%u", &fdtimeout) == 1)) {
-					fdtimeout = fdtimeout * 1000;
+					if (fdtimeout > 0) {
+						fdtimeout = fdtimeout * 1000;
+					} else {
+						ast_log(LOG_WARNING, "Timeout cannot be negative ignoring timeout\n");
+					}
 				}
 
-				faxdetect = fax_detect_attach(chan, fdtimeout, 0, DSP_FAXMODE_DETECT_CNG);
-
-				if (faxdetect && (details->faxdetect_id >= 0)) {
-					ast_debug(1, "Attached FAX detect to channel %s.\n", chan->name);
+				if (!strcasecmp(val, "t38")) {
+					flags = FAX_DETECT_MODE_T38;
+				} else if (!strcasecmp(val, "cng")) {
+					flags = FAX_DETECT_MODE_CNG;
 				} else {
+					flags = FAX_DETECT_MODE_BOTH;
+				}
+
+				faxdetect = fax_detect_attach(chan, fdtimeout, flags);
+				if (faxdetect < 0) {
 					ast_log(LOG_ERROR, "Error attaching FAX detect to channel %s.\n", chan->name);
 					res = -1;
+				} else {
+					ast_debug(1, "Attached FAX detect to channel %s.\n", chan->name);
 				}
-				ao2_ref(faxdetect, -1);
 			} else {
 				ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", chan->name);
 			}




More information about the asterisk-commits mailing list