Browse Source

Merge remote branch 'origin/sr_3.0'

latest sr_3.0 fixes.

* origin/sr_3.0: (36 commits)
  core: added id to every field of gw table schema
  tcp: use the forced socket ip as source
  tmx: pv_t_copy_msg: copy also the send flags
  textops(k): msg_apply_changes: preserve the send flags
  seas: use set_force_socket()
  rr(k): use set_force_socket()
  registrar(k): use set_force_socket()
  pv: use set_force_socket()
  kex: use set_force_socket()
  domainpolicy: use set_force_socket()
  rr(s): use set_force_socket()
  registrar(s): use set_force_socket()
  tm: use set_force_socket() instead of msg->force_send_socket
  tm: preserve forced sockets and send flags during dns failover
  core: extra flag when forcing a socket
  core: kamailio mode config parser fix
  core: PAI and PPI parsing support fixed
  core: dset minor cleanups
  core: append_branch() sets also the send_socket, path & flags
  remove extra backslash in make modules-doc action
  ...
Andrei Pelinescu-Onciul 15 years ago
parent
commit
470d30ac7d

+ 1 - 1
Makefile

@@ -527,7 +527,7 @@ $(1)-doc: modules.lst
 	@for r in $($(1)) "" ; do \
 	@for r in $($(1)) "" ; do \
 		if [ -n "$$$$r" ]; then \
 		if [ -n "$$$$r" ]; then \
 			$(call oecho, "" ;) \
 			$(call oecho, "" ;) \
-			$(call oecho, "" ;) \\
+			$(call oecho, "" ;) \
 			$(MAKE) -C $$$$r/doc $(doc_format) $$(mk_params); \
 			$(MAKE) -C $$$$r/doc $(doc_format) $$(mk_params); \
 		fi ; \
 		fi ; \
 	done
 	done

+ 6 - 5
action.c

@@ -347,15 +347,16 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
 
 
 		/* jku -- introduce a new branch */
 		/* jku -- introduce a new branch */
 		case APPEND_BRANCH_T:
 		case APPEND_BRANCH_T:
-			if ((a->val[0].type!=STRING_ST)) {
+			if (unlikely(a->val[0].type!=STR_ST)) {
 				LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
 				LOG(L_CRIT, "BUG: do_action: bad append_branch_t %d\n",
 					a->val[0].type );
 					a->val[0].type );
 				ret=E_BUG;
 				ret=E_BUG;
 				goto error;
 				goto error;
 			}
 			}
-			ret=ser_append_branch( msg, a->val[0].u.string,
-					   a->val[0].u.string ? strlen(a->val[0].u.string):0,
-					   0, 0, a->val[1].u.number, 0);
+			getbflagsval(0, (flag_t*)&flags);
+			ret=append_branch(msg, &a->val[0].u.str, &msg->dst_uri,
+								&msg->path_vec, a->val[1].u.number,
+								(flag_t)flags, msg->force_send_socket);
 			break;
 			break;
 
 
 		/* jku begin: is_length_greater_than */
 		/* jku begin: is_length_greater_than */
@@ -1208,7 +1209,7 @@ match_cleanup:
 				ret=E_BUG;
 				ret=E_BUG;
 				goto error;
 				goto error;
 			}
 			}
-			msg->force_send_socket=(struct socket_info*)a->val[0].u.data;
+			set_force_socket(msg, (struct socket_info*)a->val[0].u.data);
 			ret=1; /* continue processing */
 			ret=1; /* continue processing */
 			break;
 			break;
 
 

+ 8 - 2
cfg.lex

@@ -962,10 +962,16 @@ EAT_ABLE	[\ \t\b\r]
 <PVAR_P>{LPAREN}			{ p_nest++; yymore(); }
 <PVAR_P>{LPAREN}			{ p_nest++; yymore(); }
 <PVAR_P>.					{ yymore(); }
 <PVAR_P>.					{ yymore(); }
 
 
-<PVARID>{ID}|'.'			{yymore(); }
+<PVARID>{ID}|'\.'			{yymore(); }
 <PVARID>{LPAREN}			{	state = PVAR_P_S; BEGIN(PVAR_P);
 <PVARID>{LPAREN}			{	state = PVAR_P_S; BEGIN(PVAR_P);
 								p_nest=1; yymore(); }
 								p_nest=1; yymore(); }
-<PVARID>.					{ yyless(0); state=INITIAL_S; BEGIN(INITIAL);
+<PVARID>.					{	yyless(yyleng-1);
+								count();
+								addstr(&s_buf, yytext, yyleng);
+								yylval.strval=s_buf.s;
+								memset(&s_buf, 0, sizeof(s_buf));
+								state=INITIAL_S;
+								BEGIN(INITIAL);
 								return PVAR;
 								return PVAR;
 							}
 							}
 
 

+ 1 - 20
dset.c

@@ -238,6 +238,7 @@ void clear_branches(void)
 {
 {
 	nr_branches = 0;
 	nr_branches = 0;
 	ruri_q = Q_UNSPECIFIED;
 	ruri_q = Q_UNSPECIFIED;
+	ruri_bflags = 0;
 }
 }
 
 
 
 
@@ -442,24 +443,6 @@ qvalue_t get_ruri_q(void)
 
 
 
 
 
 
-/*
- * Get actual Request-URI
- */
-int get_request_uri(struct sip_msg* _m, str* _u)
-{
-	     /* Use new_uri if present */
-	if (_m->new_uri.s) {
-		_u->s = _m->new_uri.s;
-		_u->len = _m->new_uri.len;
-	} else {
-		_u->s = _m->first_line.u.request.uri.s;
-		_u->len = _m->first_line.u.request.uri.len;
-	}
-
-	return 0;
-}
-
-
 /*
 /*
  * Rewrite Request-URI
  * Rewrite Request-URI
  */
  */
@@ -484,8 +467,6 @@ int rewrite_uri(struct sip_msg* _m, str* _s)
         _m->new_uri.s = buf;
         _m->new_uri.s = buf;
         _m->new_uri.len = _s->len;
         _m->new_uri.len = _s->len;
 
 
-        DBG("rewrite_uri: Rewriting Request-URI with '%.*s'\n", _s->len, 
-																		   buf);
         return 1;
         return 1;
 }
 }
 
 

+ 14 - 2
dset.h

@@ -33,8 +33,8 @@
 #include "ip_addr.h"
 #include "ip_addr.h"
 #include "qvalue.h"
 #include "qvalue.h"
 #include "flags.h"
 #include "flags.h"
+#include "parser/msg_parser.h"
 
 
-struct sip_msg;
 
 
 extern unsigned int nr_branches;
 extern unsigned int nr_branches;
 
 
@@ -118,7 +118,19 @@ void set_ruri_q(qvalue_t q);
  */
  */
 qvalue_t get_ruri_q(void);
 qvalue_t get_ruri_q(void);
 
 
