Przeglądaj źródła

tm: CANCEL reason header on/off switches

Config support (both runtime and modparam) for turning on/off
Reason header support in locally generated or end-to-end
hop-by-hop CANCELs:
- local_cancel_reason =  0|1. Default 1 (on).
- e2e_cancel_reason= 0|1. (Default 1 (on).

End-to-end CANCEL reason header copy can also be turned on/off on
a per transaction basis: t_set_no_e2e_cancel_reason(0|1).
E.g.:
	t_set_no_e2e_cancel_reason(1); # disable reason copy
	t_relay();

t_set_no_e2e_cancel_reason(0) can be used to enable reason header
on a per transaction basis, if the default is disabled
(e2e_cancel_reason is set to 0).
Andrei Pelinescu-Onciul 15 lat temu
rodzic
commit
984eec800f

+ 14 - 5
modules/tm/config.c

@@ -24,10 +24,9 @@
  *  2008-02-05	adapting tm module for the configuration framework (Miklos)
  *  2008-02-05	adapting tm module for the configuration framework (Miklos)
  */
  */
 
 
-/*!
- * \file 
- * \brief TM :: Configuration
- * \ingroup tm
+/** TM :: Runtime configuration variables.
+ * @file
+ * @ingroup tm
  */
  */
 
 
 
 
@@ -94,7 +93,11 @@ struct cfg_group_tm	default_tm_cfg = {
 	1,	/* cancel_b_method used for e2e and 6xx cancels*/
 	1,	/* cancel_b_method used for e2e and 6xx cancels*/
 	1,	/* reparse_on_dns_failover */
 	1,	/* reparse_on_dns_failover */
 	0, /* disable_6xx, by default off */
 	0, /* disable_6xx, by default off */
-	0  /* local_ack_mode, default 0 (rfc3261 conformant) */
+	0,  /* local_ack_mode, default 0 (rfc3261 conformant) */
+	1, /* local_cancel_reason -- add Reason header to locally generated
+		  CANCELs; on by default */
+	1  /* e2e_cancel_reason -- copy the Reason headers from incoming CANCELs
+		  into the corresp. hop-by-hop CANCELs, on by default */
 };
 };
 
 
 void	*tm_cfg = &default_tm_cfg;
 void	*tm_cfg = &default_tm_cfg;
@@ -196,5 +199,11 @@ cfg_def_t	tm_cfg_def[] = {
 		" it is not set to 0 but allows dealing with NATed contacts in some "
 		" it is not set to 0 but allows dealing with NATed contacts in some "
 		"simple cases)"
 		"simple cases)"
 		},
 		},
+	{"local_cancel_reason",	CFG_VAR_INT | CFG_ATOMIC,	0, 1, 0, 0,
+		"if set to 1, a Reason header is added to locally generated CANCELs"
+		" (see RFC3326)" },
+	{"e2e_cancel_reason",	CFG_VAR_INT | CFG_ATOMIC,	0, 1, 0, 0,
+		"if set to 1, Reason headers from received CANCELs are copied into"
+		" the corresponding generated hop-by-hop CANCELs"},
 	{0, 0, 0, 0, 0, 0}
 	{0, 0, 0, 0, 0, 0}
 };
 };

+ 5 - 4
modules/tm/config.h

@@ -21,10 +21,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  */
 
 
-/*!
- * \file 
- * \brief TM :: Configuration
- * \ingroup tm
+/** TM :: Runtime configuration variables.
+ * @file
+ * @ingroup tm
  */
  */
 
 
 
 
@@ -136,6 +135,8 @@ struct cfg_group_tm {
 	int	reparse_on_dns_failover;
 	int	reparse_on_dns_failover;
 	int disable_6xx;
 	int disable_6xx;
 	int local_ack_mode;
 	int local_ack_mode;
+	int local_cancel_reason;
+	int e2e_cancel_reason;
 };
 };
 
 
 extern struct cfg_group_tm	default_tm_cfg;
 extern struct cfg_group_tm	default_tm_cfg;

+ 4 - 4
modules/tm/h_table.h

@@ -40,10 +40,9 @@
  *              inlined often used functions (andrei)
  *              inlined often used functions (andrei)
  */
  */
 
 
-/*!
- * \file 
- * \brief TM :: 
- * \ingroup tm
+/**  TM :: hash table, flags and other general defines.
+ * @file 
+ * @ingroup tm
  */
  */
 
 
 
 
