[svn-commits] kpfleming: trunk r222110 - in /trunk: ./ channels/ configs/ main/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Oct 5 14:45:05 CDT 2009


Author: kpfleming
Date: Mon Oct  5 14:45:00 2009
New Revision: 222110

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=222110
Log:
Allow non-compliant T.38 endpoints to be supportable via configuration option.

Many T.38 endpoints incorrectly send the maximum IFP frame size they can accept
as the T38FaxMaxDatagram value in their SDP, when in fact this value is
supposed to be the maximum UDPTL payload size (datagram size) they can accept.
If the value they supply is small enough (a commonly supplied value is '72'),
T.38 UDPTL transmissions will likely fail completely because the UDPTL packets
will not have enough room for a primary IFP frame and the redundancy used for
error correction. If this occurs, the Asterisk UDPTL stack will emit log messages
warning that data loss may occur, and that the value may need to be overridden.

This patch extends the 't38pt_udptl' configuration option in sip.conf to allow
the administrator to override the value supplied by the remote endpoint and
supply a value that allows T.38 FAX transmissions to be successful with that
endpoint. In addition, in any SIP call where the override takes effect, a debug
message will be printed to that effect. This patch also removes the
T38FaxMaxDatagram configuration option from udptl.conf.sample, since it has not
actually had any effect for a number of releases.

In addition, this patch cleans up the T.38 documentation in sip.conf.sample
(which incorrectly documented that T.38 support was passthrough only).

(issue #15586)
Reported by: globalnetinc

Modified:
    trunk/UPGRADE.txt
    trunk/channels/chan_sip.c
    trunk/configs/sip.conf.sample
    trunk/configs/udptl.conf.sample
    trunk/main/udptl.c

Modified: trunk/UPGRADE.txt
URL: http://svnview.digium.com/svn/asterisk/trunk/UPGRADE.txt?view=diff&rev=222110&r1=222109&r2=222110
==============================================================================
--- trunk/UPGRADE.txt (original)
+++ trunk/UPGRADE.txt Mon Oct  5 14:45:00 2009
@@ -66,6 +66,14 @@
 * T.38 FAX error correction mode can no longer be configured in udptl.conf;
   instead, it is configured on a per-peer (or global) basis in sip.conf, with
   the same default as was present in udptl.conf.sample.
+
+* T.38 FAX maximum datagram size can no longer be configured in updtl.conf;
+  instead, it is either supplied by the application servicing the T.38 channel
+  (for a FAX send or receive) or calculated from the bridged endpoint's
+  maximum datagram size (for a T.38 FAX passthrough call). In addition, sip.conf
+  allows for overriding the value supplied by a remote endpoint, which is useful
+  when T.38 connections are made to gateways that supply incorrectly-calculated
+  maximum datagram sizes.
 
 * There have been some changes to the IAX2 protocol to address the security
   concerns documented in the security advisory AST-2009-006.  Please see the

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=222110&r1=222109&r2=222110
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Mon Oct  5 14:45:00 2009
@@ -1272,6 +1272,8 @@
 /* }@ */
 
 static struct ast_flags global_flags[2] = {{0}};        /*!< global SIP_ flags */
+static int global_t38_maxdatagram;			/*!< global T.38 FaxMaxDatagram override */
+
 static char used_context[AST_MAX_CONTEXT];		/*!< name of automatically created context for unloading */
 
 
@@ -1518,10 +1520,10 @@
 #define SIP_PAGE2_SUBSCRIBEMWIONLY	(1 << 18)	/*!< GP: Only issue MWI notification if subscribed to */
 #define SIP_PAGE2_IGNORESDPVERSION	(1 << 19)	/*!< GDP: Ignore the SDP session version number we receive and treat all sessions as new */
 
-#define SIP_PAGE2_T38SUPPORT		        (7 << 20)	/*!< GDP: T.38 Fax Support */
+#define SIP_PAGE2_T38SUPPORT		        (3 << 20)	/*!< GDP: T.38 Fax Support */
 #define SIP_PAGE2_T38SUPPORT_UDPTL	        (1 << 20)	/*!< GDP: T.38 Fax Support (no error correction) */
 #define SIP_PAGE2_T38SUPPORT_UDPTL_FEC	        (2 << 20)	/*!< GDP: T.38 Fax Support (FEC error correction) */
-#define SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY	(4 << 20)	/*!< GDP: T.38 Fax Support (redundancy error correction) */
+#define SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY	(3 << 20)	/*!< GDP: T.38 Fax Support (redundancy error correction) */
 
 #define SIP_PAGE2_CALL_ONHOLD		(3 << 23)	/*!< D: Call hold states: */
 #define SIP_PAGE2_CALL_ONHOLD_ACTIVE    (1 << 23)       /*!< D: Active hold */
@@ -1761,6 +1763,7 @@
 	int jointnoncodeccapability;            /*!< Joint Non codec capability */
 	int redircodecs;			/*!< Redirect codecs */
 	int maxcallbitrate;			/*!< Maximum Call Bitrate for Video Calls */	
+	int t38_maxdatagram;			/*!< T.38 FaxMaxDatagram override */
 	int request_queue_sched_id;		/*!< Scheduler ID of any scheduled action to process queued requests */
 	int provisional_keepalive_sched_id; /*!< Scheduler ID for provisional responses that need to be sent out to avoid cancellation */
 	const char *last_provisional;   /*!< The last successfully transmitted provisonal response message */
@@ -2009,6 +2012,7 @@
 	int inRinging;			/*!< Number of calls ringing */
 	int onHold;                     /*!< Peer has someone on hold */
 	int call_limit;			/*!< Limit of concurrent calls */
+	int t38_maxdatagram;		/*!< T.38 FaxMaxDatagram override */
 	int busy_level;			/*!< Level of active channels where we signal busy */
 	enum transfermodes allowtransfer;	/*! SIP Refer restriction scheme */
 	struct ast_codec_pref prefs;	/*!<  codec prefs */
@@ -5178,6 +5182,7 @@
 			/* t38pt_udptl was enabled in the peer and not in [general] */
 			dialog->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr);
 		}