-int get_request_uri(struct sip_msg* _m, str* _u);
+
+
+/*
+ * Get actual Request-URI
+ */
+inline static int get_request_uri(struct sip_msg* _m, str* _u)
+{
+	*_u=*GET_RURI(_m);
+	return 0;
+}
+
+
+
 int rewrite_uri(struct sip_msg* _m, str* _s);
 int rewrite_uri(struct sip_msg* _m, str* _s);
 
 
 /*! \brief
 /*! \brief

+ 21 - 2
forward.h

@@ -123,6 +123,11 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
 {
 {
 	struct dest_info new_dst;
 	struct dest_info new_dst;
 	str outb;
 	str outb;
+#ifdef USE_TCP 
+	union sockaddr_union* from;
+	union sockaddr_union local_addr;
+#endif
+	
 	outb.s = buf;
 	outb.s = buf;
 	outb.len = len;
 	outb.len = len;
 	sr_event_exec(SREV_NET_DATA_OUT, (void*)&outb);
 	sr_event_exec(SREV_NET_DATA_OUT, (void*)&outb);
@@ -152,7 +157,14 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
 					" support is disabled\n");
 					" support is disabled\n");
 			goto error;
 			goto error;
 		}else{
 		}else{
-			if (unlikely(tcp_send(dst, 0, outb.s, outb.len)<0)){
+			from=0;
+			if (unlikely((dst->send_flags & SND_F_FORCE_SOCKET) &&
+						dst->send_sock)) {
+				local_addr=dst->send_sock->su;
+				su_setport(&local_addr, 0); /* any local port will do */
+				from=&local_addr;
+			}
+			if (unlikely(tcp_send(dst, from, outb.s, outb.len)<0)){
 				STATS_TX_DROPS;
 				STATS_TX_DROPS;
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
 				goto error;
 				goto error;
@@ -167,7 +179,14 @@ static inline int msg_send(struct dest_info* dst, char* buf, int len)
 					" support is disabled\n");
 					" support is disabled\n");
 			goto error;
 			goto error;
 		}else{
 		}else{
-			if (unlikely(tcp_send(dst, 0, outb.s, outb.len)<0)){
+			from=0;
+			if (unlikely((dst->send_flags & SND_F_FORCE_SOCKET) &&
+						dst->send_sock)) {
+				local_addr=dst->send_sock->su;
+				su_setport(&local_addr, 0); /* any local port will do */
+				from=&local_addr;
+			}
+			if (unlikely(tcp_send(dst, from, outb.s, outb.len)<0)){
 				STATS_TX_DROPS;
 				STATS_TX_DROPS;
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
 				LOG(L_ERR, "msg_send: ERROR: tcp_send failed\n");
 				goto error;
 				goto error;

+ 1 - 0
ip_addr.h

@@ -140,6 +140,7 @@ struct receive_info{
 /* send flags */
 /* send flags */
 #define SND_F_FORCE_CON_REUSE	1 /* reuse an existing connection or fail */
 #define SND_F_FORCE_CON_REUSE	1 /* reuse an existing connection or fail */
 #define SND_F_CON_CLOSE			2 /* close the connection after sending */
 #define SND_F_CON_CLOSE			2 /* close the connection after sending */
+#define SND_F_FORCE_SOCKET		4 /* send socket in dst is forced */
 
 
 typedef unsigned char  snd_flags_t;
 typedef unsigned char  snd_flags_t;
 
 

+ 20 - 11
lib/srdb1/schema/gw.xml

@@ -47,14 +47,14 @@
         <description>ID of gateway's group</description>
         <description>ID of gateway's group</description>
     </column>
     </column>
 
 
-    <column>
+    <column id="ip_addr">
         <name>ip_addr</name>
         <name>ip_addr</name>
         <type>string</type>
         <type>string</type>
         <size>15</size>
         <size>15</size>
         <description>IP Address of the gateway</description>
         <description>IP Address of the gateway</description>
     </column>
     </column>
 
 
-    <column>
+    <column id="hostname">
         <name>hostname</name>
         <name>hostname</name>
         <type>string</type>
         <type>string</type>
         <size>64</size>
         <size>64</size>
@@ -62,35 +62,35 @@
         <description>Hostname of the gateway</description>
         <description>Hostname of the gateway</description>
     </column>
     </column>
 
 
-    <column>
+    <column id="port">
         <name>port</name>
         <name>port</name>
         <type>unsigned short</type>
         <type>unsigned short</type>
         <null/>
         <null/>
         <description>Port of the gateway</description>
         <description>Port of the gateway</description>
     </column>
     </column>
 
 
-    <column>
+    <column id="uri_scheme">
         <name>uri_scheme</name>
         <name>uri_scheme</name>
         <type>unsigned char</type>
         <type>unsigned char</type>
         <null/>
         <null/>
         <description>URI scheme of gateway</description>
         <description>URI scheme of gateway</description>
     </column>
     </column>
 
 
-    <column>
+    <column id="transport">
         <name>transport</name>
         <name>transport</name>
         <type>unsigned char</type>
         <type>unsigned char</type>
         <null/>
         <null/>
         <description>Transport type to be used for the gateway</description>
         <description>Transport type to be used for the gateway</description>
     </column>
     </column>
 
 
-    <column>
+    <column id="strip">
         <name>strip</name>
         <name>strip</name>
         <type>unsigned char</type>
         <type>unsigned char</type>
         <null/>
         <null/>
         <description>The number of digits to strip from Request URI user part before inserting tag</description>
         <description>The number of digits to strip from Request URI user part before inserting tag</description>
     </column>
     </column>
 
 
-    <column>
+    <column id="tag">
         <name>tag</name>
         <name>tag</name>
         <type>string</type>
         <type>string</type>
         <size>16</size>
         <size>16</size>
@@ -99,21 +99,21 @@
         <description>Request URI user part tag</description>
         <description>Request URI user part tag</description>
     </column>
     </column>
 
 
-    <column>
+    <column id="weight">
         <name>weight</name>
         <name>weight</name>
         <type>unsigned int</type>
         <type>unsigned int</type>
         <null/>
         <null/>
         <description>Weight of gateway within gw_grp.  Valid values are 1-254.</description>
         <description>Weight of gateway within gw_grp.  Valid values are 1-254.</description>
     </column>
     </column>
 
 
-    <column>
+    <column id="flags">
         <name>flags</name>
         <name>flags</name>
         <type>unsigned int</type>
         <type>unsigned int</type>
         <default>&DEFAULT_FLAGS;</default>
         <default>&DEFAULT_FLAGS;</default>
         <description>Gateway specific flags</description>
         <description>Gateway specific flags</description>
     </column>
     </column>
 
 
-    <column>
+    <column id="defunct">
         <name>defunct</name>
         <name>defunct</name>
         <type>unsigned int</type>
         <type>unsigned int</type>
         <null/>
         <null/>
@@ -122,10 +122,19 @@
     </column>
     </column>
 
 
     <index>
     <index>
-        <name>lcr_id_gw_name_idx</name>
+        <name>lcr_id_grp_id_gw_name_idx</name>
         <colref linkend="lcr_id"/>
         <colref linkend="lcr_id"/>
+        <colref linkend="grp_id"/>
         <colref linkend="gw_name"/>
         <colref linkend="gw_name"/>
         <unique/>
         <unique/>
     </index>
     </index>
 
 
+    <index>
+        <name>lcr_id_grp_id_ip_addr_idx</name>
+        <colref linkend="lcr_id"/>
+        <colref linkend="grp_id"/>
+        <colref linkend="ip_addr"/>
+        <unique/>
+    </index>
+
 </table>
 </table>

+ 20 - 13
modules/lcr/lcr_mod.c

@@ -167,7 +167,7 @@ struct matched_gw_info {
     unsigned short prefix_len;
     unsigned short prefix_len;
     unsigned short priority;
     unsigned short priority;
     unsigned int weight;
     unsigned int weight;
-    unsigned int defunct_until;
+    unsigned short duplicate;
 };
 };
 
 
 /*
 /*
@@ -1428,7 +1428,7 @@ int mi_print_gws(struct mi_node* rpl)
 	    attr = add_mi_attr(node, MI_DUP_VALUE, "TAG", 3,
 	    attr = add_mi_attr(node, MI_DUP_VALUE, "TAG", 3,
 			       gws[i].tag, gws[i].tag_len);
 			       gws[i].tag, gws[i].tag_len);
 	    if (attr == NULL) goto err;
 	    if (attr == NULL) goto err;
-	    
+
 	    p = int2str((unsigned long)gws[i].weight, &len);
 	    p = int2str((unsigned long)gws[i].weight, &len);
 	    attr = add_mi_attr(node, MI_DUP_VALUE, "WEIGHT", 6, p, len);
 	    attr = add_mi_attr(node, MI_DUP_VALUE, "WEIGHT", 6, p, len);
 	    if (attr == NULL) goto err;
 	    if (attr == NULL) goto err;
@@ -1674,6 +1674,7 @@ void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws,
     delete_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp);
     delete_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp);
 
 
     for (i = 0; i < gw_cnt; i++) {
     for (i = 0; i < gw_cnt; i++) {
+	if (matched_gws[i].duplicate == 1) continue;
 	index = matched_gws[i].gw_index;
 	index = matched_gws[i].gw_index;
       	hostname_len = gws[index].hostname_len;
       	hostname_len = gws[index].hostname_len;
 	strip = gws[index].strip;
 	strip = gws[index].strip;
@@ -1700,7 +1701,7 @@ void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws,
 	add_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp, val);
 	add_avp(gw_uri_avp_type|AVP_VAL_STR, gw_uri_avp, val);
 
 
 	LM_DBG("added gw_uri_avp <%.*s> with weight <%u>\n",
 	LM_DBG("added gw_uri_avp <%.*s> with weight <%u>\n",
-		value.len, value.s, matched_gws[i].weight);
+	       value.len, value.s, matched_gws[i].weight);
     skip:
     skip:
 	continue;
 	continue;
     }
     }
@@ -1713,8 +1714,8 @@ void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws,
 static int load_gws(struct sip_msg* _m, char *_lcr_id, char *_from_uri)
 static int load_gws(struct sip_msg* _m, char *_lcr_id, char *_from_uri)
 {
 {
     str ruri_user, from_uri;
     str ruri_user, from_uri;
-    unsigned int j, k, gw_index, gw_count, now;
-    int lcr_id;
+    int i, j, lcr_id;
+    unsigned int gw_index, gw_count, now, ip_addr;
     int_str val;
     int_str val;
     struct matched_gw_info matched_gws[MAX_NO_OF_GWS + 1];
     struct matched_gw_info matched_gws[MAX_NO_OF_GWS + 1];
     struct lcr_info **lcrs, *lcr_rec, *pl;
     struct lcr_info **lcrs, *lcr_rec, *pl;
@@ -1786,18 +1787,12 @@ static int load_gws(struct sip_msg* _m, char *_lcr_id, char *_from_uri)
 		    while (j) {
 		    while (j) {
                         /* If this gw is defunct, skip it */
                         /* If this gw is defunct, skip it */
 		        if (gws[j].defunct_until > now) goto gw_found;
 		        if (gws[j].defunct_until > now) goto gw_found;
-			for (k = 0; k < gw_index; k++) {
-			    if (gws[j].ip_addr ==
-				gws[matched_gws[k].gw_index].ip_addr)
-				/* Skip already existing gw */
-				goto gw_found;
-			}
-			/* This is a new gw */
 			matched_gws[gw_index].gw_index = j;
 			matched_gws[gw_index].gw_index = j;
 			matched_gws[gw_index].prefix_len = pl->prefix_len;
 			matched_gws[gw_index].prefix_len = pl->prefix_len;
 			matched_gws[gw_index].priority = lcr_rec->priority;
 			matched_gws[gw_index].priority = lcr_rec->priority;
 			matched_gws[gw_index].weight = gws[j].weight *
 			matched_gws[gw_index].weight = gws[j].weight *
 			    (rand() >> 8);
 			    (rand() >> 8);
+			matched_gws[gw_index].duplicate = 0;
 			LM_DBG("added matched_gws[%d]=[%u, %u, %u, %u]\n",
 			LM_DBG("added matched_gws[%d]=[%u, %u, %u, %u]\n",
 			       gw_index, j, pl->prefix_len, lcr_rec->priority,
 			       gw_index, j, pl->prefix_len, lcr_rec->priority,
 			       matched_gws[gw_index].weight);
 			       matched_gws[gw_index].weight);
@@ -1812,9 +1807,21 @@ static int load_gws(struct sip_msg* _m, char *_lcr_id, char *_from_uri)
 	pl = pl->next;
 	pl = pl->next;
     }
     }
 
 
-    /* Sort gateways based on prefix_len, priority, and randomized weight */
+    /* Sort gateways in reverse order based on prefix_len, priority,
+       and randomized weight */
     qsort(matched_gws, gw_index, sizeof(struct matched_gw_info), comp_matched);
     qsort(matched_gws, gw_index, sizeof(struct matched_gw_info), comp_matched);
 
 
+    /* Remove duplicate gws */
+    for (i = gw_index - 1; i >= 0; i--) {
+	if (matched_gws[i].duplicate == 1) continue;
+	ip_addr = gws[matched_gws[i].gw_index].ip_addr;
+	for (j = i - 1; j >= 0; j--) {
+	    if (gws[matched_gws[j].gw_index].ip_addr == ip_addr) {
+		matched_gws[j].duplicate = 1;
+	    }
+	}
+    }
+
     /* Add gateways into gw_uris_avp */
     /* Add gateways into gw_uris_avp */
     add_gws_into_avps(gws, matched_gws, gw_index, &ruri_user);
     add_gws_into_avps(gws, matched_gws, gw_index, &ruri_user);
 
 

+ 3 - 3
modules/lcr/lcr_rpc.c

@@ -81,7 +81,7 @@ static void dump_gws(rpc_t* rpc, void* c)
 		if (rpc->add(c, "{", &st) < 0) return;
 		if (rpc->add(c, "{", &st) < 0) return;
 		rpc->struct_add(st, "d", "lcr_id", j);
 		rpc->struct_add(st, "d", "lcr_id", j);
 		rpc->struct_add(st, "d", "grp_id", gws[i].grp_id);
 		rpc->struct_add(st, "d", "grp_id", gws[i].grp_id);
-		rpc->struct_printf(st,   "ip_addr", "%d.%d.%d.%d",
+		rpc->struct_printf(st, "ip_addr", "%d.%d.%d.%d",
 				   (gws[i].ip_addr << 24) >> 24,
 				   (gws[i].ip_addr << 24) >> 24,
 				   ((gws[i].ip_addr >> 8) << 24) >> 24,
 				   ((gws[i].ip_addr >> 8) << 24) >> 24,
 				   ((gws[i].ip_addr >> 16) << 24) >> 24,
 				   ((gws[i].ip_addr >> 16) << 24) >> 24,
@@ -117,9 +117,9 @@ static void dump_gws(rpc_t* rpc, void* c)
 		tag.len=gws[i].tag_len;
 		tag.len=gws[i].tag_len;
 		rpc->struct_add(st, "dSddd",
 		rpc->struct_add(st, "dSddd",
 				"strip",  gws[i].strip,
 				"strip",  gws[i].strip,
-				"tag",    gws[i].tag, /* FIXME */
+				"tag",    &tag,
 				"weight", gws[i].weight,
 				"weight", gws[i].weight,
-				"flags",  &tag,
+				"flags",  gws[i].flags,
 				"defunct_until",  &gws[i].defunct_until
 				"defunct_until",  &gws[i].defunct_until
 				);
 				);
 	    }
 	    }

+ 49 - 25
modules/tm/t_fwd.c

@@ -159,7 +159,7 @@ unsigned int get_on_branch(void)
    the sending information: t->uac[branch].request.dst, branch buffer, uri
    the sending information: t->uac[branch].request.dst, branch buffer, uri
    path vector a.s.o.) and runs the on_branch route.
    path vector a.s.o.) and runs the on_branch route.
  * t->uac[branch].request.dst will be filled if next_hop !=0 with the result
  * t->uac[branch].request.dst will be filled if next_hop !=0 with the result
