changeset 35:6486e97f56ae

Added test for modified message parsing
author Sebastien Decugis <sdecugis@nict.go.jp>
date Mon, 02 Nov 2009 14:54:42 +0900
parents 0e2b57789361
children 1498b3c7304c
files freeDiameter/CMakeLists.txt freeDiameter/fD.h freeDiameter/p_ce.c freeDiameter/p_out.c freeDiameter/p_psm.c freeDiameter/tests/testmesg.c libfreeDiameter/messages.c
diffstat 7 files changed, 150 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/freeDiameter/CMakeLists.txt	Fri Oct 30 17:23:06 2009 +0900
+++ b/freeDiameter/CMakeLists.txt	Mon Nov 02 14:54:42 2009 +0900
@@ -19,6 +19,7 @@
 	messages.c
 	queues.c
 	peers.c
+	p_ce.c
 	p_expiry.c
 	p_out.c
 	p_psm.c
--- a/freeDiameter/fD.h	Fri Oct 30 17:23:06 2009 +0900
+++ b/freeDiameter/fD.h	Mon Nov 02 14:54:42 2009 +0900
@@ -242,6 +242,9 @@
 int fd_p_sr_fetch(struct sr_list * srlist, uint32_t hbh, struct msg **req);
 void fd_p_sr_failover(struct sr_list * srlist);
 
+/* Capabilities Exchange */
+int fd_p_ce_merge(struct fd_peer * peer, struct msg * cer);
+
 /* Active peers -- routing process should only ever take the read lock, the write lock is managed by PSMs */
 extern struct fd_list fd_g_activ_peers;
 extern pthread_rwlock_t fd_g_activ_peers_rw; /* protect the list */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/p_ce.c	Mon Nov 02 14:54:42 2009 +0900
@@ -0,0 +1,45 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fD.h"
+
+/* This file contains code to handle Capabilities Exchange messages (CER and CEA) */
+
+int fd_p_ce_merge(struct fd_peer * peer, struct msg * cer)
+{
+	/* Save all information from the CER into the peer structure, after cleaning old information if any */
+	
+	return ENOTSUP;
+}
--- a/freeDiameter/p_out.c	Fri Oct 30 17:23:06 2009 +0900
+++ b/freeDiameter/p_out.c	Mon Nov 02 14:54:42 2009 +0900
@@ -154,7 +154,13 @@
 			cnx = peer->p_cnxctx;
 
 		/* Do send the message */
-		CHECK_FCT( do_send(msg, cnx, hbh, peer ? &peer->p_sr : NULL) );
+		CHECK_FCT_DO( do_send(msg, cnx, hbh, peer ? &peer->p_sr : NULL),
+			{
+				fd_log_debug("An error occurred while sending this message, it is lost:\n");
+				fd_msg_dump_walk(NONE, *msg);
+				fd_msg_free(*msg);
+				*msg = NULL;
+			} );
 	}
 	
 	return 0;
--- a/freeDiameter/p_psm.c	Fri Oct 30 17:23:06 2009 +0900
+++ b/freeDiameter/p_psm.c	Mon Nov 02 14:54:42 2009 +0900
@@ -358,11 +358,23 @@
 		}
 		
 		/* Link-local message: They must be understood by our dictionary */
+		{
+			int ret;
+			CHECK_FCT_DO( ret = fd_msg_parse_or_error( &msg ),
+				{
+					if ((ret == EBADMSG) && (msg != NULL)) {
+						/* msg now contains an answer message to send back */
+						CHECK_FCT_DO( fd_out_send(&msg, peer->p_cnxctx, peer), /* In case of error the message has already been dumped */ );
+					}
+					if (msg) {
+						CHECK_FCT_DO( fd_msg_free(msg), /* continue */);
+					}
+					goto psm_loop;
+				} );
+		}
 		
-		TODO("Check if it is a local message (CER, DWR, ...)");
-		TODO("If not, check we are in OPEN state");
-		TODO("Update expiry timer if needed");
-		TODO("Handle the message");
+		/* Handle the LL message and update the expiry timer appropriately */
+		TODO("...");
 	}
 	
 	/* The connection object is broken */
@@ -400,6 +412,12 @@
 			case STATE_CLOSED:
 				TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake, move to OPEN or REOPEN state");
 				/* In case of error : DIAMETER_UNKNOWN_PEER */
+				
+				CHECK_FCT_DO( fd_p_ce_merge(peer, params->cer),
+					{
+						
+					} );
+				
 				break;
 				
 			case STATE_WAITCNXACK:
--- a/freeDiameter/tests/testmesg.c	Fri Oct 30 17:23:06 2009 +0900
+++ b/freeDiameter/tests/testmesg.c	Mon Nov 02 14:54:42 2009 +0900
@@ -282,7 +282,14 @@
 			ADD_RULE(gavp, 73565, "AVP Test - os", 	    	    RULE_REQUIRED,     2, 3, 0);
 			ADD_RULE(gavp, 73565, "AVP Test - enumos",     	    RULE_OPTIONAL,     0, 1, 0);
 			ADD_RULE(gavp, 73565, "AVP Test - grouped",         RULE_FIXED_TAIL,  -1, 1, 1);
