[asterisk-commits] oej: branch oej/teapot-1.8 r402921 - in /team/oej/teapot-1.8: channels/ chann...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Nov 21 07:29:39 CST 2013


Author: oej
Date: Thu Nov 21 07:29:37 2013
New Revision: 402921

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=402921
Log:
Adding timer C

Added:
    team/oej/teapot-1.8/patches/grape-sip-timeout-pdd-1.8.diff   (with props)
Modified:
    team/oej/teapot-1.8/channels/chan_sip.c
    team/oej/teapot-1.8/channels/sip/include/sip.h
    team/oej/teapot-1.8/configs/sip.conf.sample

Modified: team/oej/teapot-1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/channels/chan_sip.c?view=diff&rev=402921&r1=402920&r2=402921
==============================================================================
--- team/oej/teapot-1.8/channels/chan_sip.c (original)
+++ team/oej/teapot-1.8/channels/chan_sip.c Thu Nov 21 07:29:37 2013
@@ -740,6 +740,7 @@
 static int global_t1;           /*!< T1 time */
 static int global_t1min;        /*!< T1 roundtrip time minimum */
 static int global_timer_b;      /*!< Timer B - RFC 3261 Section 17.1.1.2 */
+static int global_timer_c;      /*!< Timer C - RFC 3261 Section 16.6 */
 static unsigned int global_autoframing; /*!< Turn autoframing on or off. */
 static int global_qualifyfreq;          /*!< Qualify frequency */
 static int global_qualify_gap;          /*!< Time between our group of peer pokes */
@@ -1290,6 +1291,7 @@
 static void *registry_unref(struct sip_registry *reg, char *tag);
 static int update_call_counter(struct sip_pvt *fup, int event);
 static int auto_congest(const void *arg);
+static int dialog_proceeding_timeout(const void *arg);
 static struct sip_pvt *find_call(struct sip_request *req, struct ast_sockaddr *addr, const int intended_method);
 static void free_old_route(struct sip_route *route);
 static void list_route(struct sip_route *route);
@@ -4280,6 +4282,9 @@
 		if (p->timer_b == 0) {
 			p->timer_b = global_timer_b;  /* Set timer B if not set (RFC 3261) */
 		}