+		dialog->t38_maxdatagram = peer->t38_maxdatagram;
 		set_t38_capabilities(dialog);
 	} else if (dialog->udptl) {
 		ast_udptl_destroy(dialog->udptl);
@@ -7235,6 +7240,7 @@
 	if (sip_methods[intended_method].need_rtp) {
 		if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && (p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr))) {
 			ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio);
+			p->t38_maxdatagram = global_t38_maxdatagram;
 		}
 		p->maxcallbitrate = default_maxcallbitrate;
 		p->autoframing = global_autoframing;
@@ -7263,6 +7269,7 @@
 	    (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
 		p->noncodeccapability |= AST_RTP_DTMF;
 	if (p->udptl) {
+		p->t38_maxdatagram = global_t38_maxdatagram;
 		set_t38_capabilities(p);
 	}
 	ast_string_field_set(p, context, sip_cfg.default_context);
@@ -8725,6 +8732,11 @@
 					ast_debug(3, "FaxVersion: %d\n", x);
 					p->t38.their_parms.version = x;
 				} else if ((sscanf(a, "T38FaxMaxDatagram:%30d", &x) == 1) || (sscanf(a, "T38MaxDatagram:%30d", &x) == 1)) {
+					/* override the supplied value if the configuration requests it */
+					if (p->t38_maxdatagram > x) {
+						ast_debug(1, "Overriding T38FaxMaxDatagram '%d' with '%d'\n", x, p->t38_maxdatagram);
+						x = p->t38_maxdatagram;
+					}
 					found = 1;
 					ast_debug(3, "FaxMaxDatagram: %d\n", x);
 					ast_udptl_set_far_max_datagram(p->udptl, x);
@@ -14262,6 +14274,7 @@
 	ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
 
 	if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->udptl) {
+		p->t38_maxdatagram = peer->t38_maxdatagram;
 		set_t38_capabilities(p);
 	}
 
@@ -15577,6 +15590,18 @@
 	}
 }
 