@@ -281,6 +280,7 @@ struct totag_elem {
 
 
 #define T_DISABLE_6xx (1<<8) /* treat 6xx as a normal reply */
 #define T_DISABLE_6xx (1<<8) /* treat 6xx as a normal reply */
 #define T_DISABLE_FAILOVER (1<<9) /* don't perform dns failover */
 #define T_DISABLE_FAILOVER (1<<9) /* don't perform dns failover */
+#define T_NO_E2E_CANCEL_REASON (1<<10) /* don't propagate CANCEL Reason */
 #define T_DONT_FORK   (T_CANCELED|T_6xx)
 #define T_DONT_FORK   (T_CANCELED|T_6xx)
 
 
 /* unsigned short should be enough for a retr. timer: max. 65535 ticks =>
 /* unsigned short should be enough for a retr. timer: max. 65535 ticks =>

+ 2 - 0
modules/tm/t_lookup.c

@@ -1265,6 +1265,8 @@ static inline void init_new_t(struct cell *new_cell, struct sip_msg *p_msg)
 					(!cfg_get(tm, tm_cfg, tm_auto_inv_100) -1);
 					(!cfg_get(tm, tm_cfg, tm_auto_inv_100) -1);
 		new_cell->flags|=T_DISABLE_6xx &
 		new_cell->flags|=T_DISABLE_6xx &
 					(!cfg_get(tm, tm_cfg, disable_6xx) -1);
 					(!cfg_get(tm, tm_cfg, disable_6xx) -1);
+		new_cell->flags|=T_NO_E2E_CANCEL_REASON &
+					(!!cfg_get(tm, tm_cfg, e2e_cancel_reason) -1);
 		/* reset flags */
 		/* reset flags */
 		new_cell->flags &=
 		new_cell->flags &=
 			(~ get_msgid_val(user_cell_reset_flags, p_msg->id, int));
 			(~ get_msgid_val(user_cell_reset_flags, p_msg->id, int));

+ 14 - 8
modules/tm/t_msgbuilder.c

@@ -171,16 +171,18 @@ char *build_local(struct cell *Trans,unsigned int branch,
 	*len+=CONTENT_LENGTH_LEN+1 + CRLF_LEN;
 	*len+=CONTENT_LENGTH_LEN+1 + CRLF_LEN;
 	reason_len = 0;
 	reason_len = 0;
 	reas1 = 0;
 	reas1 = 0;
-	/* compute reason size */
+	/* compute reason size (if no reason or disabled => reason_len == 0)*/
 	if (reason && reason->cause != CANCEL_REAS_UNKNOWN){
 	if (reason && reason->cause != CANCEL_REAS_UNKNOWN){
-		if (likely(reason->cause > 0)){
+		if (likely(reason->cause > 0 &&
+					cfg_get(tm, tm_cfg, local_cancel_reason))){
 			/* Reason: SIP;cause=<reason->cause>[;text=<reason->u.text.s>] */
 			/* Reason: SIP;cause=<reason->cause>[;text=<reason->u.text.s>] */
 			reason_len = REASON_PREFIX_LEN + USHORT2SBUF_MAX_LEN +
 			reason_len = REASON_PREFIX_LEN + USHORT2SBUF_MAX_LEN +
 				(reason->u.text.s?
 				(reason->u.text.s?
 					REASON_TEXT_LEN + 1 + reason->u.text.len + 1 : 0) +
 					REASON_TEXT_LEN + 1 + reason->u.text.len + 1 : 0) +
 				CRLF_LEN;
 				CRLF_LEN;
 		} else if (reason->cause == CANCEL_REAS_RCVD_CANCEL &&
 		} else if (reason->cause == CANCEL_REAS_RCVD_CANCEL &&
-					reason->u.e2e_cancel) {
+					reason->u.e2e_cancel &&
+					!(Trans->flags & T_NO_E2E_CANCEL_REASON)) {
 			/* parse the entire cancel, to get all the Reason headers */
 			/* parse the entire cancel, to get all the Reason headers */
 			parse_headers(reason->u.e2e_cancel, HDR_EOH_F, 0);
 			parse_headers(reason->u.e2e_cancel, HDR_EOH_F, 0);
 			for(hdr=get_hdr(reason->u.e2e_cancel, HDR_REASON_T), reas1=hdr;
 			for(hdr=get_hdr(reason->u.e2e_cancel, HDR_REASON_T), reas1=hdr;
@@ -189,7 +191,7 @@ char *build_local(struct cell *Trans,unsigned int branch,
 				reason_len += hdr->len;
 				reason_len += hdr->len;
 				reas_last=hdr;
 				reas_last=hdr;
 			}
 			}
-		} else if (unlikely(reason->cause != -1))
+		} else if (unlikely(reason->cause < -1))
 			BUG("unhandled reason cause %d\n", reason->cause);
 			BUG("unhandled reason cause %d\n", reason->cause);
 	}
 	}
 	*len+= reason_len;
 	*len+= reason_len;
@@ -305,16 +307,18 @@ char *build_local_reparse(struct cell *Trans,unsigned int branch,
 	
 	
 	reason_len = 0;
 	reason_len = 0;
 	reas1 = 0;
 	reas1 = 0;
-	/* compute reason size */
+	/* compute reason size (if no reason or disabled => reason_len == 0)*/
 	if (reason && reason->cause != CANCEL_REAS_UNKNOWN){
 	if (reason && reason->cause != CANCEL_REAS_UNKNOWN){
-		if (likely(reason->cause > 0)){
+		if (likely(reason->cause > 0 &&
+					cfg_get(tm, tm_cfg, local_cancel_reason))){
 			/* Reason: SIP;cause=<reason->cause>[;text=<reason->u.text.s>] */
 			/* Reason: SIP;cause=<reason->cause>[;text=<reason->u.text.s>] */
 			reason_len = REASON_PREFIX_LEN + USHORT2SBUF_MAX_LEN +
 			reason_len = REASON_PREFIX_LEN + USHORT2SBUF_MAX_LEN +
 				(reason->u.text.s?
 				(reason->u.text.s?
 					REASON_TEXT_LEN + 1 + reason->u.text.len + 1 : 0) +
 					REASON_TEXT_LEN + 1 + reason->u.text.len + 1 : 0) +
 				CRLF_LEN;
 				CRLF_LEN;
 		} else if (reason->cause == CANCEL_REAS_RCVD_CANCEL &&
 		} else if (reason->cause == CANCEL_REAS_RCVD_CANCEL &&
-					reason->u.e2e_cancel) {
+					reason->u.e2e_cancel &&
+					!(Trans->flags & T_NO_E2E_CANCEL_REASON)) {
 			/* parse the entire cancel, to get all the Reason headers */
 			/* parse the entire cancel, to get all the Reason headers */
 			parse_headers(reason->u.e2e_cancel, HDR_EOH_F, 0);
 			parse_headers(reason->u.e2e_cancel, HDR_EOH_F, 0);
 			for(hdr=get_hdr(reason->u.e2e_cancel, HDR_REASON_T), reas1=hdr;
 			for(hdr=get_hdr(reason->u.e2e_cancel, HDR_REASON_T), reas1=hdr;
@@ -323,7 +327,7 @@ char *build_local_reparse(struct cell *Trans,unsigned int branch,
 				reason_len += hdr->len;
 				reason_len += hdr->len;
 				reas_last=hdr;
 				reas_last=hdr;
 			}
 			}
-		} else if (unlikely(reason->cause != -1))
+		} else if (unlikely(reason->cause < -1))
 			BUG("unhandled reason cause %d\n", reason->cause);
 			BUG("unhandled reason cause %d\n", reason->cause);
 	}
 	}
 
 
@@ -431,6 +435,8 @@ char *build_local_reparse(struct cell *Trans,unsigned int branch,
 				/* end of SIP message found */
 				/* end of SIP message found */
 				/* add reason if needed */
 				/* add reason if needed */
 				if (reason_len) {
 				if (reason_len) {
+					/* if reason_len !=0, no need for any reason enabled
+					   checks */
 					if (likely(reason->cause > 0)) {
 					if (likely(reason->cause > 0)) {
 						append_str(d, REASON_PREFIX, REASON_PREFIX_LEN);
 						append_str(d, REASON_PREFIX, REASON_PREFIX_LEN);
 						code_len=ushort2sbuf(reason->cause, d,
 						code_len=ushort2sbuf(reason->cause, d,

+ 21 - 6
modules/tm/tm.c

@@ -87,16 +87,17 @@
  *  2008-08-11  sctp support: t_relay_to_sctp, t_replicate_sctp,
  *  2008-08-11  sctp support: t_relay_to_sctp, t_replicate_sctp,
  *               t_forward_nonack_sctp (andrei)
  *               t_forward_nonack_sctp (andrei)
  *  2009-03-18  added a new param: auto_inv_100_reason (aheise) 
  *  2009-03-18  added a new param: auto_inv_100_reason (aheise) 
+ *  2010-03-03  added new params: local_cancel_reason and e2e_cancel_reason
+ *              (andrei)
  */
  */
 
 
-/*!
- * \file 
- * \brief TM :: Module API (core)
- * \ingroup tm
+/** TM :: Module API (core).
+ * @file 
+ * @ingroup tm
  */
  */
 
 
-/*!
- * \defgroup tm TM :: Transaction stateful proxy support
+/**
+ * @defgroup tm TM :: Transaction stateful proxy support
  *
  *
    The TM module enables stateful processing of SIP transactions. The main use
    The TM module enables stateful processing of SIP transactions. The main use
    of stateful logic, which is costly in terms of memory and CPU, is some
    of stateful logic, which is costly in terms of memory and CPU, is some
@@ -283,6 +284,8 @@ static int w_t_reset_max_lifetime(struct sip_msg* msg, char* foo, char* bar);
 static int t_set_auto_inv_100(struct sip_msg* msg, char* on_off, char* foo);
 static int t_set_auto_inv_100(struct sip_msg* msg, char* on_off, char* foo);
 static int t_set_disable_6xx(struct sip_msg* msg, char* on_off, char* foo);
 static int t_set_disable_6xx(struct sip_msg* msg, char* on_off, char* foo);
 static int t_set_disable_failover(struct sip_msg* msg, char* on_off, char* f);
 static int t_set_disable_failover(struct sip_msg* msg, char* on_off, char* f);
+static int t_set_no_e2e_cancel_reason(struct sip_msg* msg, char* on_off,
+										char* f);
 static int t_branch_timeout(struct sip_msg* msg, char*, char*);
 static int t_branch_timeout(struct sip_msg* msg, char*, char*);
 static int t_branch_replied(struct sip_msg* msg, char*, char*);
 static int t_branch_replied(struct sip_msg* msg, char*, char*);
 static int t_any_timeout(struct sip_msg* msg, char*, char*);
 static int t_any_timeout(struct sip_msg* msg, char*, char*);
@@ -428,6 +431,13 @@ static cmd_export_t cmds[]={
 			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
 			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
 	{"t_set_disable_failover", t_set_disable_failover, 1, fixup_var_int_1,
 	{"t_set_disable_failover", t_set_disable_failover, 1, fixup_var_int_1,
 			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
 			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
+	{"t_set_no_e2e_cancel_reason", t_set_no_e2e_cancel_reason, 1,
+		fixup_var_int_1,
+			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
+	/* alias for t_set_no_e2e_cancel_reason */
+	{"t_disable_e2e_cancel_reason", t_set_no_e2e_cancel_reason, 1,
+		fixup_var_int_1,
+			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
 	{"t_branch_timeout",  t_branch_timeout,         0, 0,  FAILURE_ROUTE},
 	{"t_branch_timeout",  t_branch_timeout,         0, 0,  FAILURE_ROUTE},
 	{"t_branch_replied",  t_branch_replied,         0, 0,  FAILURE_ROUTE},
 	{"t_branch_replied",  t_branch_replied,         0, 0,  FAILURE_ROUTE},
 	{"t_any_timeout",     t_any_timeout,            0, 0, 
 	{"t_any_timeout",     t_any_timeout,            0, 0, 
@@ -535,6 +545,8 @@ static param_export_t params[]={
 	{"contacts_avp",        PARAM_STRING, &contacts_avp_param                },
 	{"contacts_avp",        PARAM_STRING, &contacts_avp_param                },
 	{"disable_6xx_block",   PARAM_INT, &default_tm_cfg.disable_6xx           },
 	{"disable_6xx_block",   PARAM_INT, &default_tm_cfg.disable_6xx           },
 	{"local_ack_mode",      PARAM_INT, &default_tm_cfg.local_ack_mode        },
 	{"local_ack_mode",      PARAM_INT, &default_tm_cfg.local_ack_mode        },
+	{"local_cancel_reason", PARAM_INT, &default_tm_cfg.local_cancel_reason   },
+	{"e2e_cancel_reason",   PARAM_INT, &default_tm_cfg.e2e_cancel_reason     },
 	{0,0,0}
 	{0,0,0}
 };
 };
 
 
@@ -1736,6 +1748,9 @@ T_SET_FLAG_GEN_FUNC(t_set_disable_6xx, T_DISABLE_6xx)
 T_SET_FLAG_GEN_FUNC(t_set_disable_failover, T_DISABLE_FAILOVER)
 T_SET_FLAG_GEN_FUNC(t_set_disable_failover, T_DISABLE_FAILOVER)
 
 
 
 
+/* disable/enable e2e cancel reason copy for the current transaction */
+T_SET_FLAG_GEN_FUNC(t_set_no_e2e_cancel_reason, T_NO_E2E_CANCEL_REASON)
+
 
 
 /* script function, FAILURE_ROUTE only, returns true if the 
 /* script function, FAILURE_ROUTE only, returns true if the 
  * choosed "failure" branch failed because of a timeout, 
  * choosed "failure" branch failed because of a timeout,