From cce1ec5463dee300bae74b20c4ed121b7c5c032f Mon Sep 17 00:00:00 2001
From: Tilghman Lesher <tilghman@meg.abyt.es>
Date: Wed, 2 Jul 2008 02:48:43 +0000
Subject: [PATCH] Change the global timer B to be dependent on the value of the
 T1 timer, as recommended in RFC 3261, instead of being hardcoded to 32
 seconds.  This is important for LANs, as it allows autocongestion to occur
 much more quickly, if desired by the local PBX administrator.  It also
 corrects a bug: if the T1 timer was increased beyond 500ms, then timer B
 would have been set at a much lower value than recommended. (closes issue
 #12544)  Reported by: kactus  Patches:        20080616__bug12544.diff.txt
 uploaded by Corydon76 (license 14)  Tested by: kactus

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@127297 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 channels/chan_sip.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 5c635911c4..74b20dd64e 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -21462,11 +21462,22 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
 				ast_log(LOG_WARNING, "'%s' is not a valid T1 time at line %d.  Using default.\n", v->value, v->lineno);
 				peer->timer_t1 = global_t1;
 			}
+			/* Note that Timer B is dependent upon T1 and MUST NOT be lower
+			 * than T1 * 64, according to RFC 3261, Section 17.1.1.2 */
+			if (peer->timer_b < peer->timer_t1 * 64) {
+				peer->timer_b = peer->timer_t1 * 64;
+			}
 		} else if (!strcasecmp(v->name, "timerb")) {
 			if ((sscanf(v->value, "%d", &peer->timer_b) != 1) || (peer->timer_b < 0)) {
 				ast_log(LOG_WARNING, "'%s' is not a valid Timer B time at line %d.  Using default.\n", v->value, v->lineno);
 				peer->timer_b = global_timer_b;
 			}
+			if (peer->timer_b < peer->timer_t1 * 64) {
+				static int warning = 0;
+				if (warning++ % 20 == 0) {
+					ast_log(LOG_WARNING, "Timer B has been set lower than recommended. (RFC 3261, 17.1.1.2)\n");
+				}
+			}
 		} else if (!strcasecmp(v->name, "setvar")) {
 			peer->chanvars = add_var(v->value, peer->chanvars);
 		} else if (!strcasecmp(v->name, "qualify")) {
@@ -21851,6 +21862,13 @@ static int reload_config(enum channelreloadreason reason)
 			sip_cfg.peer_rtupdate = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "ignoreregexpire")) {
 			sip_cfg.ignore_regexpire = ast_true(v->value);
+		} else if (!strcasecmp(v->name, "timert1")) {
+			/* Defaults to 500ms, but RFC 3261 states that it is recommended
+			 * for the value to be set higher, though a lower value is only
+			 * allowed on private networks unconnected to the Internet. */
+			global_t1 = atoi(v->value);
+			/* Note that timer B is dependent on the value of T1 */
+			global_timer_b = global_t1 * 64;
 		} else if (!strcasecmp(v->name, "t1min")) {
 			global_t1min = atoi(v->value);
 		} else if (!strcasecmp(v->name, "tcpenable")) {
-- 
GitLab