diff libfdproto/messages.c @ 706:4ffbc9f1e922

Large UNTESTED commit with the following changes: * Improved DiameterIdentity handling (esp. interationalization issues), and improve efficiency of some string operations in peers, sessions, and dictionary modules (closes #7) * Cleanup in the session module to free only unreferenced sessions (#16) * Removed fd_cpu_flush_cache(), replaced by more robust alternatives. * Improved peer state machine algorithm to counter SCTP multistream race condition.
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 09 Feb 2011 15:26:58 +0900
parents 289632905e19
children e60376cb15e8
line wrap: on
line diff
--- a/libfdproto/messages.c	Mon Jan 31 17:22:21 2011 +0900
+++ b/libfdproto/messages.c	Wed Feb 09 15:26:58 2011 +0900
@@ -125,7 +125,8 @@
 			void * data;
 			struct timespec timeout;
 		}		 msg_cb;		/* Callback to be called when an answer is received, if not NULL */
-	char *			 msg_src_id;		/* Diameter Id of the peer this message was received from. This string is malloc'd and must be freed */
+	DiamId_t		 msg_src_id;		/* Diameter Id of the peer this message was received from. This string is malloc'd and must be freed */
+	size_t			 msg_src_id_len;	/* cached length of this string */
 };
 
 /* Macro to compute the message header size */
@@ -331,15 +332,16 @@
 	/* Add the Session-Id AVP if session is known */
 	if (sess && dict) {
 		struct dict_object * sess_id_avp;
-		char * sid;
+		os0_t sid;
+		size_t sidlen;
 		struct avp * avp;
 		union avp_value val;
 		
 		CHECK_FCT( fd_dict_search( dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sess_id_avp, ENOENT) );
-		CHECK_FCT( fd_sess_getsid ( sess, &sid ) );
+		CHECK_FCT( fd_sess_getsid ( sess, &sid, &sidlen ) );
 		CHECK_FCT( fd_msg_avp_new ( sess_id_avp, 0, &avp ) );
-		val.os.data = (unsigned char *)sid;
-		val.os.len  = strlen(sid);
+		val.os.data = sid;
+		val.os.len  = sidlen;
 		CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
 		CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_FIRST_CHILD, avp ) );
 		ans->msg_sess = sess;
@@ -702,8 +704,8 @@
 		msg->msg_public.msg_hbhid,
 		msg->msg_public.msg_eteid
 		);
-	fd_log_debug_fstr(fstr, INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s\n", 
-			INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_associated, msg->msg_sess, msg->msg_src_id?:"(nil)");
+	fd_log_debug_fstr(fstr, INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s(%zd)\n", 
+			INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_associated, msg->msg_sess, msg->msg_src_id?:"(nil)", msg->msg_src_id_len);
 }
 
 /* Dump an avp object */
@@ -1011,16 +1013,21 @@
 	return (msg->msg_routable == 1) ? 1 : 0;
 }
 
+/* cache the dictionary model for next function to avoid re-searching at every incoming message */
+static struct dict_object *cached_avp_rr_model = NULL;
+static struct dictionary  *cached_avp_rr_dict  = NULL;
+static pthread_mutex_t     cached_avp_rr_lock = PTHREAD_MUTEX_INITIALIZER;
+
 /* Associate source peer */
-int fd_msg_source_set( struct msg * msg, char * diamid, int add_rr, struct dictionary * dict )
+int fd_msg_source_set( struct msg * msg, DiamId_t diamid, size_t diamidlen, int add_rr, struct dictionary * dict )
 {
-	TRACE_ENTRY( "%p %p %d %p", msg, diamid, add_rr, dict);
+	TRACE_ENTRY( "%p %p %zd %d %p", msg, diamid, diamidlen, add_rr, dict);
 	
 	/* Check we received a valid message */
 	CHECK_PARAMS( CHECK_MSG(msg) && ( (! add_rr) || dict ) );
 	
 	/* Cleanup any previous source */
-	free(msg->msg_src_id); msg->msg_src_id = NULL;
+	free(msg->msg_src_id); msg->msg_src_id = NULL; msg->msg_src_id_len = 0;
 	
 	/* If the request is to cleanup the source, we are done */
 	if (diamid == NULL) {
@@ -1028,24 +1035,42 @@
 	}
 	
 	/* Otherwise save the new informations */
-	CHECK_MALLOC( msg->msg_src_id = strdup(diamid) );
+	CHECK_MALLOC( msg->msg_src_id = os0dup(diamid, diamidlen) );
+	msg->msg_src_id_len = diamidlen;
+	
 	
 	if (add_rr) {
-		struct dict_object 	*avp_rr_model;
+		struct dict_object 	*avp_rr_model = NULL;
 		avp_code_t 		 code = AC_ROUTE_RECORD;
 		struct avp 		*avp;
 		union avp_value		 val;
 		
-		/* Find the model for Route-Record in the dictionary */
-		CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_CODE, &code, &avp_rr_model, ENOENT) );
+		/* Lock the cached values */
+		CHECK_POSIX( pthread_mutex_lock(&cached_avp_rr_lock) );
+		if (cached_avp_rr_dict == dict) {
+			avp_rr_model = cached_avp_rr_model;
+		}
+		CHECK_POSIX( pthread_mutex_unlock(&cached_avp_rr_lock) );
+		
+		/* If it was not cached */
+		if (!avp_rr_model) {
+			/* Find the model for Route-Record in the dictionary */
+			CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_CODE, &code, &avp_rr_model, ENOENT) );
+			
+			/* Now cache this result */
+			CHECK_POSIX( pthread_mutex_lock(&cached_avp_rr_lock) );
+			cached_avp_rr_dict  = dict;
+			cached_avp_rr_model = avp_rr_model;
+			CHECK_POSIX( pthread_mutex_unlock(&cached_avp_rr_lock) );
+		}
 		
 		/* Create the AVP with this model */
 		CHECK_FCT( fd_msg_avp_new ( avp_rr_model, 0, &avp ) );
 		
 		/* Set the AVP value with the diameter id */
 		memset(&val, 0, sizeof(val));
-		val.os.data = (unsigned char *)diamid;
-		val.os.len  = strlen(diamid);
+		val.os.data = (uint8_t *)diamid;
+		val.os.len  = diamidlen;
 		CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
 
 		/* Add the AVP in the message */
@@ -1056,9 +1081,9 @@
 	return 0;
 }
 
-int fd_msg_source_get( struct msg * msg, char ** diamid )
+int fd_msg_source_get( struct msg * msg, DiamId_t* diamid, size_t * diamidlen )
 {
-	TRACE_ENTRY( "%p %p", msg, diamid);
+	TRACE_ENTRY( "%p %p %p", msg, diamid, diamidlen);
 	
 	/* Check we received valid parameters */
 	CHECK_PARAMS( CHECK_MSG(msg) );
@@ -1067,6 +1092,9 @@
 	/* Copy the informations */
 	*diamid = msg->msg_src_id;
 	
+	if (diamidlen)
+		*diamidlen = msg->msg_src_id_len;
+	
 	/* done */
 	return 0;
 }
@@ -2224,7 +2252,7 @@
 		goto out;
 
 /* Call all dispatch callbacks for a given message */
-int fd_msg_dispatch ( struct msg ** msg, struct session * session, enum disp_action *action, const char ** error_code)
+int fd_msg_dispatch ( struct msg ** msg, struct session * session, enum disp_action *action, char ** error_code)
 {
 	struct dictionary  * dict;
 	struct dict_object * app;
"Welcome to our mercurial repository"