changeset 89:3f8b437bcb66

Added some default routing handlers
author Sebastien Decugis <sdecugis@nict.go.jp>
date Mon, 07 Dec 2009 16:56:42 +0900
parents 9e2db1647d6f
children 2c9444152e4b
files freeDiameter/dispatch.c freeDiameter/routing.c include/freeDiameter/freeDiameter.h
diffstat 3 files changed, 107 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/freeDiameter/dispatch.c	Mon Dec 07 15:51:09 2009 +0900
+++ b/freeDiameter/dispatch.c	Mon Dec 07 16:56:42 2009 +0900
@@ -66,6 +66,7 @@
 }
 
 
-/* Note2: if the message is still for local delivery, we should test for duplicate
+/* Note: if the message is for local delivery, we should test for duplicate
   (draft-asveren-dime-dupcons-00). This may conflict with path validation decisions, no clear answer yet */
 
+
--- a/freeDiameter/routing.c	Mon Dec 07 15:51:09 2009 +0900
+++ b/freeDiameter/routing.c	Mon Dec 07 16:56:42 2009 +0900
@@ -305,7 +305,6 @@
 	return 0;
 }
 
-
 /* The (routing-in) thread -- see description in freeDiameter.h */
 static void * routing_in_thr(void * arg)
 {
@@ -742,6 +741,104 @@
 	return NULL;
 }
 