- * of the DNS resolution (next_hop and fproto).
+ * of the DNS resolution (next_hop, fproto and fsocket).
  * If next_hop is 0 all the dst members except the send_flags are read-only
  * If next_hop is 0 all the dst members except the send_flags are read-only
  * (send_flags it's updated) and are supposed to be pre-filled.
  * (send_flags it's updated) and are supposed to be pre-filled.
  *
  *
@@ -174,6 +174,8 @@ unsigned int get_on_branch(void)
  *              for DNS resolution and the branch request.dst structure will
  *              for DNS resolution and the branch request.dst structure will
  *              be filled. If 0 the branch must already have
  *              be filled. If 0 the branch must already have
  *              a pre-filled valid request.dst.
  *              a pre-filled valid request.dst.
+ * @param fsocket - forced send socket for forwarding.
+ * @param send_flags - special flags for sending (see SND_F_* / snd_flags_t).
  * @param fproto - forced proto for forwarding. Used only if next_hop!=0.
  * @param fproto - forced proto for forwarding. Used only if next_hop!=0.
  * @param flags - 0 or UAC_DNS_FAILOVER_F for now.
  * @param flags - 0 or UAC_DNS_FAILOVER_F for now.
  *
  *
@@ -181,8 +183,10 @@ unsigned int get_on_branch(void)
  */
  */
 static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 									int branch, str *uri, str* path,
 									int branch, str *uri, str* path,
-									str* next_hop, int fproto,
-									int flags)
+									str* next_hop,
+									struct socket_info* fsocket,
+									snd_flags_t snd_flags,
+									int fproto, int flags)
 {
 {
 	char *shbuf;
 	char *shbuf;
 	struct lump* add_rm_backup, *body_lumps_backup;
 	struct lump* add_rm_backup, *body_lumps_backup;
@@ -198,6 +202,7 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 	int backup_route_type;
 	int backup_route_type;
 	snd_flags_t fwd_snd_flags_bak;
 	snd_flags_t fwd_snd_flags_bak;
 	snd_flags_t rpl_snd_flags_bak;
 	snd_flags_t rpl_snd_flags_bak;
+	struct socket_info *force_send_socket_bak;
 	struct dest_info *dst;
 	struct dest_info *dst;
 
 
 	shbuf=0;
 	shbuf=0;
@@ -232,8 +237,6 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 #endif
 #endif
 	add_rm_backup = i_req->add_rm;
 	add_rm_backup = i_req->add_rm;
 	body_lumps_backup = i_req->body_lumps;
 	body_lumps_backup = i_req->body_lumps;
-	i_req->add_rm=0;
-	i_req->body_lumps=0;
 	if (unlikely(i_req->add_rm)){
 	if (unlikely(i_req->add_rm)){
 		i_req->add_rm = dup_lump_list(i_req->add_rm);
 		i_req->add_rm = dup_lump_list(i_req->add_rm);
 		if (unlikely(i_req->add_rm==0)){
 		if (unlikely(i_req->add_rm==0)){
@@ -323,17 +326,22 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 			   (
 			   (
 			 */
 			 */
 			if (exec_pre_script_cb(i_req, BRANCH_CB_TYPE)>0) {
 			if (exec_pre_script_cb(i_req, BRANCH_CB_TYPE)>0) {
-				/* backup ireq msg send flags */
+				/* backup ireq msg send flags and force_send_socket*/
 				fwd_snd_flags_bak=i_req->fwd_send_flags;;
 				fwd_snd_flags_bak=i_req->fwd_send_flags;;
 				rpl_snd_flags_bak=i_req->rpl_send_flags;
 				rpl_snd_flags_bak=i_req->rpl_send_flags;
-				i_req->fwd_send_flags=dst->send_flags /* intial value  */;
+				force_send_socket_bak=i_req->force_send_socket;
+				/* set the new values */
+				i_req->fwd_send_flags=snd_flags /* intial value  */;
+				set_force_socket(i_req, fsocket);
 				if (run_top_route(branch_rt.rlist[branch_route], i_req, 0) < 0)
 				if (run_top_route(branch_rt.rlist[branch_route], i_req, 0) < 0)
 				{
 				{
 					LOG(L_ERR, "Error in run_top_route\n");
 					LOG(L_ERR, "Error in run_top_route\n");
 				}
 				}
-				/* update dst send_flags */
-				dst->send_flags=i_req->fwd_send_flags;
-				/* restore ireq_msg flags */
+				/* update dst send_flags  and send socket*/
+				snd_flags=i_req->fwd_send_flags;
+				fsocket=i_req->force_send_socket;
+				/* restore ireq_msg force_send_socket & flags */
+				set_force_socket(i_req, force_send_socket_bak);
 				i_req->fwd_send_flags=fwd_snd_flags_bak;
 				i_req->fwd_send_flags=fwd_snd_flags_bak;
 				i_req->rpl_send_flags=rpl_snd_flags_bak;
 				i_req->rpl_send_flags=rpl_snd_flags_bak;
 				exec_post_script_cb(i_req, BRANCH_CB_TYPE);
 				exec_post_script_cb(i_req, BRANCH_CB_TYPE);
@@ -378,11 +386,12 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 	if (likely(next_hop!=0 || (flags & UAC_DNS_FAILOVER_F))){
 	if (likely(next_hop!=0 || (flags & UAC_DNS_FAILOVER_F))){
 		/* next_hop present => use it for dns resolution */
 		/* next_hop present => use it for dns resolution */
 #ifdef USE_DNS_FAILOVER
 #ifdef USE_DNS_FAILOVER
-		if (uri2dst(&t->uac[branch].dns_h, dst, i_req,
+		if (uri2dst2(&t->uac[branch].dns_h, dst, fsocket, snd_flags,
 							next_hop?next_hop:uri, fproto) == 0)
 							next_hop?next_hop:uri, fproto) == 0)
 #else
 #else
 		/* dst filled from the uri & request (send_socket) */
 		/* dst filled from the uri & request (send_socket) */
-		if (uri2dst(dst, i_req, next_hop?next_hop:uri, fproto)==0)
+		if (uri2dst2(dst, fsocket, snd_flags,
+							next_hop?next_hop:uri, fproto)==0)
 #endif
 #endif
 		{
 		{
 			ret=E_BAD_ADDRESS;
 			ret=E_BAD_ADDRESS;
@@ -454,6 +463,7 @@ error03:
 	i_req->parsed_uri=parsed_uri_bak;
 	i_req->parsed_uri=parsed_uri_bak;
 	i_req->parsed_uri_ok=parsed_uri_ok_bak;
 	i_req->parsed_uri_ok=parsed_uri_ok_bak;
 	i_req->path_vec=path_bak;
 	i_req->path_vec=path_bak;
+	
 	/* Delete the duplicated lump lists, this will also delete
 	/* Delete the duplicated lump lists, this will also delete
 	 * all lumps created here, such as lumps created in per-branch
 	 * all lumps created here, such as lumps created in per-branch
 	 * routing sections, Via, and Content-Length headers created in
 	 * routing sections, Via, and Content-Length headers created in
@@ -605,6 +615,8 @@ int add_blind_uac( /*struct cell *t*/ )
  *                     uri format, e.g.: "<sip:1.2.3.4;lr>, <sip:5.6.7.8;lr>").
  *                     uri format, e.g.: "<sip:1.2.3.4;lr>, <sip:5.6.7.8;lr>").
  *  @param proxy    - proxy structure. If non-null it takes precedence over
  *  @param proxy    - proxy structure. If non-null it takes precedence over
  *                    next_hop/uri and it will be used for forwarding.
  *                    next_hop/uri and it will be used for forwarding.
+ *  @param fsocket  - forced forward send socket (can be 0).
+ *  @param snd_flags - special send flags (see SND_F_* / snd_flags_t)
  *  @param proto    - forced protocol for forwarding (overrides the protocol
  *  @param proto    - forced protocol for forwarding (overrides the protocol
  *                    in next_hop/uri or proxy if != PROTO_NONE).
  *                    in next_hop/uri or proxy if != PROTO_NONE).
  *  @param flags    - special flags passed to prepare_new_uac().
  *  @param flags    - special flags passed to prepare_new_uac().
@@ -613,6 +625,7 @@ int add_blind_uac( /*struct cell *t*/ )
 */
 */
 static int add_uac( struct cell *t, struct sip_msg *request, str *uri,
 static int add_uac( struct cell *t, struct sip_msg *request, str *uri,
 					str* next_hop, str* path, struct proxy_l *proxy,
 					str* next_hop, str* path, struct proxy_l *proxy,
+					struct socket_info* fsocket, snd_flags_t snd_flags,
 					int proto, int flags)
 					int proto, int flags)
 {
 {
 
 
@@ -655,7 +668,8 @@ static int add_uac( struct cell *t, struct sip_msg *request, str *uri,
 
 
 	/* now message printing starts ... */
 	/* now message printing starts ... */
 	if (unlikely( (ret=prepare_new_uac(t, request, branch, uri, path,
 	if (unlikely( (ret=prepare_new_uac(t, request, branch, uri, path,
-											next_hop, proto, flags)) < 0)){
+										next_hop, fsocket, snd_flags,
+										proto, flags)) < 0)){
 		ser_error=ret;
 		ser_error=ret;
 		goto error01;
 		goto error01;
 	}
 	}
@@ -691,7 +705,10 @@ error:
    the failed branch to construct the new message in case of DNS failover.
    the failed branch to construct the new message in case of DNS failover.
 */
 */
 static int add_uac_from_buf( struct cell *t, struct sip_msg *request,
 static int add_uac_from_buf( struct cell *t, struct sip_msg *request,
-								str *uri, str* path, int proto,
+								str *uri, str* path,
+								struct socket_info* fsocket,
+								snd_flags_t send_flags,
+								int proto,
 								char *buf, short buf_len)
 								char *buf, short buf_len)
 {
 {
 
 
@@ -715,8 +732,8 @@ static int add_uac_from_buf( struct cell *t, struct sip_msg *request,
 		goto error;
 		goto error;
 	}
 	}
 
 
-	if (uri2dst(&t->uac[branch].dns_h, &t->uac[branch].request.dst,
-				request, uri, proto) == 0)
+	if (uri2dst2(&t->uac[branch].dns_h, &t->uac[branch].request.dst,
+					fsocket, send_flags, uri, proto) == 0)
 	{
 	{
 		ret=ser_error=E_BAD_ADDRESS;
 		ret=ser_error=E_BAD_ADDRESS;
 		goto error;
 		goto error;
@@ -822,21 +839,29 @@ int add_uac_dns_fallback(struct cell *t, struct sip_msg* msg,
 			dns_srv_handle_cpy(&t->uac[t->nr_of_outgoings].dns_h,
 			dns_srv_handle_cpy(&t->uac[t->nr_of_outgoings].dns_h,
 								&old_uac->dns_h);
 								&old_uac->dns_h);
 
 
-			if (cfg_get(tm, tm_cfg, reparse_on_dns_failover))
+			if (cfg_get(tm, tm_cfg, reparse_on_dns_failover)){
 				/* Reuse the old buffer and only replace the via header.
 				/* Reuse the old buffer and only replace the via header.
 				 * The drawback is that the send_socket is not corrected
 				 * The drawback is that the send_socket is not corrected
 				 * in the rest of the message, only in the VIA HF (Miklos) */
 				 * in the rest of the message, only in the VIA HF (Miklos) */
 				ret=add_uac_from_buf(t,  msg, &old_uac->uri,
 				ret=add_uac_from_buf(t,  msg, &old_uac->uri,
 							&old_uac->path,
 							&old_uac->path,
+							 (old_uac->request.dst.send_flags &
+								SND_F_FORCE_SOCKET)?
+									old_uac->request.dst.send_sock:0,
+							old_uac->request.dst.send_flags,
 							old_uac->request.dst.proto,
 							old_uac->request.dst.proto,
 							old_uac->request.buffer,
 							old_uac->request.buffer,
 							old_uac->request.buffer_len);
 							old_uac->request.buffer_len);
-			else
+			}else
 				/* add_uac will use dns_h => next_hop will be ignored.
 				/* add_uac will use dns_h => next_hop will be ignored.
 				 * Unfortunately we can't reuse the old buffer, the branch id
 				 * Unfortunately we can't reuse the old buffer, the branch id
 				 *  must be changed and the send_socket might be different =>
 				 *  must be changed and the send_socket might be different =>
 				 *  re-create the whole uac */
 				 *  re-create the whole uac */
 				ret=add_uac(t,  msg, &old_uac->uri, 0, &old_uac->path, 0,
 				ret=add_uac(t,  msg, &old_uac->uri, 0, &old_uac->path, 0,
+							 (old_uac->request.dst.send_flags &
+								SND_F_FORCE_SOCKET)?
+									old_uac->request.dst.send_sock:0,
+							old_uac->request.dst.send_flags,
 							old_uac->request.dst.proto, UAC_DNS_FAILOVER_F);
 							old_uac->request.dst.proto, UAC_DNS_FAILOVER_F);
 
 
 			if (ret<0){
 			if (ret<0){
@@ -908,7 +933,7 @@ int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel,
 		if (unlikely((ret=prepare_new_uac( t_cancel, cancel_msg, branch,
 		if (unlikely((ret=prepare_new_uac( t_cancel, cancel_msg, branch,
 									&t_invite->uac[branch].uri,
 									&t_invite->uac[branch].uri,
 									&t_invite->uac[branch].path,
 									&t_invite->uac[branch].path,
-									0, PROTO_NONE, 0)) <0)){
+									0, 0, 0, PROTO_NONE, 0)) <0)){
 			ser_error=ret;
 			ser_error=ret;
 			goto error;
 			goto error;
 		}
 		}
@@ -1244,7 +1269,7 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
 	int try_new;
 	int try_new;
 	int lock_replies;
 	int lock_replies;
 	str dst_uri, path;
 	str dst_uri, path;
-	struct socket_info* si, *backup_si;
+	struct socket_info* si;
 	flag_t backup_bflags = 0;
 	flag_t backup_bflags = 0;
 	flag_t bflags = 0;
 	flag_t bflags = 0;
 	
 	
@@ -1269,7 +1294,6 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
 		}
 		}
 	}
 	}
 
 
-	backup_si = p_msg->force_send_socket;
 	getbflagsval(0, &backup_bflags);
 	getbflagsval(0, &backup_bflags);
 
 
 	/* if no more specific error code is known, use this */
 	/* if no more specific error code is known, use this */
@@ -1305,7 +1329,8 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
 #endif
 #endif
 		try_new=1;
 		try_new=1;
 		branch_ret=add_uac( t, p_msg, GET_RURI(p_msg), GET_NEXT_HOP(p_msg),
 		branch_ret=add_uac( t, p_msg, GET_RURI(p_msg), GET_NEXT_HOP(p_msg),
-							&p_msg->path_vec, proxy, proto, 0);
+							&p_msg->path_vec, proxy, p_msg->force_send_socket,
+							p_msg->fwd_send_flags, proto, 0);
 		if (branch_ret>=0) 
 		if (branch_ret>=0) 
 			added_branches |= 1<<branch_ret;
 			added_branches |= 1<<branch_ret;
 		else
 		else
@@ -1316,12 +1341,12 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
 	while((current_uri.s=next_branch( &current_uri.len, &q, &dst_uri, &path,
 	while((current_uri.s=next_branch( &current_uri.len, &q, &dst_uri, &path,
 										&bflags, &si))) {
 										&bflags, &si))) {
 		try_new++;
 		try_new++;
-		p_msg->force_send_socket = si;
 		setbflagsval(0, bflags);
 		setbflagsval(0, bflags);
 
 
 		branch_ret=add_uac( t, p_msg, &current_uri,
 		branch_ret=add_uac( t, p_msg, &current_uri,
 							(dst_uri.len) ? (&dst_uri) : &current_uri,
 							(dst_uri.len) ? (&dst_uri) : &current_uri,
-							&path, proxy, proto, 0);
+							&path, proxy, si, p_msg->fwd_send_flags,
+							proto, 0);
 		/* pick some of the errors in case things go wrong;
 		/* pick some of the errors in case things go wrong;
 		   note that picking lowest error is just as good as
 		   note that picking lowest error is just as good as
 		   any other algorithm which picks any other negative
 		   any other algorithm which picks any other negative
@@ -1334,7 +1359,6 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
 	/* consume processed branches */
 	/* consume processed branches */
 	clear_branches();
 	clear_branches();
 
 
-	p_msg->force_send_socket = backup_si;
 	setbflagsval(0, backup_bflags);
 	setbflagsval(0, backup_bflags);
 
 
 	/* don't forget to clear all branches processed so far */
 	/* don't forget to clear all branches processed so far */

+ 1 - 1
modules/tm/t_serial.c

@@ -447,7 +447,7 @@ int t_next_contacts(struct sip_msg* msg, char* key, char* value)
 		else reset_dst_uri(msg);
 		else reset_dst_uri(msg);
 		if (path.s && path.len) set_path_vector(msg, &path);
 		if (path.s && path.len) set_path_vector(msg, &path);
 		else reset_path_vector(msg);
 		else reset_path_vector(msg);
-		msg->force_send_socket = sock;
+		set_force_socket(msg, sock);
 		setbflagsval(0, flags);
 		setbflagsval(0, flags);
 
 
 		if (avp->flags & Q_FLAG) {
 		if (avp->flags & Q_FLAG) {

+ 1 - 1
modules_k/domainpolicy/domainpolicy.c

@@ -850,7 +850,7 @@ int dp_apply_policy(struct sip_msg* _msg, char* _s1, char* _s2) {
 		}
 		}
 		si = grep_sock_info( &host, (unsigned short) port, (unsigned short) proto);
 		si = grep_sock_info( &host, (unsigned short) port, (unsigned short) proto);
 		if (si) {
 		if (si) {
-			_msg->force_send_socket = si;
+			set_force_socket(_msg, si);
 		} else {
 		} else {
 			LM_WARN("could not find socket for"
 			LM_WARN("could not find socket for"
 					"send_socket '%.*s'\n", val.s.len, ZSW(val.s.s));
 					"send_socket '%.*s'\n", val.s.len, ZSW(val.s.s));

+ 1 - 1
modules_k/kex/km_core.c

@@ -44,7 +44,7 @@ int w_km_append_branch(struct sip_msg *msg, char *uri, str *sq)
 		ret = km_append_branch(msg, 0, &msg->dst_uri, &msg->path_vec,
 		ret = km_append_branch(msg, 0, &msg->dst_uri, &msg->path_vec,
 			q, branch_flags, msg->force_send_socket);
 			q, branch_flags, msg->force_send_socket);
 		/* reset all branch info */
 		/* reset all branch info */
-		msg->force_send_socket = 0;
+		reset_force_socket(msg);
 		setbflagsval(0, 0);
 		setbflagsval(0, 0);
 		if(msg->dst_uri.s!=0)
 		if(msg->dst_uri.s!=0)
 			pkg_free(msg->dst_uri.s);
 			pkg_free(msg->dst_uri.s);

+ 2 - 2
modules_k/pv/pv_core.c

@@ -1882,7 +1882,7 @@ int pv_set_force_sock(struct sip_msg* msg, pv_param_t *param,
 
 
 	if(val==NULL || (val->flags&PV_VAL_NULL))
 	if(val==NULL || (val->flags&PV_VAL_NULL))
 	{
 	{
-		msg->force_send_socket = NULL;
+		reset_force_socket(msg);
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -1904,7 +1904,7 @@ int pv_set_force_sock(struct sip_msg* msg, pv_param_t *param,
 	si = grep_sock_info(&host, (unsigned short)port, (unsigned short)proto);
 	si = grep_sock_info(&host, (unsigned short)port, (unsigned short)proto);
 	if (si!=NULL)
 	if (si!=NULL)
 	{
 	{
-		msg->force_send_socket = si;
+		set_force_socket(msg, si);
 	} else {
 	} else {
 		LM_WARN("no socket found to match [%.*s]\n",
 		LM_WARN("no socket found to match [%.*s]\n",
 				val->rs.len, val->rs.s);
 				val->rs.len, val->rs.s);

+ 1 - 1
modules_k/registrar/lookup.c

@@ -134,7 +134,7 @@ int lookup(struct sip_msg* _m, char* _t, char* _s)
 		setbflagsval( 0, ptr->cflags);
 		setbflagsval( 0, ptr->cflags);
 
 
 		if (ptr->sock)
 		if (ptr->sock)
-			_m->force_send_socket = ptr->sock;
+			set_force_socket(_m, ptr->sock);
 
 
 		ptr = ptr->next;
 		ptr = ptr->next;
 	}
 	}

+ 1 - 1
modules_k/registrar/save.c

@@ -280,7 +280,7 @@ static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c,
 
 
 		/* set flags */
 		/* set flags */
 		ci.flags  = _f;
 		ci.flags  = _f;
-		getbflagsval(0, &ci.flags);
+		getbflagsval(0, &ci.cflags);
 
 
 		/* get received */
 		/* get received */
 		if (path_received.len && path_received.s) {
 		if (path_received.len && path_received.s) {

+ 2 - 2
modules_k/rr/loose.c

@@ -597,7 +597,7 @@ static inline int after_strict(struct sip_msg* _m)
 		 * send interface the one advertise in second Route */
 		 * send interface the one advertise in second Route */
 		si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
 		si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
 		if (si) {
 		if (si) {
-			_m->force_send_socket = si;
+			set_force_socket(_m, si);
 		} else {
 		} else {
 			LM_WARN("no socket found for match second RR\n");
 			LM_WARN("no socket found for match second RR\n");
 		}
 		}
@@ -813,7 +813,7 @@ static inline int after_loose(struct sip_msg* _m, int preloaded)
 			}
 			}
 			si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
 			si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
 			if (si) {
 			if (si) {
-				_m->force_send_socket = si;
+				set_force_socket(_m, si);
 			} else {
 			} else {
 				LM_WARN("no socket found for match second RR\n");
 				LM_WARN("no socket found for match second RR\n");
 			}
 			}

+ 3 - 1
modules_k/seas/seas_action.c

@@ -817,7 +817,9 @@ int ac_sl_msg(as_p the_as,char *action,int len)
    }else{
    }else{
       uri = GET_RURI(my_msg);
       uri = GET_RURI(my_msg);
    }
    }
-   my_msg->force_send_socket=grep_sock_info(&my_msg->via1->host,my_msg->via1->port,my_msg->via1->proto);
+   set_force_socket(my_msg, grep_sock_info(&my_msg->via1->host,
+                                            my_msg->via1->port,
+                                            my_msg->via1->proto) );
    /* or also could be:
    /* or also could be:
       my_msg->force_send_socket=the_as->binds[processor_id].bind_address;
       my_msg->force_send_socket=the_as->binds[processor_id].bind_address;
       not sure which is better...
       not sure which is better...

+ 2 - 0
modules_k/textops/textops.c

@@ -1903,6 +1903,8 @@ static int msg_apply_changes_f(sip_msg_t *msg, char *str1, char *str2)
 	msg->flags              = tmp.flags;
 	msg->flags              = tmp.flags;
 	msg->msg_flags          = tmp.msg_flags;
 	msg->msg_flags          = tmp.msg_flags;
 	msg->force_send_socket  = tmp.force_send_socket;
 	msg->force_send_socket  = tmp.force_send_socket;
+	msg->fwd_send_flags     = tmp.fwd_send_flags;
+	msg->rpl_send_flags     = tmp.rpl_send_flags;
 	msg->dst_uri            = tmp.dst_uri;
 	msg->dst_uri            = tmp.dst_uri;
 	msg->path_vec           = tmp.path_vec;
 	msg->path_vec           = tmp.path_vec;
 
 

+ 2 - 0
modules_k/tmx/t_var.c

@@ -52,6 +52,8 @@ int pv_t_copy_msg(struct sip_msg *src, struct sip_msg *dst)
 	dst->set_global_address=src->set_global_address;
 	dst->set_global_address=src->set_global_address;
 	dst->set_global_port=src->set_global_port;
 	dst->set_global_port=src->set_global_port;
 	dst->flags = src->flags;
 	dst->flags = src->flags;
+	dst->fwd_send_flags = src->fwd_send_flags;
+	dst->rpl_send_flags = src->rpl_send_flags;
 	dst->force_send_socket = src->force_send_socket;
 	dst->force_send_socket = src->force_send_socket;
 
 
 	if (parse_msg(dst->buf, dst->len, dst)!=0)
 	if (parse_msg(dst->buf, dst->len, dst)!=0)

+ 2 - 2
modules_s/registrar/lookup.c

@@ -139,7 +139,7 @@ int lookup(struct sip_msg* _m, char* _t, char* _s)
 		}
 		}
 
 
 		if (ptr->sock) {
 		if (ptr->sock) {
-			_m->force_send_socket = ptr->sock;
+			set_force_socket(_m, ptr->sock);
 		}
 		}
 
 
 skip_rewrite_uri:
 skip_rewrite_uri:
@@ -302,7 +302,7 @@ int lookup2(struct sip_msg* msg, char* table, char* p2)
 		}
 		}
 
 
 		if (ptr->sock) {
 		if (ptr->sock) {
-			msg->force_send_socket = ptr->sock;
+			set_force_socket(msg, ptr->sock);
 		}
 		}
 
 
 skip_rewrite_uri:
 skip_rewrite_uri:

+ 3 - 3
modules_s/rr/loose.c

@@ -901,9 +901,9 @@ static inline int after_loose(struct sip_msg* _m, struct sip_uri* _pru, int _rou
 					LOG(L_ERR, "after_loose: Error while parsing the second route header\n");
 					LOG(L_ERR, "after_loose: Error while parsing the second route header\n");
 					return RR_ERROR;
 					return RR_ERROR;
 				}
 				}
-				_m->force_send_socket = grep_sock_info(&parsed_uri.host,
-								parsed_uri.port_no,
-								parsed_uri.proto);
+				set_force_socket(_m, grep_sock_info(&parsed_uri.host,
+													parsed_uri.port_no,
+													parsed_uri.proto) );
 				if (_m->force_send_socket == 0)
 				if (_m->force_send_socket == 0)
 					LOG(L_WARN, "after_loose: send socket cannot be set"
 					LOG(L_WARN, "after_loose: send socket cannot be set"
 						" based on the second route header\n");
 						" based on the second route header\n");

+ 9 - 0
parser/hf.c

@@ -221,6 +221,15 @@ void clean_hdr_field(struct hdr_field* hf)
 		case HDR_PATH_T:
 		case HDR_PATH_T:
 		case HDR_PRIVACY_T:
 		case HDR_PRIVACY_T:
 			break;
 			break;
+
+		case HDR_PPI_T:
+			free_to(hf->parsed);
+			break;
+
+		case HDR_PAI_T:
+			free_to(hf->parsed);
+			break;
+
 		default:
 		default:
 			LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n",
 			LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n",
 			    hf->type);
 			    hf->type);

+ 10 - 0
parser/msg_parser.c

@@ -255,6 +255,8 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 		case HDR_PROXY_AUTHENTICATE_T:
 		case HDR_PROXY_AUTHENTICATE_T:
 	    case HDR_PATH_T:
 	    case HDR_PATH_T:
 	    case HDR_PRIVACY_T:
 	    case HDR_PRIVACY_T:
+	    case HDR_PAI_T:
+	    case HDR_PPI_T:
 		case HDR_OTHER_T:
 		case HDR_OTHER_T:
 			/* just skip over it */
 			/* just skip over it */
 			hdr->body.s=tmp;
 			hdr->body.s=tmp;
@@ -540,6 +542,14 @@ int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next)
 				if (msg->privacy==0) msg->privacy=hf;
 				if (msg->privacy==0) msg->privacy=hf;
 				msg->parsed_flag|=HDR_PRIVACY_F;
 				msg->parsed_flag|=HDR_PRIVACY_F;
 				break;
 				break;
+		    case HDR_PAI_T:
+				if (msg->pai==0) msg->pai=hf;
+				msg->parsed_flag|=HDR_PAI_F;
+				break;
+		    case HDR_PPI_T:
+				if (msg->ppi==0) msg->ppi=hf;
+				msg->parsed_flag|=HDR_PPI_F;
+				break;
 			default:
 			default:
 				LOG(L_CRIT, "BUG: parse_headers: unknown header type %d\n",
 				LOG(L_CRIT, "BUG: parse_headers: unknown header type %d\n",
 							hf->type);
 							hf->type);

+ 19 - 0
parser/msg_parser.h

@@ -472,4 +472,23 @@ int set_path_vector(struct sip_msg* msg, str* path);
 
 
 void reset_path_vector(struct sip_msg* msg);
 void reset_path_vector(struct sip_msg* msg);
 
 
+
+/** force a specific send socket for forwarding a request.
+ * @param msg - sip msg.
+ * @param fsocket - forced socket, pointer to struct socket_info, can be 0 (in
+ *                  which case it's equivalent to reset_force_socket()).
+ */
+#define set_force_socket(msg, fsocket) \
+	do { \
+		(msg)->force_send_socket=(fsocket); \
+		if ((msg)->force_send_socket) \
+			(msg)->fwd_send_flags |= SND_F_FORCE_SOCKET; \
+		else \
+			(msg)->fwd_send_flags &= ~SND_F_FORCE_SOCKET; \
+	} while (0)
+
+/** reset a previously forced send socket. */
+#define reset_force_socket(msg) set_force_socket(msg, 0)
+
+
 #endif
 #endif

+ 20 - 0
parser/parse_hname2.c

@@ -170,6 +170,24 @@ static inline char* skip_ws(char* p, unsigned int size)
         }
         }
 
 
 
 
+int hdr_update_type(struct hdr_field* hdr)
+{
+	if(hdr==0 || hdr->name.s==0)
+		return -1;
+	switch(hdr->name.len) {
+		case 19:
+			if(strncasecmp(hdr->name.s, "P-Asserted-Identity", 19)==0)
+				hdr->type = HDR_PAI_T;
+		break;
+		case 20:
+			if(strncasecmp(hdr->name.s, "P-Preferred-Identity", 20)==0)
+				hdr->type = HDR_PPI_T;
+		break;
+	}
+
+	return 0;
+}
+
 char* parse_hname2(char* begin, char* end, struct hdr_field* hdr)
 char* parse_hname2(char* begin, char* end, struct hdr_field* hdr)
 {
 {
 	register char* p;
 	register char* p;
@@ -249,6 +267,8 @@ char* parse_hname2(char* begin, char* end, struct hdr_field* hdr)
 	} else {
 	} else {
 		hdr->type = HDR_OTHER_T;
 		hdr->type = HDR_OTHER_T;
 		hdr->name.len = p - hdr->name.s;
 		hdr->name.len = p - hdr->name.s;
+		hdr_update_type(hdr);
 		return (p + 1);
 		return (p + 1);
 	}
 	}
 }
 }
+

+ 11 - 0
route.c

@@ -983,6 +983,17 @@ int fix_actions(struct action* a)
 									(unsigned int)t->val[0].u.number);
 									(unsigned int)t->val[0].u.number);
 				}
 				}
 				break;
 				break;
+			case APPEND_BRANCH_T:
+				if (t->val[0].type!=STRING_ST){
+					BUG("invalid subtype%d for append_branch_t\n",
+								t->val[0].type);
+					return E_BUG;
+				}
+				s.s=t->val[0].u.string;
+				s.len=(s.s)?strlen(s.s):0;
+				t->val[0].u.str=s;
+				t->val[0].type=STR_ST;
+				break;
 			default:
 			default:
 				/* no fixup required for the rest */
 				/* no fixup required for the rest */
 				break;
 				break;