2
0
Эх сурвалжийг харах

dispatcher: added two new flags to mode parameter of ds_is_from_list function for more strictly matching

- Two new flgs added:
  DS_MATCH_SOCKET (8) to take in account socket/sockname attribute of gw
  DS_MATCH_TRY_FULLADDRSOCK (16) try to find the most complete "address/protocol/port/local socket" combination for all dispatcher targets
Dennis Yurasov 1 жил өмнө
parent
commit
17536b1064

+ 90 - 22
src/modules/dispatcher/dispatch.c

@@ -82,6 +82,11 @@
 
 
 #define DS_HN_SIZE 256
 #define DS_HN_SIZE 256
 
 
+#define DS_MATCHED_ADDR 1
+#define DS_MATCHED_PORT (1 << 1)
+#define DS_MATCHED_PROTO (1 << 2)
+#define DS_MATCHED_SOCK (1 << 3)
+
 /* increment call load */
 /* increment call load */
 #define DS_LOAD_INC(dgrp, didx)      \
 #define DS_LOAD_INC(dgrp, didx)      \
 	do {                             \
 	do {                             \
@@ -126,6 +131,10 @@ static int *ds_list_nr = NULL;
 static int *ds_crt_idx = NULL;
 static int *ds_crt_idx = NULL;
 static int *ds_next_idx = NULL;
 static int *ds_next_idx = NULL;
 
 
+static ds_set_t *ds_strictest_node = NULL;
+static int ds_strictest_idx;
+static int ds_strictness;
+
 #define _ds_list (ds_lists[*ds_crt_idx])
 #define _ds_list (ds_lists[*ds_crt_idx])
 #define _ds_list_nr (*ds_list_nr)
 #define _ds_list_nr (*ds_list_nr)
 
 
@@ -3514,17 +3523,45 @@ int ds_fprint_list(FILE *fout)
 	return 0;
 	return 0;
 }
 }
 
 
+static int ds_set_vars(
+		sip_msg_t *_m, ds_set_t *node, int idx, int export_set_pv)
+{
+	pv_value_t val;
+	if(!node)
+		return -1;
+
+	if(export_set_pv && ds_setid_pvname.s != 0) {
+		memset(&val, 0, sizeof(pv_value_t));
+		val.flags = PV_VAL_INT | PV_TYPE_INT;
+
+		val.ri = node->id;
+		if(ds_setid_pv.setf(_m, &ds_setid_pv.pvp, (int)EQ_T, &val) < 0) {
+			LM_ERR("setting PV failed\n");
+			return -2;
+		}
+	}
+	if(ds_attrs_pvname.s != 0 && node->dlist[idx].attrs.body.len > 0) {
+		memset(&val, 0, sizeof(pv_value_t));
+		val.flags = PV_VAL_STR;
+		val.rs = node->dlist[idx].attrs.body;
+		if(ds_attrs_pv.setf(_m, &ds_attrs_pv.pvp, (int)EQ_T, &val) < 0) {
+			LM_ERR("setting attrs pv failed\n");
+			return -3;
+		}
+	}
+	return 1;
+}
 
 
 int ds_is_addr_from_set(sip_msg_t *_m, struct ip_addr *pipaddr,
 int ds_is_addr_from_set(sip_msg_t *_m, struct ip_addr *pipaddr,
 		unsigned short tport, unsigned short tproto, ds_set_t *node, int mode,
 		unsigned short tport, unsigned short tproto, ds_set_t *node, int mode,
 		int export_set_pv)
 		int export_set_pv)
 {
 {
-	pv_value_t val;
 	ip_addr_t *ipa;
 	ip_addr_t *ipa;
 	ip_addr_t ipaddress;
 	ip_addr_t ipaddress;
 	char hn[DS_HN_SIZE];
 	char hn[DS_HN_SIZE];
 	struct hostent *he;
 	struct hostent *he;
 	int j;
 	int j;
+	int node_strictness;
 	unsigned short sport = 0;
 	unsigned short sport = 0;
 	char sproto = PROTO_NONE;
 	char sproto = PROTO_NONE;
 
 
@@ -3567,33 +3604,54 @@ int ds_is_addr_from_set(sip_msg_t *_m, struct ip_addr *pipaddr,
 		}
 		}
 		if(ip_addr_cmp(pipaddr, ipa)
 		if(ip_addr_cmp(pipaddr, ipa)
 				&& ((mode & DS_MATCH_NOPORT) || node->dlist[j].port == 0
 				&& ((mode & DS_MATCH_NOPORT) || node->dlist[j].port == 0
-						|| tport == node->dlist[j].port)
-				&& ((mode & DS_MATCH_NOPROTO) || tproto == node->dlist[j].proto)
+						|| tport == node->dlist[j].port
+						|| (mode & DS_MATCH_TRY_FULLADDRSOCK))
+				&& ((mode & DS_MATCH_NOPROTO) || tproto == node->dlist[j].proto
+						|| (mode & DS_MATCH_TRY_FULLADDRSOCK))
 				&& (((mode & DS_MATCH_ACTIVE)
 				&& (((mode & DS_MATCH_ACTIVE)
 							&& !ds_skip_dst(node->dlist[j].flags))
 							&& !ds_skip_dst(node->dlist[j].flags))
-						|| !(mode & DS_MATCH_ACTIVE))) {
-			if(export_set_pv && ds_setid_pvname.s != 0) {
-				memset(&val, 0, sizeof(pv_value_t));
-				val.flags = PV_VAL_INT | PV_TYPE_INT;
+						|| !(mode & DS_MATCH_ACTIVE))
+				&& (((mode & DS_MATCH_SOCKET)
+							&& node->dlist[j].sock == _m->rcv.bind_address)
+						|| !node->dlist[j].sock || !(mode & DS_MATCH_SOCKET))) {
+
+			if(mode & DS_MATCH_TRY_FULLADDRSOCK) {
+				node_strictness = DS_MATCHED_ADDR;
+				if(node->dlist[j].port) {
+					if(tport != node->dlist[j].port)
+						continue;
+					else
+						node_strictness |= DS_MATCHED_PORT;
+				}
 
 
-				val.ri = node->id;
-				if(ds_setid_pv.setf(_m, &ds_setid_pv.pvp, (int)EQ_T, &val)
-						< 0) {
-					LM_ERR("setting PV failed\n");
-					return -2;
+				if(node->dlist[j].proto) {
+					if(tproto != node->dlist[j].proto)
+						continue;
+					else
+						node_strictness |= DS_MATCHED_PROTO;
 				}
 				}
-			}
-			if(ds_attrs_pvname.s != 0 && node->dlist[j].attrs.body.len > 0) {
-				memset(&val, 0, sizeof(pv_value_t));
-				val.flags = PV_VAL_STR;
-				val.rs = node->dlist[j].attrs.body;
-				if(ds_attrs_pv.setf(_m, &ds_attrs_pv.pvp, (int)EQ_T, &val)
-						< 0) {
-					LM_ERR("setting attrs pv failed\n");
-					return -3;
+
+				if(node->dlist[j].sock) {
+					if(node->dlist[j].sock != _m->rcv.bind_address)
+						continue;
+					else
+						node_strictness |= DS_MATCHED_SOCK;
+				}
+
+				if(node_strictness
+						== (DS_MATCHED_ADDR | DS_MATCHED_PORT | DS_MATCHED_PROTO
+								| DS_MATCHED_SOCK))
+					return ds_set_vars(_m, node, j, export_set_pv);
+
+				if(ds_strictness < node_strictness) {
+					ds_strictness = node_strictness;
+					ds_strictest_node = node;
+					ds_strictest_idx = j;
 				}
 				}
+				continue;
 			}
 			}
-			return 1;
+
+			return ds_set_vars(_m, node, j, export_set_pv);
 		}
 		}
 	}
 	}
 	return -1;
 	return -1;