+		if (p->timer_c == 0) {
+			p->timer_c = global_timer_c;  /* Set timer C if not set (RFC 3261) */
+		}
 		ms = p->timer_t1 * 64;
 	}
 	if (sip_debug_test_pvt(p)) {
@@ -5798,6 +5803,12 @@
 	else
 		dialog->timer_b = 64 * dialog->timer_t1;
 
+	if (peer->timer_c) {
+		dialog->timer_c = peer->timer_c;
+	} else {
+		dialog->timer_c = global_timer_c;
+	}
+
 	if ((ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
 	    (ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
 		dialog->noncodeccapability |= AST_RTP_DTMF;
@@ -5852,6 +5863,7 @@
 
 	dialog->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */
 	dialog->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */
+	dialog->timer_c = global_timer_c; /* Default SIP transaction timer C (RFC 3261) */
 	peer = find_peer(peername, NULL, TRUE, FINDPEERS, FALSE, 0);
 
 	if (peer) {
@@ -5956,6 +5968,30 @@
 	return 0;
 }
 
+/*! \brief Scheduled congestion on a call when no responses has been received for 3 minutes (or configured)
+ * Only called by the scheduler, must return the reference when done.
+ */
+static int dialog_proceeding_timeout(const void *arg)
+{
+	struct sip_pvt *p = (struct sip_pvt *)arg;
+
+	sip_pvt_lock(p);
+	p->timercid = -1;	/* event gone, will not be rescheduled */
+	if (p->owner) {
+		/* XXX fails on possible deadlock */
+		if (!ast_channel_trylock(p->owner)) {
+			append_history(p, "Cong", "Auto-congesting (timer C)");
+			ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
+			ast_channel_unlock(p->owner);
+		}
+
+		/* Give the channel a chance to act before we proceed with destruction */
+		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+	}
+	sip_pvt_unlock(p);
+	dialog_unref(p, "unreffing arg passed into timer C callback (p->timerc)");
+	return 0;
+}
 
 /*! \brief Initiate SIP call from PBX
  *      used from the dial() application      */
@@ -8075,6 +8111,7 @@
 	p->rtcpeventid = -1;
 	p->initid = -1;
 	p->waitid = -1;
+	p->timercid = -1;
 	p->reinviteid = -1;
 	p->autokillid = -1;
 	p->request_queue_sched_id = -1;
@@ -8091,6 +8128,7 @@
 	if (intended_method != SIP_OPTIONS) {	/* Peerpoke has it's own system */
 		p->timer_t1 = global_t1;	/* Default SIP retransmission timer T1 (RFC 3261) */
 		p->timer_b = global_timer_b;	/* Default SIP transaction timer B (RFC 3261) */
+		p->timer_c = global_timer_c;	/* Default SIP transaction timer B (RFC 3261) */
 	}
 
 	if (!addr) {
@@ -16758,6 +16796,11 @@
  		p->timer_b = peer->timer_b;
  	else
  		p->timer_b = 64 * p->timer_t1;
+ 	/* Set timer C to control transaction timeouts */
+ 	if (peer->timer_c)
+ 		p->timer_c = peer->timer_c;
+ 	else
+ 		p->timer_c = global_timer_c;
 
 	p->allowtransfer = peer->allowtransfer;
 
@@ -18320,6 +18363,7 @@
 		ast_cli(fd, "  DTMFmode     : %s\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF)));
 		ast_cli(fd, "  Timer T1     : %d\n", peer->timer_t1);
 		ast_cli(fd, "  Timer B      : %d\n", peer->timer_b);
+		ast_cli(fd, "  Timer C      : %d\n", peer->timer_c);
 		ast_cli(fd, "  ToHost       : %s\n", peer->tohost);
 		ast_cli(fd, "  Addr->IP     : %s\n", ast_sockaddr_stringify(&peer->addr));
 		ast_cli(fd, "  Defaddr->IP  : %s\n", ast_sockaddr_stringify(&peer->defaddr));
@@ -18598,6 +18642,7 @@
                                         "__sip_autodestruct",
                                         "expire_register",
                                         "auto_congest",
+					"dialog_proceeding_timeout",
                                         "sip_reg_timeout",
                                         "sip_poke_peer_s",
                                         "sip_poke_noanswer",
@@ -18607,6 +18652,7 @@
                                      __sip_autodestruct,
                                      expire_register,
                                      auto_congest,
+				     dialog_proceeding_timeout,
                                      sip_reg_timeout,
                                      sip_poke_peer_s,
                                      sip_poke_noanswer,
@@ -19029,6 +19075,7 @@
  	ast_cli(a->fd, "  Timer T1:               %d\n", global_t1);
 	ast_cli(a->fd, "  Timer T1 minimum:       %d\n", global_t1min);
  	ast_cli(a->fd, "  Timer B:                %d\n", global_timer_b);
+ 	ast_cli(a->fd, "  Timer C:                %d\n", global_timer_c);
 	ast_cli(a->fd, "  No premature media:     %s\n", AST_CLI_YESNO(global_prematuremediafilter));
 	ast_cli(a->fd, "  Early media focus:      %s\n", AST_CLI_YESNO(sip_cfg.early_media_focus));
 	ast_cli(a->fd, "  Max forwards:           %d\n", sip_cfg.default_max_forwards);
@@ -20893,8 +20940,27 @@
 		resp = 183;
 
  	/* Any response between 100 and 199 is PROCEEDING */
- 	if (resp >= 100 && resp < 200 && p->invitestate == INV_CALLING)
+ 	if (resp >= 100 && resp < 200 && p->invitestate == INV_CALLING) {
  		p->invitestate = INV_PROCEEDING;
+		if (p->timercid == -1) {
+			/* Trigger timer C */
+			AST_SCHED_REPLACE_UNREF(p->timercid, sched, p->timer_c, dialog_proceeding_timeout, p,
+						dialog_unref(_data, "dialog ptr dec when SCHED_REPLACE del op succeeded"),
+						dialog_unref(p, "dialog ptr dec when SCHED_REPLACE add failed"),
+						dialog_ref(p, "dialog ptr inc when SCHED_REPLACE add succeeded") );
+			ast_debug(3, "Setting Timer C to %d \n", p->timer_c);
+		}
+	}
+
+	if (resp >= 200) {
+		/* Delete timer C - we have a response */
+		AST_SCHED_DEL_UNREF(sched, p->timercid, dialog_unref(p, "when you delete the timercid sched, you should dec the refcount for the stored dialog ptr"));
+		ast_debug(3, "Deleting Timer C (response received)\n");
+	} else {
+		/* reset timer C */
+		AST_SCHED_REPLACE_VARIABLE(p->timercid, sched, p->timer_c, dialog_proceeding_timeout, p, 1);
+		ast_debug(3, "Resetting Timer C to %d \n", p->timer_c);
+	}
 
  	/* Final response, not 200 ? */
  	if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA ))
@@ -28267,6 +28333,7 @@
 	peer->stimer.st_max_se = global_max_se;
 	peer->timer_t1 = global_t1;
 	peer->timer_b = global_timer_b;
+	peer->timer_c = global_timer_c;
 	clear_peer_mailboxes(peer);
 	peer->disallowed_methods = sip_cfg.disallowed_methods;
 	peer->transports = default_transports;
@@ -28357,7 +28424,7 @@
 	int firstpass = 1;
 	uint16_t port = 0;
 	int format = 0;		/* Ama flags */
-	int timerb_set = 0, timert1_set = 0;
+	int timerb_set = 0, timert1_set = 0, timerc_set = 0;
 	time_t regseconds = 0;
 	struct ast_flags peerflags[3] = {{(0)}};
 	struct ast_flags mask[3] = {{(0)}};
@@ -28710,6 +28777,12 @@
 					peer->timer_b = global_timer_b;
 				}
 				timerb_set = 1;
+			} else if (!strcasecmp(v->name, "timerc")) {
+				if ((sscanf(v->value, "%30d", &peer->timer_c) != 1) || (peer->timer_c > 100)) {
+					ast_log(LOG_WARNING, "'%s' is not a valid Timer C time at line %d (above 100, default 180 s).  Using configured default %d.\n", v->value, v->lineno, global_timer_c);
+					peer->timer_c = global_timer_c;
+				}
+				timerc_set = 1;
 			} else if (!strcasecmp(v->name, "setvar")) {
 				peer->chanvars = add_var(v->value, peer->chanvars);
 			} else if (!strcasecmp(v->name, "header")) {
@@ -29286,6 +29359,7 @@
 	global_authfailureevents = FALSE;
 	global_t1 = DEFAULT_TIMER_T1;
 	global_timer_b = 64 * DEFAULT_TIMER_T1;
+	global_timer_c = 180;	/* 3 minutes per RFC 3261 */
 	global_t1min = DEFAULT_T1MIN;
 	global_qualifyfreq = DEFAULT_QUALIFYFREQ;
 	global_t38_maxdatagram = -1;
@@ -29371,6 +29445,12 @@
 				ast_log(LOG_WARNING, "Invalid value for timerb ('%s').  Setting to default ('%d').\n", v->value, global_timer_b);
 			}
 			timerb_set = 1;
+		} else if (!strcasecmp(v->name, "timerc")) {
+			int tmp = atoi(v->value);
+			if (tmp < 100) {
+				global_timer_c = DEFAULT_TIMER_C;
+				ast_log(LOG_WARNING, "Invalid value (< 100 s) for timerc ('%s').  Setting to default ('%d').\n", v->value, global_timer_c);
+			}
 		} else if (!strcasecmp(v->name, "t1min")) {
 			global_t1min = atoi(v->value);
 		} else if (!strcasecmp(v->name, "transport")) {
@@ -31973,7 +32053,8 @@
 	MEMBER(sip_peer, maxms, AST_DATA_MILLISECONDS)		\
 	MEMBER(sip_peer, qualifyfreq, AST_DATA_MILLISECONDS)	\
 	MEMBER(sip_peer, timer_t1, AST_DATA_MILLISECONDS)	\
-	MEMBER(sip_peer, timer_b, AST_DATA_MILLISECONDS)
+	MEMBER(sip_peer, timer_b, AST_DATA_MILLISECONDS)	\
+	MEMBER(sip_peer, timer_c, AST_DATA_SECONDS)
 
 AST_DATA_STRUCTURE(sip_peer, DATA_EXPORT_SIP_PEER);
 

Modified: team/oej/teapot-1.8/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/channels/sip/include/sip.h?view=diff&rev=402921&r1=402920&r2=402921
==============================================================================
--- team/oej/teapot-1.8/channels/sip/include/sip.h (original)
+++ team/oej/teapot-1.8/channels/sip/include/sip.h Thu Nov 21 07:29:37 2013
@@ -87,6 +87,7 @@
 
 #define DEFAULT_RETRANS           1000        /*!< How frequently to retransmit Default: 2 * 500 ms in RFC 3261 */
 #define DEFAULT_TIMER_T1          500         /*!< SIP timer T1 (according to RFC 3261) */
+#define DEFAULT_TIMER_C           180         /*!< SIP timer C (according to RFC 3261) */
 #define SIP_TRANS_TIMEOUT         64 * DEFAULT_TIMER_T1 /*!< SIP request timeout (rfc 3261) 64*T1
                                                          *  \todo Use known T1 for timeout (peerpoke)
                                                          */
@@ -1036,6 +1037,7 @@
 	unsigned short req_secure_signaling:1;/*!< Whether we are required to have secure signaling or not */
 	int timer_t1;                     /*!< SIP timer T1, ms rtt */
 	int timer_b;                      /*!< SIP timer B, ms */
+	int timer_c;                      /*!< SIP timer B, ms */
 	unsigned int sipoptions;          /*!< Supported SIP options on the other end */
 	unsigned int reqsipoptions;       /*!< Required SIP options on the other end */
 	struct ast_codec_pref prefs;      /*!< codec prefs */
@@ -1096,6 +1098,7 @@
 
 	int initid;                         /*!< Auto-congest ID if appropriate (scheduler) */
 	int waitid;                         /*!< Wait ID for scheduler after 491 or other delays */
+	int timercid;                       /*!< Scheduler ID for timer C delays */
 	int reinviteid;                     /*!< Reinvite in case of provisional, but no final response */
 	int autokillid;                     /*!< Auto-kill ID (scheduler) */
 	int rtcpeventid;                        /*!< Scheduler ID for RTCP Events */
@@ -1297,6 +1300,7 @@
 	struct sip_st_cfg stimer;       /*!<  SIP Session-Timers */
 	int timer_t1;                   /*!<  The maximum T1 value for the peer */
 	int timer_b;                    /*!<  The maximum timer B (transaction timeouts) */
+	int timer_c;                    /*!<  The timer c (transaction timeouts) */
 	int fromdomainport;             /*!<  The From: domain port */
 
 	/*XXX Seems like we suddenly have two flags with the same content. Why? To be continued... */

Modified: team/oej/teapot-1.8/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/configs/sip.conf.sample?view=diff&rev=402921&r1=402920&r2=402921
==============================================================================
--- team/oej/teapot-1.8/configs/sip.conf.sample (original)
+++ team/oej/teapot-1.8/configs/sip.conf.sample Thu Nov 21 07:29:37 2013
@@ -534,9 +534,13 @@
 ;timert1=500                    ; Default T1 timer
                                 ; Defaults to 500 ms or the measured round-trip
                                 ; time to a peer (qualify=yes).
-;timerb=32000                   ; Call setup timer. If a provisional response is not received
+;timerb=32000                   ; Call setup timer. If a final response is not received
                                 ; in this amount of time, the call will autocongest
                                 ; Defaults to 64*timert1
+;timerc=420                     ; Call setup timer. If a provisional response is not received
+				; during this time - the call will autocongest. Default 180 secs.
+				; Needs to be higher than 100. RFC says MUST be higher than 
+				; or equal to 180.
 
 ;--------------------------- RTP timers ----------------------------------------------------
 ; These timers are currently used for both audio and video streams. The RTP timeouts

Added: team/oej/teapot-1.8/patches/grape-sip-timeout-pdd-1.8.diff
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/patches/grape-sip-timeout-pdd-1.8.diff?view=auto&rev=402921
==============================================================================
--- team/oej/teapot-1.8/patches/grape-sip-timeout-pdd-1.8.diff (added)
+++ team/oej/teapot-1.8/patches/grape-sip-timeout-pdd-1.8.diff Thu Nov 21 07:29:37 2013
@@ -1,0 +1,331 @@
+Index: channels/chan_sip.c
+===================================================================
+--- channels/chan_sip.c	(.../branches/1.8)	(revision 402920)
++++ channels/chan_sip.c	(.../team/oej/grape-sip-timeout-pdd-1.8)	(revision 402920)
+@@ -736,6 +736,7 @@
+ static int global_t1;           /*!< T1 time */
+ static int global_t1min;        /*!< T1 roundtrip time minimum */
+ static int global_timer_b;      /*!< Timer B - RFC 3261 Section 17.1.1.2 */
++static int global_timer_c;      /*!< Timer C - RFC 3261 Section 16.6 */
+ static unsigned int global_autoframing; /*!< Turn autoframing on or off. */
+ static int global_qualifyfreq;          /*!< Qualify frequency */
+ static int global_qualify_gap;          /*!< Time between our group of peer pokes */
+@@ -1285,6 +1286,7 @@
+ static void *registry_unref(struct sip_registry *reg, char *tag);
+ static int update_call_counter(struct sip_pvt *fup, int event);
+ static int auto_congest(const void *arg);
++static int dialog_proceeding_timeout(const void *arg);
+ static struct sip_pvt *find_call(struct sip_request *req, struct ast_sockaddr *addr, const int intended_method);
+ static void free_old_route(struct sip_route *route);
+ static void list_route(struct sip_route *route);
+@@ -4271,6 +4273,9 @@
+ 		if (p->timer_b == 0) {
+ 			p->timer_b = global_timer_b;  /* Set timer B if not set (RFC 3261) */
+ 		}
++		if (p->timer_c == 0) {
++			p->timer_c = global_timer_c;  /* Set timer C if not set (RFC 3261) */
++		}
+ 		ms = p->timer_t1 * 64;
+ 	}
+ 	if (sip_debug_test_pvt(p)) {
+@@ -5756,6 +5761,12 @@
+ 	else
+ 		dialog->timer_b = 64 * dialog->timer_t1;
+ 
++	if (peer->timer_c) {
++		dialog->timer_c = peer->timer_c;
++	} else {
++		dialog->timer_c = global_timer_c;
++	}
++
+ 	if ((ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
+ 	    (ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
+ 		dialog->noncodeccapability |= AST_RTP_DTMF;
+@@ -5806,6 +5817,7 @@
+ 
+ 	dialog->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */
+ 	dialog->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */
++	dialog->timer_c = global_timer_c; /* Default SIP transaction timer C (RFC 3261) */
+ 	peer = find_peer(peername, NULL, TRUE, FINDPEERS, FALSE, 0);
+ 
+ 	if (peer) {
+@@ -5910,7 +5922,31 @@
+ 	return 0;
+ }
+ 
++/*! \brief Scheduled congestion on a call when no responses has been received for 3 minutes (or configured)
++ * Only called by the scheduler, must return the reference when done.
++ */
++static int dialog_proceeding_timeout(const void *arg)
++{
++	struct sip_pvt *p = (struct sip_pvt *)arg;
+ 
++	sip_pvt_lock(p);
++	p->timercid = -1;	/* event gone, will not be rescheduled */
++	if (p->owner) {
++		/* XXX fails on possible deadlock */
++		if (!ast_channel_trylock(p->owner)) {
++			append_history(p, "Cong", "Auto-congesting (timer C)");
++			ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
++			ast_channel_unlock(p->owner);
++		}
++
++		/* Give the channel a chance to act before we proceed with destruction */
++		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
++	}
++	sip_pvt_unlock(p);
++	dialog_unref(p, "unreffing arg passed into timer C callback (p->timerc)");
++	return 0;
++}
++
+ /*! \brief Initiate SIP call from PBX
+  *      used from the dial() application      */
+ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
+@@ -8160,6 +8196,7 @@
+ 	p->method = intended_method;
+ 	p->initid = -1;
+ 	p->waitid = -1;
++	p->timercid = -1;
+ 	p->reinviteid = -1;
+ 	p->autokillid = -1;
+ 	p->request_queue_sched_id = -1;
+@@ -8176,6 +8213,7 @@
+ 	if (intended_method != SIP_OPTIONS) {	/* Peerpoke has it's own system */
+ 		p->timer_t1 = global_t1;	/* Default SIP retransmission timer T1 (RFC 3261) */
+ 		p->timer_b = global_timer_b;	/* Default SIP transaction timer B (RFC 3261) */
++		p->timer_c = global_timer_c;	/* Default SIP transaction timer B (RFC 3261) */
+ 	}
+ 
+ 	if (!addr) {
+@@ -16702,6 +16740,11 @@
+  		p->timer_b = peer->timer_b;
+  	else
+  		p->timer_b = 64 * p->timer_t1;
++ 	/* Set timer C to control transaction timeouts */
++ 	if (peer->timer_c)
++ 		p->timer_c = peer->timer_c;
++ 	else
++ 		p->timer_c = global_timer_c;
+ 
+ 	p->allowtransfer = peer->allowtransfer;
+ 
+@@ -18257,6 +18300,7 @@
+ 		ast_cli(fd, "  DTMFmode     : %s\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF)));
+ 		ast_cli(fd, "  Timer T1     : %d\n", peer->timer_t1);
+ 		ast_cli(fd, "  Timer B      : %d\n", peer->timer_b);
++		ast_cli(fd, "  Timer C      : %d\n", peer->timer_c);
+ 		ast_cli(fd, "  ToHost       : %s\n", peer->tohost);
+ 		ast_cli(fd, "  Addr->IP     : %s\n", ast_sockaddr_stringify(&peer->addr));
+ 		ast_cli(fd, "  Defaddr->IP  : %s\n", ast_sockaddr_stringify(&peer->defaddr));
+@@ -18533,6 +18577,7 @@
+                                         "__sip_autodestruct",
+                                         "expire_register",
+                                         "auto_congest",
++					"dialog_proceeding_timeout",
+                                         "sip_reg_timeout",
+                                         "sip_poke_peer_s",
+                                         "sip_poke_noanswer",
+@@ -18542,6 +18587,7 @@
+                                      __sip_autodestruct,
+                                      expire_register,
+                                      auto_congest,
++				     dialog_proceeding_timeout,
+                                      sip_reg_timeout,
+                                      sip_poke_peer_s,
+                                      sip_poke_noanswer,
+@@ -18955,6 +19001,7 @@
+  	ast_cli(a->fd, "  Timer T1:               %d\n", global_t1);
+ 	ast_cli(a->fd, "  Timer T1 minimum:       %d\n", global_t1min);
+  	ast_cli(a->fd, "  Timer B:                %d\n", global_timer_b);
++ 	ast_cli(a->fd, "  Timer C:                %d\n", global_timer_c);
+ 	ast_cli(a->fd, "  No premature media:     %s\n", AST_CLI_YESNO(global_prematuremediafilter));
+ 	ast_cli(a->fd, "  Max forwards:           %d\n", sip_cfg.default_max_forwards);
+ 
+@@ -20771,9 +20818,28 @@
+ 		resp = 183;
+ 
+  	/* Any response between 100 and 199 is PROCEEDING */
+- 	if (resp >= 100 && resp < 200 && p->invitestate == INV_CALLING)
++ 	if (resp >= 100 && resp < 200 && p->invitestate == INV_CALLING) {
+  		p->invitestate = INV_PROCEEDING;
++		if (p->timercid == -1) {
++			/* Trigger timer C */
++			AST_SCHED_REPLACE_UNREF(p->timercid, sched, p->timer_c, dialog_proceeding_timeout, p,
++						dialog_unref(_data, "dialog ptr dec when SCHED_REPLACE del op succeeded"),
++						dialog_unref(p, "dialog ptr dec when SCHED_REPLACE add failed"),
++						dialog_ref(p, "dialog ptr inc when SCHED_REPLACE add succeeded") );
++			ast_debug(3, "Setting Timer C to %d \n", p->timer_c);
++		}
++	}
+ 
++	if (resp >= 200) {
++		/* Delete timer C - we have a response */
++		AST_SCHED_DEL_UNREF(sched, p->timercid, dialog_unref(p, "when you delete the timercid sched, you should dec the refcount for the stored dialog ptr"));
++		ast_debug(3, "Deleting Timer C (response received)\n");
++	} else {
++		/* reset timer C */
++		AST_SCHED_REPLACE_VARIABLE(p->timercid, sched, p->timer_c, dialog_proceeding_timeout, p, 1);
++		ast_debug(3, "Resetting Timer C to %d \n", p->timer_c);
++	}
++
+  	/* Final response, not 200 ? */
+  	if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA ))
+  		p->invitestate = INV_COMPLETED;
+@@ -27986,6 +28052,7 @@
+ 	peer->stimer.st_max_se = global_max_se;
+ 	peer->timer_t1 = global_t1;
+ 	peer->timer_b = global_timer_b;
++	peer->timer_c = global_timer_c;
+ 	clear_peer_mailboxes(peer);
+ 	peer->disallowed_methods = sip_cfg.disallowed_methods;
+ 	peer->transports = default_transports;
+@@ -28076,7 +28143,7 @@
+ 	int firstpass = 1;
+ 	uint16_t port = 0;
+ 	int format = 0;		/* Ama flags */
+-	int timerb_set = 0, timert1_set = 0;
++	int timerb_set = 0, timert1_set = 0, timerc_set = 0;
+ 	time_t regseconds = 0;
+ 	struct ast_flags peerflags[3] = {{(0)}};
+ 	struct ast_flags mask[3] = {{(0)}};
+@@ -28429,6 +28496,12 @@
+ 					peer->timer_b = global_timer_b;
+ 				}
+ 				timerb_set = 1;
++			} else if (!strcasecmp(v->name, "timerc")) {
++				if ((sscanf(v->value, "%30d", &peer->timer_c) != 1) || (peer->timer_c > 100)) {
++					ast_log(LOG_WARNING, "'%s' is not a valid Timer C time at line %d (above 100, default 180 s).  Using configured default %d.\n", v->value, v->lineno, global_timer_c);
++					peer->timer_c = global_timer_c;
++				}
++				timerc_set = 1;
+ 			} else if (!strcasecmp(v->name, "setvar")) {
+ 				peer->chanvars = add_var(v->value, peer->chanvars);
+ 			} else if (!strcasecmp(v->name, "header")) {
+@@ -29002,6 +29075,7 @@
+ 	global_authfailureevents = FALSE;
+ 	global_t1 = DEFAULT_TIMER_T1;
+ 	global_timer_b = 64 * DEFAULT_TIMER_T1;
++	global_timer_c = 180;	/* 3 minutes per RFC 3261 */
+ 	global_t1min = DEFAULT_T1MIN;
+ 	global_qualifyfreq = DEFAULT_QUALIFYFREQ;
+ 	global_t38_maxdatagram = -1;
+@@ -29087,6 +29161,12 @@
+ 				ast_log(LOG_WARNING, "Invalid value for timerb ('%s').  Setting to default ('%d').\n", v->value, global_timer_b);
+ 			}
+ 			timerb_set = 1;
++		} else if (!strcasecmp(v->name, "timerc")) {
++			int tmp = atoi(v->value);
++			if (tmp < 100) {
++				global_timer_c = DEFAULT_TIMER_C;
++				ast_log(LOG_WARNING, "Invalid value (< 100 s) for timerc ('%s').  Setting to default ('%d').\n", v->value, global_timer_c);
++			}
+ 		} else if (!strcasecmp(v->name, "t1min")) {
+ 			global_t1min = atoi(v->value);
+ 		} else if (!strcasecmp(v->name, "transport")) {
+@@ -31668,7 +31748,8 @@
+ 	MEMBER(sip_peer, maxms, AST_DATA_MILLISECONDS)		\
+ 	MEMBER(sip_peer, qualifyfreq, AST_DATA_MILLISECONDS)	\
+ 	MEMBER(sip_peer, timer_t1, AST_DATA_MILLISECONDS)	\
+-	MEMBER(sip_peer, timer_b, AST_DATA_MILLISECONDS)
++	MEMBER(sip_peer, timer_b, AST_DATA_MILLISECONDS)	\
++	MEMBER(sip_peer, timer_c, AST_DATA_SECONDS)
+ 
+ AST_DATA_STRUCTURE(sip_peer, DATA_EXPORT_SIP_PEER);
+ 
+Index: channels/sip/include/sip.h
+===================================================================
+--- channels/sip/include/sip.h	(.../branches/1.8)	(revision 402920)
++++ channels/sip/include/sip.h	(.../team/oej/grape-sip-timeout-pdd-1.8)	(revision 402920)
+@@ -87,6 +87,7 @@
+ 
+ #define DEFAULT_RETRANS           1000        /*!< How frequently to retransmit Default: 2 * 500 ms in RFC 3261 */
+ #define DEFAULT_TIMER_T1          500         /*!< SIP timer T1 (according to RFC 3261) */
++#define DEFAULT_TIMER_C           180         /*!< SIP timer C (according to RFC 3261) */
+ #define SIP_TRANS_TIMEOUT         64 * DEFAULT_TIMER_T1 /*!< SIP request timeout (rfc 3261) 64*T1
+                                                          *  \todo Use known T1 for timeout (peerpoke)
+                                                          */
+@@ -1018,6 +1019,7 @@
+ 	unsigned short req_secure_signaling:1;/*!< Whether we are required to have secure signaling or not */
+ 	int timer_t1;                     /*!< SIP timer T1, ms rtt */
+ 	int timer_b;                      /*!< SIP timer B, ms */
++	int timer_c;                      /*!< SIP timer B, ms */
+ 	unsigned int sipoptions;          /*!< Supported SIP options on the other end */
+ 	unsigned int reqsipoptions;       /*!< Required SIP options on the other end */
+ 	struct ast_codec_pref prefs;      /*!< codec prefs */
+@@ -1078,6 +1080,7 @@
+ 
+ 	int initid;                         /*!< Auto-congest ID if appropriate (scheduler) */
+ 	int waitid;                         /*!< Wait ID for scheduler after 491 or other delays */
++	int timercid;                       /*!< Scheduler ID for timer C delays */
+ 	int reinviteid;                     /*!< Reinvite in case of provisional, but no final response */
+ 	int autokillid;                     /*!< Auto-kill ID (scheduler) */
+ 	int t38id;                          /*!< T.38 Response ID */
+@@ -1271,6 +1274,7 @@
+ 	struct sip_st_cfg stimer;       /*!<  SIP Session-Timers */
+ 	int timer_t1;                   /*!<  The maximum T1 value for the peer */
+ 	int timer_b;                    /*!<  The maximum timer B (transaction timeouts) */
++	int timer_c;                    /*!<  The timer c (transaction timeouts) */
+ 	int fromdomainport;             /*!<  The From: domain port */
+ 
+ 	/*XXX Seems like we suddenly have two flags with the same content. Why? To be continued... */
+Index: configs/sip.conf.sample
+===================================================================
+--- configs/sip.conf.sample	(.../branches/1.8)	(revision 402920)
++++ configs/sip.conf.sample	(.../team/oej/grape-sip-timeout-pdd-1.8)	(revision 402920)
+@@ -513,9 +513,13 @@
+ ;timert1=500                    ; Default T1 timer
+                                 ; Defaults to 500 ms or the measured round-trip
+                                 ; time to a peer (qualify=yes).
+-;timerb=32000                   ; Call setup timer. If a provisional response is not received
++;timerb=32000                   ; Call setup timer. If a final response is not received
+                                 ; in this amount of time, the call will autocongest
+                                 ; Defaults to 64*timert1
++;timerc=420                     ; Call setup timer. If a provisional response is not received
++				; during this time - the call will autocongest. Default 180 secs.
++				; Needs to be higher than 100. RFC says MUST be higher than 
++				; or equal to 180.
+ 
+ ;--------------------------- RTP timers ----------------------------------------------------
+ ; These timers are currently used for both audio and video streams. The RTP timeouts
+Index: README.grape
+===================================================================
+--- README.grape	(.../branches/1.8)	(revision 0)
++++ README.grape	(.../team/oej/grape-sip-timeout-pdd-1.8)	(revision 402920)
+@@ -0,0 +1,22 @@
++Edvina AB
++Olle E. Johansson
++
++Start date: 2013-11-21
++
++
++
++
++
++
++
++
++Grape - implement timer C in Chan_sip
++=====================================
++
++If we call a server and that server just sends 100 trying, we wait forever. This is not good.
++In order to fix this, this branch will implement a timer C that is normally a proxy timer.
++This fires after 3 minutes if there's no provisional response at all received from a device.
++
++When the timer fires, the call attempt is killed..
++
++The timer is set per channel, or per device.
+
+Property changes on: README.grape
+___________________________________________________________________
+Added: svn:mime-type
+## -0,0 +1 ##
++text/plain
+\ No newline at end of property
+Added: svn:keywords
+## -0,0 +1 ##
++Author Date Id Revision
+\ No newline at end of property
+Added: svn:eol-style
+## -0,0 +1 ##
++native
+\ No newline at end of property

Propchange: team/oej/teapot-1.8/patches/grape-sip-timeout-pdd-1.8.diff
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/oej/teapot-1.8/patches/grape-sip-timeout-pdd-1.8.diff
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/oej/teapot-1.8/patches/grape-sip-timeout-pdd-1.8.diff
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the asterisk-commits mailing list