Browse code

tm: new param: local_ack_mode

local_ack_mode controls how local 200 ACKs (ACKs to 2xx replies
for local transactions, created via t_uac*) are sent.
There are 3 possible modes:
- 0 (default) - ACK is sent according to the rfc (the next hop is
found using the contact and the route set and then dns
resolution is used on it).
- 1 - the ACK is sent to the same address as the corresponding
INVITE branch.
- 2 - the ACL is sent to the same address as the source of the 2xx
reply.

Modes 1 and 2 break the rfc, but are useful to deal with
some simple UA behind the NAT cases.
Note that mode 1 is not similar to generating ACKs for negative
replies. Even if the ACK will be sent to the same address as the
INVITE, it will contain the correct route set and uri.

Andrei Pelinescu-Onciul authored on 23/12/2009 12:16:01
Showing 4 changed files
... ...
@@ -91,7 +91,8 @@ struct cfg_group_tm	default_tm_cfg = {
91 91
 			 * for every method except BYE by default */
92 92
 	1,	/* cancel_b_method used for e2e and 6xx cancels*/
93 93
 	1,	/* reparse_on_dns_failover */
94
-	0 /* disable_6xx, by default off */
94
+	0, /* disable_6xx, by default off */
95
+	0  /* local_ack_mode, default 0 (rfc3261 conformant) */
95 96
 };
96 97
 
97 98
 void	*tm_cfg = &default_tm_cfg;
... ...
@@ -186,5 +187,12 @@ cfg_def_t	tm_cfg_def[] = {
186 186
 		"branch instead of from the received request"},
187 187
 	{"disable_6xx_block",	CFG_VAR_INT | CFG_ATOMIC,	0, 1, 0, 0,
188 188
 		"if set to 1, 6xx is treated like a normal reply (breaks rfc)"},
189
+	{"local_ack_mode",		CFG_VAR_INT | CFG_ATOMIC,	0, 2, 0, 0,
190
+		"if set to 1 or 2, local 200 ACKs are sent to the same address as the"
191
+		" corresponding INVITE (1) or the source of the 200 reply (2) instead"
192
+		" of using the contact and the route set (it breaks the rfc, if "
193
+		" it is not set to 0 but allows dealing with NATed contacts in some "
194
+		"simple cases)"
195
+		},
189 196
 	{0, 0, 0, 0, 0, 0}
190 197
 };
... ...
@@ -134,6 +134,7 @@ struct cfg_group_tm {
134 134
 	unsigned int	cancel_b_flags;
135 135
 	int	reparse_on_dns_failover;
136 136
 	int disable_6xx;
137
+	int local_ack_mode;
137 138
 };
138 139
 
139 140
 extern struct cfg_group_tm	default_tm_cfg;
... ...
@@ -982,33 +982,49 @@ char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans,
982 982
 	*len = SIP_VERSION_LEN + ACK_LEN + 2 /* spaces */ + CRLF_LEN;
983 983
 	*len += ruri.len;
984 984
 	
985
-	
986
-	 /* via */
985
+	/* dst */
986
+	switch(cfg_get(tm, tm_cfg, local_ack_mode)){
987
+		case 1:
988
+			/* send the local 200 ack to the same dst as the corresp. invite*/
989
+			*dst=Trans->uac[branch].request.dst;
990
+			break;
991
+		case 2: 
992
+			/* send the local 200 ack to the same dst as the 200 reply source*/
993
+			init_dst_from_rcv(dst, &rpl->rcv);
994
+			dst->send_flags=rpl->fwd_send_flags;
995
+			break;
996
+		case 0:
997
+		default:
998
+			/* rfc conformant behaviour: use the next_hop determined from the
999
+			   contact and the route set */
987 1000
 #ifdef USE_DNS_FAILOVER
988
-	if (cfg_get(core, core_cfg, use_dns_failover)){
989
-		dns_srv_handle_init(&dns_h);
990
-		if ((uri2dst(&dns_h , dst, rpl, &next_hop, PROTO_NONE)==0) ||
991
-				(dst->send_sock==0)){
992
-			dns_srv_handle_put(&dns_h);
993
-			LOG(L_ERR, "build_dlg_ack: no socket found\n");
994
-			goto error;
1001
+		if (cfg_get(core, core_cfg, use_dns_failover)){
1002
+			dns_srv_handle_init(&dns_h);
1003
+			if ((uri2dst(&dns_h , dst, rpl, &next_hop, PROTO_NONE)==0) ||
1004
+					(dst->send_sock==0)){
1005
+				dns_srv_handle_put(&dns_h);
1006
+				LOG(L_ERR, "build_dlg_ack: no socket found\n");
1007
+				goto error;
1008
+			}
1009
+			dns_srv_handle_put(&dns_h); /* not needed any more */
1010
+		}else{
1011
+			if ((uri2dst(0 , dst, rpl, &next_hop, PROTO_NONE)==0) ||
1012
+					(dst->send_sock==0)){
1013
+				LOG(L_ERR, "build_dlg_ack: no socket found\n");
1014
+				goto error;
1015
+			}
995 1016
 		}
996
-		dns_srv_handle_put(&dns_h); /* not needed any more */
997
-	}else{
998
-		if ((uri2dst(0 , dst, rpl, &next_hop, PROTO_NONE)==0) ||
1017
+#else /* USE_DNS_FAILOVER */
1018
+		if ( (uri2dst( dst, rpl, &next_hop, PROTO_NONE)==0) ||
999 1019
 				(dst->send_sock==0)){
1000
-			LOG(L_ERR, "build_dlg_ack: no socket found\n");
1020
+				LOG(L_ERR, "build_dlg_ack: no socket found\n");
1001 1021
 			goto error;
1002 1022
 		}
1023
+#endif /* USE_DNS_FAILOVER */
1024
+		break;
1003 1025
 	}
1004
-#else
1005
-	if ( (uri2dst( dst, rpl, &next_hop, PROTO_NONE)==0) ||
1006
-			(dst->send_sock==0)){
1007
-			LOG(L_ERR, "build_dlg_ack: no socket found\n");
1008
-		goto error;
1009
-	}
1010
-#endif
1011 1026
 	
1027
+	 /* via */
1012 1028
 	if (!t_calc_branch(Trans,  branch, branch_buf, &branch_len)) goto error;
1013 1029
 	branch_str.s = branch_buf;
1014 1030
 	branch_str.len = branch_len;
... ...
@@ -470,6 +470,7 @@ static param_export_t params[]={
470 470
 	{"on_sl_reply",         PARAM_STRING|PARAM_USE_FUNC, fixup_on_sl_reply   },
471 471
 	{"contacts_avp",        PARAM_STRING, &contacts_avp_param                },
472 472
 	{"disable_6xx_block",   PARAM_INT, &default_tm_cfg.disable_6xx           },
473
+	{"local_ack_mode",      PARAM_INT, &default_tm_cfg.local_ack_mode        },
473 474
 	{0,0,0}
474 475
 };
475 476