+/* First OUT callback: prevent sending to peers that do not support the message application */
+static int dont_send_if_no_common_app(void * cbdata, struct msg * msg, struct fd_list * candidates)
+{
+	struct fd_list * li;
+	struct msg_hdr * hdr;
+	
+	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+	CHECK_PARAMS(msg && candidates);
+	
+	CHECK_FCT( fd_msg_hdr(msg, &hdr) );
+	
+	/* For Base Diameter Protocol, every peer is supposed to support it, so skip */
+	if (hdr->msg_appl == 0)
+		return 0;
+	
+	/* Otherwise, check that the peers support the application */
+	for (li = candidates->next; li != candidates; li = li->next) {
+		struct rtd_candidate *c = (struct rtd_candidate *) li;
+		struct fd_peer * peer;
+		struct fd_app *found;
+		CHECK_FCT( fd_peer_getbyid( c->diamid, (void *)&peer ) );
+		if (peer && (peer->p_hdr.info.runtime.pir_relay == 0)) {
+			/* Check if the remote peer advertised the message's appli */
+			CHECK_FCT( fd_app_check(&peer->p_hdr.info.runtime.pir_apps, hdr->msg_appl, &found) );
+			if (!found)
+				c->score += FD_SCORE_NO_DELIVERY;
+		}
+	}
+
+	return 0;
+}
+
+/* Second OUT callback: Detect if the Destination-Host and Destination-Realm match the peer */
+static int score_destination_avp(void * cbdata, struct msg * msg, struct fd_list * candidates)
+{
+	struct fd_list * li;
+	struct avp * avp;
+	union avp_value *dh = NULL, *dr = NULL;
+	
+	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+	CHECK_PARAMS(msg && candidates);
+	
+	/* Search the Destination-Host and Destination-Realm AVPs -- we could also use fd_msg_search_avp here, but this one is slightly more efficient */
+	CHECK_FCT(  fd_msg_browse(msg, MSG_BRW_FIRST_CHILD, &avp, NULL) );
+	while (avp) {
+		struct avp_hdr * ahdr;
+		CHECK_FCT(  fd_msg_avp_hdr( avp, &ahdr ) );
+
+		if (! (ahdr->avp_flags & AVP_FLAG_VENDOR)) {
+			switch (ahdr->avp_code) {
+				case AC_DESTINATION_HOST:
+					/* Parse this AVP */
+					CHECK_FCT( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict ) );
+					ASSERT( ahdr->avp_value );
+					dh = ahdr->avp_value;
+					break;
+
+				case AC_DESTINATION_REALM:
+					/* Parse this AVP */
+					CHECK_FCT( fd_msg_parse_dict ( avp, fd_g_config->cnf_dict ) );
+					ASSERT( ahdr->avp_value );
+					dr = ahdr->avp_value;
+					break;
+			}
+		}
+
+		if (dh && dr)
+			break;
+
+		/* Go to next AVP */
+		CHECK_FCT(  fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL) );
+	}
+	
+	/* Now, check each candidate against these AVP values */
+	for (li = candidates->next; li != candidates; li = li->next) {
+		struct rtd_candidate *c = (struct rtd_candidate *) li;
+		struct fd_peer * peer;
+		CHECK_FCT( fd_peer_getbyid( c->diamid, (void *)&peer ) );
+		if (peer) {
+			if (dh 
+				&& (dh->os.len == strlen(peer->p_hdr.info.pi_diamid)) 
+				&& (strncasecmp(peer->p_hdr.info.pi_diamid, dh->os.data, dh->os.len) == 0)) {
+				/* The candidate is the Destination-Host */
+				c->score += FD_SCORE_FINALDEST;
+			} else {
+				if (dr  && peer->p_hdr.info.runtime.pir_realm 
+					&& (dr->os.len == strlen(peer->p_hdr.info.runtime.pir_realm)) 
+					&& (strncasecmp(peer->p_hdr.info.runtime.pir_realm, dr->os.data, dr->os.len) == 0)) {
+					/* The candidate's realm matchs the Destination-Realm */
+					c->score += FD_SCORE_REALM;
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
 static pthread_t rt_out = (pthread_t)NULL;
 static pthread_t rt_in  = (pthread_t)NULL;
 
@@ -752,6 +849,11 @@
 	CHECK_POSIX( pthread_create( &rt_in,  NULL, routing_in_thr,  NULL) );
 	
 	/* Later: TODO("Set the thresholds for the IN and OUT queues to create more routing threads as needed"); */
+	
+	/* Register the built-in callbacks */
+	CHECK_FCT( fd_rt_out_register( dont_send_if_no_common_app, NULL, 10, NULL ) );
+	CHECK_FCT( fd_rt_out_register( score_destination_avp, NULL, 10, NULL ) );
+	
 	return 0;
 }
 
--- a/include/freeDiameter/freeDiameter.h	Mon Dec 07 15:51:09 2009 +0900
+++ b/include/freeDiameter/freeDiameter.h	Mon Dec 07 16:56:42 2009 +0900
@@ -564,13 +564,14 @@
 	FD_SCORE_LOAD_BALANCE	 =   1,	/* Use this to differentiate between several peers with the same score */
 	FD_SCORE_DEFAULT	 =   5,	/* The peer is a default route for all messages */
 	FD_SCORE_DEFAULT_REALM	 =  10,	/* The peer is a default route for this realm */
+	FD_SCORE_REALM		 =  15,	/* The peer belongs to Destination-Realm of the message */
 	FD_SCORE_REDIR_HOST	 =  25,	/* If there is a redirect rule with ALL_HOST for these message and peer */
 	FD_SCORE_REDIR_APP	 =  30,	/* If there is a redirect rule with ALL_APPLICATION for these message and peer */
 	FD_SCORE_REDIR_REALM	 =  35,	/* If there is a redirect rule with ALL_REALM for these message and peer */
 	FD_SCORE_REDIR_REALM_APP =  40,	/* If there is a redirect rule with REALM_AND_APPLICATION for these message and peer */
 	FD_SCORE_REDIR_USER	 =  45,	/* If there is a redirect rule with ALL_USER for these message and peer */
 	FD_SCORE_REDIR_SESSION	 =  50,	/* If there is a redirect rule with ALL_SESSION for these message and peer */
-	FD_SCORE_FINALDEST	 = 100	/* If the peer is the final recipient of the message, it receives a big score. */
+	FD_SCORE_FINALDEST	 = 100	/* If the peer is the final recipient of the message (i.e. matching Destination-Host), it receives a big score. */
 };
 
 /*
"Welcome to our mercurial repository"