-			
+			/* ABNF : 
+				< no vendor - f32 >
+				< i64 >
+				< enumi32 >
+			    2*3 { os }
+			     *1 [ enumos ]
+				< grouped >
+						*/
 			#if 0
 			fd_dict_dump_object ( gavp );
 			#endif
@@ -727,9 +734,9 @@
 		
 		/* Now test the msg_parse_rule function */
 		{
-			struct dict_object * rule;
+			struct fd_pei pei;
 			
-			CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &rule ) );
+			CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ) );
 			
 			/* Use the "AVP Test - rules" AVP to test the rules */
 			{
@@ -748,38 +755,50 @@
 				ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp, 73565, "AVP Test - grouped" );
 				
 				/* Check the message is still conform */
-				CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &rule ) );
+				CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ) );
 				
 				/* The first avp is optional in fixed position, so remove it and check the message is still OK */
 				CHECK( 0, fd_msg_browse ( tavp, MSG_BRW_FIRST_CHILD, &childavp, NULL) );
 				CHECK( 0, fd_msg_free ( childavp ) );
-				CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &rule ) );
+				CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ) );
 				ADD_AVP( tavp, MSG_BRW_FIRST_CHILD, childavp,     0, "AVP Test - no vendor - f32" );
 				
 				
 				/* Now break some rules and check it is detected */
-				#define CHECK_CONFLICT( _msg, _ruleavp, _avpvendor )		{				\
-					struct dict_object * _rule;								\
-					CHECK( EBADMSG,  fd_msg_parse_rules( _msg, fd_g_config->cnf_dict, &_rule ) );			\
-					if ((_ruleavp) == NULL) {								\
-						CHECK( NULL, _rule);								\
+				#define CHECK_CONFLICT( _msg, _error, _conflictavp_name, _conflictavp_vnd )		{	\
+					struct fd_pei _pei;									\
+					CHECK( EBADMSG,  fd_msg_parse_rules( _msg, fd_g_config->cnf_dict, &_pei ) );		\
+					if (_error) {										\
+						CHECK( 0, strcmp( _error, _pei.pei_errcode ) );					\
+					}											\
+					if ((_conflictavp_name) == NULL) {							\
+						CHECK( NULL, _pei.pei_avp);							\
 					} else {										\
-						struct dict_rule_data   _ruledata;						\
+						struct dict_avp_request _req = { (_conflictavp_vnd), 0, (_conflictavp_name) };	\
 						struct dict_object *    _avp;							\
-						struct dict_avp_request _req = { (_avpvendor), 0, (_ruleavp) };			\
+						struct dict_object * _conflict;							\
+						CHECK( 1, (_pei.pei_avp) ? 1 : 0 );						\
+						CHECK( 0, fd_msg_model( _pei.pei_avp, &_conflict ) );				\
 						CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));	\
-						CHECK( 0, fd_dict_getval( _rule, &_ruledata ) );				\
-						CHECK( _avp, _ruledata.rule_avp );						\
+						CHECK( _avp, _conflict );							\
 					}											\
 				}
 
+			/* ABNF : 
+				< no vendor - f32 >
+				< i64 >
+				< enumi32 >
+			    2*3 { os }
+			     *1 [ enumos ]
+				< grouped >
+						*/
 				{
 					/* Test the FIXED_HEAD rules positions: add another AVP before the third */
 					CHECK( 0, fd_msg_browse ( tavp, MSG_BRW_FIRST_CHILD, &tempavp, NULL) ); /* tempavp is the novendor avp */
 					CHECK( 0, fd_msg_browse ( tempavp, MSG_BRW_NEXT, &tempavp, NULL) );     /* tempavp is the i64 avp */
 					ADD_AVP( tempavp, MSG_BRW_NEXT, childavp, 73565, "AVP Test - os" );
 					
-					CHECK_CONFLICT( msg, "AVP Test - enumi32", 73565 );
+					CHECK_CONFLICT( msg, "DIAMETER_MISSING_AVP", "AVP Test - enumi32", 73565 );
 					
 					/* Now remove this AVP */
 					CHECK( 0, fd_msg_free ( childavp ) );
@@ -789,7 +808,7 @@
 					CHECK( 0, fd_msg_browse ( tempavp, MSG_BRW_NEXT, &childavp, NULL) );     /* childavp is the enumi32 avp */
 					CHECK( 0, fd_msg_free ( childavp ) );
 					
-					CHECK_CONFLICT( msg, "AVP Test - enumi32", 73565 );
+					CHECK_CONFLICT( msg, "DIAMETER_MISSING_AVP", "AVP Test - enumi32", 73565 );
 					
 					/* Add the AVP back */
 					ADD_AVP( tempavp, MSG_BRW_NEXT, childavp, 73565, "AVP Test - enumi32" );
@@ -800,7 +819,7 @@
 					CHECK( 0, fd_msg_browse ( childavp, MSG_BRW_NEXT, &tempavp, NULL) );     /* tempavp is the os avp */
 					CHECK( 0, fd_msg_free ( tempavp ) );
 					
-					CHECK_CONFLICT( msg, "AVP Test - os", 73565 );	/* The rule requires at least 2 AVP, we have only 1 */
+					CHECK_CONFLICT( msg, "DIAMETER_MISSING_AVP", "AVP Test - os", 73565 ); /* The rule requires at least 2 AVP, we have only 1 */
 					
 					/* Now add this AVP */
 					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - os" );
@@ -810,7 +829,7 @@
 					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - os" );
 					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - os" );
 					
-					CHECK_CONFLICT( msg, "AVP Test - os", 73565 );	/* The rule requires at most 3 AVP, we have 4 */
+					CHECK_CONFLICT( msg, "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES", "AVP Test - os", 73565 ); /* The rule requires at most 3 AVP, we have 4 */
 					
 					/* Now delete these AVP */
 					CHECK( 0, fd_msg_free ( tempavp ) );
@@ -823,12 +842,12 @@
 					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - enumos" );
 					
 					/* The message is still conform */
-					CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &rule ) );
+					CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ) );
 					
 					/* Now break the rule */
 					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - enumos" );
 					