@@ -3680,6 +3738,11 @@ int ds_is_addr_from_list(sip_msg_t *_m, int group, str *uri, int mode)
 	}
 	}
 
 
 
 
+	if(mode & DS_MATCH_TRY_FULLADDRSOCK) {
+		ds_strictness = 0;
+		ds_strictest_node = NULL;
+	}
+
 	if(group == -1) {
 	if(group == -1) {
 		rc = ds_is_addr_from_set_r(
 		rc = ds_is_addr_from_set_r(
 				_m, pipaddr, tport, tproto, _ds_list, mode, 1);
 				_m, pipaddr, tport, tproto, _ds_list, mode, 1);
@@ -3690,6 +3753,11 @@ int ds_is_addr_from_list(sip_msg_t *_m, int group, str *uri, int mode)
 		}
 		}
 	}
 	}
 
 
+	if(rc == -1 && mode & DS_MATCH_TRY_FULLADDRSOCK && ds_strictest_node) {
+		rc = ds_set_vars(
+				_m, ds_strictest_node, ds_strictest_idx, group == -1 ? 1 : 0);
+	}
+
 	return rc;
 	return rc;
 }
 }
 
 

+ 6 - 4
src/modules/dispatcher/dispatch.h

@@ -55,10 +55,12 @@
 #define DS_PROBE_INACTIVE	2
 #define DS_PROBE_INACTIVE	2
 #define DS_PROBE_ONLYFLAGGED	3
 #define DS_PROBE_ONLYFLAGGED	3
 
 
-#define DS_MATCH_ALL		0
-#define DS_MATCH_NOPORT		1
-#define DS_MATCH_NOPROTO	2
-#define DS_MATCH_ACTIVE 	4
+#define DS_MATCH_ALL			0
+#define DS_MATCH_NOPORT			1
+#define DS_MATCH_NOPROTO		2
+#define DS_MATCH_ACTIVE			4
+#define DS_MATCH_SOCKET			8
+#define DS_MATCH_TRY_FULLADDRSOCK	16
 
 
 #define DS_SETOP_DSTURI		0
 #define DS_SETOP_DSTURI		0
 #define DS_SETOP_RURI		1
 #define DS_SETOP_RURI		1

+ 4 - 1
src/modules/dispatcher/doc/dispatcher_admin.xml

@@ -1803,7 +1803,10 @@ if(ds_list_exists("10")) {
 				active status is ignored.
 				active status is ignored.
 				If bit one is set, then port is ignored.
 				If bit one is set, then port is ignored.
 				If bit two is set, then protocol is ignored.
 				If bit two is set, then protocol is ignored.
-				If bit three is set, then state must be active.	The parameter
+				If bit three is set, then state must be active.
+				If bit four is set, then socket/sockname be matched.
+				If bit five is set, then try to find the most complete 
+				"address/protocol/port/local socket" combination for all dispatcher targets.	The parameter
 				can be an integer or a variable holding an integer value.
 				can be an integer or a variable holding an integer value.
 				It must be provided if the uri parameter is provided.
 				It must be provided if the uri parameter is provided.
 			</para>
 			</para>