+static struct _map_x_s faxecmodes[] = {
+	{ SIP_PAGE2_T38SUPPORT_UDPTL,			"None"},
+	{ SIP_PAGE2_T38SUPPORT_UDPTL_FEC,		"FEC"},
+	{ SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY,	"Redundancy"},
+	{ -1,						NULL},
+};
+
+static const char *faxec2str(int faxec)
+{
+	return map_x_s(faxecmodes, faxec, "Unknown");
+}
+
 /*! \brief Show one peer in detail (main function) */
 static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[])
 {
@@ -15655,7 +15680,9 @@
 		ast_cli(fd, "  Insecure     : %s\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE)));
 		ast_cli(fd, "  Force rport  : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT)));
 		ast_cli(fd, "  ACL          : %s\n", cli_yesno(peer->ha != NULL));
-		ast_cli(fd, "  T38 pt UDPTL : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)));
+		ast_cli(fd, "  T.38 support : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)));
+		ast_cli(fd, "  T.38 EC mode : %s\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)));
+		ast_cli(fd, "  T.38 MaxDtgrm: %d\n", peer->t38_maxdatagram);
 		ast_cli(fd, "  DirectMedia  : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_DIRECT_MEDIA)));
 		ast_cli(fd, "  PromiscRedir : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR)));
 		ast_cli(fd, "  User=Phone   : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_USEREQPHONE)));
@@ -15767,6 +15794,9 @@
 		astman_append(s, "SIP-UserPhone: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_USEREQPHONE)?"Y":"N"));
 		astman_append(s, "SIP-VideoSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT)?"Y":"N"));
 		astman_append(s, "SIP-TextSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT)?"Y":"N"));
+		astman_append(s, "SIP-T.38Support: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)?"Y":"N"));
+		astman_append(s, "SIP-T.38EC: %s\r\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)));
+		astman_append(s, "SIP-T.38MaxDtgrm: %d\r\n", peer->t38_maxdatagram);
 		astman_append(s, "SIP-Sess-Timers: %s\r\n", stmode2str(peer->stimer.st_mode_oper));
 		astman_append(s, "SIP-Sess-Refresh: %s\r\n", strefresher2str(peer->stimer.st_ref));
 		astman_append(s, "SIP-Sess-Expires: %d\r\n", peer->stimer.st_max_se);
@@ -16215,7 +16245,9 @@
 	ast_cli(a->fd, "  Call Events:            %s\n", sip_cfg.callevents ? "On" : "Off");
 	ast_cli(a->fd, "  Auth. Failure Events:   %s\n", global_authfailureevents ? "On" : "Off");
 
-	ast_cli(a->fd, "  T38 fax pt UDPTL:       %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT)));
+	ast_cli(a->fd, "  T.38 support:           %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT)));
+	ast_cli(a->fd, "  T.38 EC mode:           %s\n", faxec2str(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT)));
+	ast_cli(a->fd, "  T.38 MaxDtgrm:          %d\n", global_t38_maxdatagram);
 	if (!realtimepeers && !realtimeregs)
 		ast_cli(a->fd, "  SIP realtime:           Disabled\n" );
 	else
@@ -20493,6 +20525,7 @@
 
 		/* If T38 is needed but not present, then make it magically appear */
 		if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && !p->udptl && (p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr))) {
+			p->t38_maxdatagram = global_t38_maxdatagram;
 			set_t38_capabilities(p);
 		}
 
@@ -23726,6 +23759,48 @@
 }
 
 /*!
+  \brief Handle T.38 configuration options common to users and peers
+  \returns non-zero if any config options were handled, zero otherwise
+*/
+static int handle_t38_options(struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v,
+			      int *maxdatagram)
+{
+	int res = 1;
+
+	if (!strcasecmp(v->name, "t38pt_udptl")) {
+		char *buf = ast_strdupa(v->value);
+		char *word, *next = buf;
+
+		ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT);
+
+		while ((word = strsep(&next, ","))) {
+			if (ast_true(word) || !strcasecmp(word, "fec")) {
+				ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
+				ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_FEC);
+			} else if (!strcasecmp(word, "redundancy")) {
+				ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
+				ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY);
+			} else if (!strcasecmp(word, "none")) {
+				ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
+				ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL);
+			} else if (!strncasecmp(word, "maxdatagram=", 12)) {
+				if (sscanf(&word[12], "%30d", maxdatagram) != 1) {
+					ast_log(LOG_WARNING, "Invalid maxdatagram '%s' at line %d of %s\n", v->value, v->lineno, config);
+					*maxdatagram = global_t38_maxdatagram;
+				}
+			}
+		}
+	} else if (!strcasecmp(v->name, "t38pt_usertpsource")) {
+		ast_set_flag(&mask[1], SIP_PAGE2_UDPTL_DESTINATION);
+		ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_UDPTL_DESTINATION);
+	} else {
+		res = 0;
+	}
+
+	return res;
+}
+
+/*!
   \brief Handle flag-type options common to configuration of devices - peers
   \param flags array of two struct ast_flags
   \param mask array of two struct ast_flags
@@ -23851,34 +23926,12 @@
 	} else if (!strcasecmp(v->name, "faxdetect")) {
 		ast_set_flag(&mask[1], SIP_PAGE2_FAX_DETECT);
 		ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_FAX_DETECT);
-	} else if (!strcasecmp(v->name, "t38pt_udptl")) {
-		char buf[16], *word, *next = buf;
-
-		ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT);
-
-		ast_copy_string(buf, v->value, sizeof(buf));
-
-		while ((word = strsep(&next, ","))) {
-			if (ast_true(word) || !strcasecmp(word, "fec")) {
-				ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
-				ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_FEC);
-			} else if (!strcasecmp(word, "redundancy")) {
-				ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
-				ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY);
-			} else if (!strcasecmp(word, "none")) {
-				ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT);
-				ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL);
-			}
-		}
 	} else if (!strcasecmp(v->name, "rfc2833compensate")) {
 		ast_set_flag(&mask[1], SIP_PAGE2_RFC2833_COMPENSATE);
 		ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RFC2833_COMPENSATE);
 	} else if (!strcasecmp(v->name, "buggymwi")) {
 		ast_set_flag(&mask[1], SIP_PAGE2_BUGGY_MWI);
 		ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_BUGGY_MWI);
-	} else if (!strcasecmp(v->name, "t38pt_usertpsource")) {
-		ast_set_flag(&mask[1], SIP_PAGE2_UDPTL_DESTINATION);
-		ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_UDPTL_DESTINATION);
 	} else if (!strcasecmp(v->name, "constantssrc")) {
 		ast_set_flag(&mask[1], SIP_PAGE2_CONSTANT_SSRC);
 		ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_CONSTANT_SSRC);
@@ -24085,6 +24138,7 @@
 	peer->rtpkeepalive = global_rtpkeepalive;
 	peer->allowtransfer = sip_cfg.allowtransfer;
 	peer->autoframing = global_autoframing;
+	peer->t38_maxdatagram = global_t38_maxdatagram;
 	peer->qualifyfreq = global_qualifyfreq;
 	if (global_callcounter)
 		peer->call_limit=INT_MAX;
@@ -24242,6 +24296,9 @@
 	for (; v || ((v = alt) && !(alt=NULL)); v = v->next) {
 		if (!devstate_only) {
 			if (handle_common_options(&peerflags[0], &mask[0], v)) {
+				continue;
+			}
+			if (handle_t38_options(&peerflags[0], &mask[0], v, &peer->t38_maxdatagram)) {
 				continue;
 			}
 			if (!strcasecmp(v->name, "transport") && !ast_strlen_zero(v->value)) {
@@ -24955,6 +25012,7 @@
 	global_timer_b = 64 * DEFAULT_TIMER_T1;
 	global_t1min = DEFAULT_T1MIN;
 	global_qualifyfreq = DEFAULT_QUALIFYFREQ;
+	global_t38_maxdatagram = -1;
 
 	sip_cfg.matchexterniplocally = DEFAULT_MATCHEXTERNIPLOCALLY;
 
@@ -24971,6 +25029,9 @@
 	for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
 		if (handle_common_options(&global_flags[0], &dummy[0], v))
 			continue;
+		if (handle_t38_options(&global_flags[0], &dummy[0], v, &global_t38_maxdatagram)) {
+			continue;
+		}
 		/* handle jb conf */
 		if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
 			continue;

Modified: trunk/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/sip.conf.sample?view=diff&rev=222110&r1=222109&r2=222110
==============================================================================
--- trunk/configs/sip.conf.sample (original)
+++ trunk/configs/sip.conf.sample Mon Oct  5 14:45:00 2009
@@ -496,22 +496,32 @@
 ;callcounter = yes              ; Enable call counters on devices. This can be set per
                                 ; device too.
 
-;----------------------------------------- T.38 FAX PASSTHROUGH SUPPORT -----------------------
+;----------------------------------------- T.38 FAX SUPPORT ----------------------------------
 ;
 ; This setting is available in the [general] section as well as in device configurations.
-; Setting this to yes, enables T.38 fax (UDPTL) passthrough on SIP to SIP calls, provided
-; both parties have T38 support enabled in their Asterisk configuration
-; This has to be enabled in the general section for all devices to work. You can then
-; disable it on a per device basis.
-;
-; T.38 faxing only works in SIP to SIP calls. It defaults to off.
+; Setting this to yes enables T.38 FAX (UDPTL) on SIP calls; it defaults to off.
 ;
 ; t38pt_udptl = yes            ; Enables T.38 with FEC error correction.
 ; t38pt_udptl = yes,fec        ; Enables T.38 with FEC error correction.
 ; t38pt_udptl = yes,redundancy ; Enables T.38 with redundancy error correction.
 ; t38pt_udptl = yes,none       ; Enables T.38 with no error correction.
 ;
-; Faxs Detect will cause the SIP channel to jump to the 'fax' extension (if it exists)
+; In some cases, T.38 endpoints will provide a T38FaxMaxDatagram value (during T.38 setup) that
+; is based on an incorrect interpretation of the T.38 recommendation, and results in failures
+; because Asterisk does not believe it can send T.38 packets of a reasonable size to that
+; endpoint (Cisco media gateways are one example of this situation). In these cases, during a
+; T.38 call you will see warning messages on the console/in the logs from the Asterisk UDPTL
+; stack complaining about lack of buffer space to send T.38 FAX packets. If this occurs, you
+; can set an override (globally, or on a per-device basis) to make Asterisk ignore the
+; T38FaxMaxDatagram value specified by the other endpoint, and use a configured value instead.
+; This can be done by appending 'maxdatagram=<value>' to the t38pt_udptl configuration option,
+; like this:
+;
+; t38pt_udptl = yes,fec,maxdatagram=400 ; Enables T.38 with FEC error correction and overrides
+;                                       ; the other endpoint's provided value to assume we can
+;                                       ; send 400 byte T.38 FAX packets to it.
+;
+; FAX detection will cause the SIP channel to jump to the 'fax' extension (if it exists)
 ; after T.38 is successfully negotiated.
 ;
 ; faxdetect = yes              ; Default false

Modified: trunk/configs/udptl.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/udptl.conf.sample?view=diff&rev=222110&r1=222109&r2=222110
==============================================================================
--- trunk/configs/udptl.conf.sample (original)
+++ trunk/configs/udptl.conf.sample Mon Oct  5 14:45:00 2009
@@ -12,10 +12,6 @@
 ;
 ;udptlchecksums=no
 ;
-; The maximum length of a UDPTL packet
-;
-T38FaxMaxDatagram = 400
-;
 ; The number of error correction entries in a UDPTL packet
 ;
 udptlfecentries = 3

Modified: trunk/main/udptl.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/udptl.c?view=diff&rev=222110&r1=222109&r2=222110
==============================================================================
--- trunk/main/udptl.c (original)
+++ trunk/main/udptl.c Mon Oct  5 14:45:00 2009
@@ -711,7 +711,7 @@
 
 static void calculate_local_max_datagram(struct ast_udptl *udptl)
 {
-	unsigned int new_max = 200;
+	unsigned int new_max = 0;
 
 	/* calculate the amount of space required to receive an IFP
 	 * using the current error correction mode, and ensure that our
@@ -741,32 +741,28 @@
 
 static void calculate_far_max_ifp(struct ast_udptl *udptl)
 {
-	unsigned new_max = 60;
+	unsigned new_max = 0;
 
 	/* calculate the maximum IFP the local endpoint should
 	 * generate based on the far end's maximum datagram size
-	 * and the current error correction mode. some endpoints
-	 * bogus 'max datagram' values that would result in unusable
-	 * (too small) maximum IFP values, so we have a a reasonable
-	 * minimum value to ensure that we can actually construct
-	 * UDPTL packets.
+	 * and the current error correction mode.
 	 */
 	switch (udptl->error_correction_scheme) {
 	case UDPTL_ERROR_CORRECTION_NONE:
 		/* only need room for sequence number and length indicators */
-		new_max = MAX(new_max, udptl->far_max_datagram - 6);
+		new_max = udptl->far_max_datagram - 6;
 		break;
 	case UDPTL_ERROR_CORRECTION_REDUNDANCY:
 		/* need room for sequence number, length indicators and the
 		 * configured number of redundant packets
 		 */
-		new_max = MAX(new_max, (udptl->far_max_datagram - 8) / (udptl->error_correction_entries + 1));
+		new_max = (udptl->far_max_datagram - 8) / (udptl->error_correction_entries + 1);
 		break;
 	case UDPTL_ERROR_CORRECTION_FEC:
 		/* need room for sequence number, length indicators and a
 		 * a single IFP of the maximum size expected
 		 */
-		new_max = MAX(new_max, (udptl->far_max_datagram - 10) / 2);
+		new_max = (udptl->far_max_datagram - 10) / 2;
 		break;
 	}
 	/* subtract 25% of space for insurance */
@@ -998,7 +994,9 @@
 	}
 
 	if (f->datalen > s->far_max_ifp) {
-		ast_log(LOG_WARNING, "UDPTL asked to send %d bytes of IFP when far end only prepared to accept %d bytes; data loss may occur.\n", f->datalen, s->far_max_ifp);
+		ast_log(LOG_WARNING,
+			"UDPTL asked to send %d bytes of IFP when far end only prepared to accept %d bytes; data loss may occur. "
+			"You may need to override the T38FaxMaxDatagram value for this endpoint in the channel driver configuration.\n", f->datalen, s->far_max_ifp);
 	}
 
 	/* Save seq_no for debug output because udptl_build_packet increments it */




More information about the svn-commits mailing list