-					CHECK_CONFLICT( msg, "AVP Test - enumos", 73565 );	/* The rule requires at most 3 AVP, we have 4 */
+					CHECK_CONFLICT( msg, "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES", "AVP Test - enumos", 73565 );
 					
 					/* Now delete this AVP */
 					CHECK( 0, fd_msg_free ( tempavp ) );
@@ -838,7 +857,7 @@
 					/* Test the RULE_FIXED_TAIL rules positions: add another AVP at the end */
 					ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp, 73565, "AVP Test - os" );
 					
-					CHECK_CONFLICT( msg, "AVP Test - grouped", 73565 );
+					CHECK_CONFLICT( msg, "DIAMETER_MISSING_AVP", "AVP Test - grouped", 73565 );
 					
 					/* Now remove this AVP */
 					CHECK( 0, fd_msg_free ( childavp ) );
--- a/libfreeDiameter/messages.c	Fri Oct 30 17:23:06 2009 +0900
+++ b/libfreeDiameter/messages.c	Mon Nov 02 14:54:42 2009 +0900
@@ -1864,8 +1864,34 @@
 /* Create an empty AVP of a given model (to use in Failed-AVP) */
 static struct avp * empty_avp(struct dict_object * model_avp)
 {
-	TODO("Create the AVP instance and set a 0 value");
-	return NULL;
+	struct avp * avp = NULL;
+	struct dict_avp_data avp_info;
+	union avp_value val;
+	char os[1] = { '\0' };
+	
+	/* Create an instance */
+	CHECK_FCT_DO( fd_msg_avp_new(model_avp, 0, &avp ), return NULL );
+	
+	/* Type of the AVP */
+	CHECK_FCT_DO( fd_dict_getval(model_avp, &avp_info), return NULL );
+	
+	/* Prepare the empty value */
+	memset(&val, 0, sizeof(val));
+	switch (avp_info.avp_basetype) {
+		case AVP_TYPE_OCTETSTRING:
+			val.os.data = os;
+			val.os.len  = sizeof(os);
+		case AVP_TYPE_INTEGER32:
+		case AVP_TYPE_INTEGER64:
+		case AVP_TYPE_UNSIGNED32:
+		case AVP_TYPE_UNSIGNED64:
+		case AVP_TYPE_FLOAT32:
+		case AVP_TYPE_FLOAT64:
+			CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), return NULL );
+		/* For AVP_TYPE_GROUPED we don't do anything */
+	}
+	
+	return avp;
 }
 
 /* Check that a list of AVPs is compliant with a given rule -- will be iterated on the list of rules */
@@ -2055,12 +2081,12 @@
 {
 	TRACE_ENTRY("%p %p %p", object, dict, error_info);
 	
+	if (error_info)
+		memset(error_info, 0, sizeof(struct fd_pei));
+	
 	/* Resolve the dictionary objects when missing. This also validates the object. */
 	CHECK_FCT(  fd_msg_parse_dict ( object, dict )  );
 	
-	if (error_info)
-		memset(error_info, 0, sizeof(struct fd_pei));
-	
 	/* Call the recursive function */
 	return parserules_do ( dict, object, error_info, 1 ) ;
 }
@@ -2186,7 +2212,7 @@
 	
 	if (app == NULL) {
 		/* In that case, maybe we should answer a DIAMETER_APPLICATION_UNSUPPORTED error ? Do we do this here ? */
-		TRACE_DEBUG(NONE, "Reply DIAMETER_APPLICATION_UNSUPPORTED if it's a request ?");
+		TODO("Reply DIAMETER_APPLICATION_UNSUPPORTED if it's a request ?");
 	}
 	
 	/* So start browsing the message */
"Welcome to our mercurial repository"