comparison 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
comparison
equal deleted inserted replaced
705:f0cb8f465763 706:4ffbc9f1e922
123 struct { 123 struct {
124 void (*fct)(void *, struct msg **); 124 void (*fct)(void *, struct msg **);
125 void * data; 125 void * data;
126 struct timespec timeout; 126 struct timespec timeout;
127 } msg_cb; /* Callback to be called when an answer is received, if not NULL */ 127 } msg_cb; /* Callback to be called when an answer is received, if not NULL */
128 char * msg_src_id; /* Diameter Id of the peer this message was received from. This string is malloc'd and must be freed */ 128 DiamId_t msg_src_id; /* Diameter Id of the peer this message was received from. This string is malloc'd and must be freed */
129 size_t msg_src_id_len; /* cached length of this string */
129 }; 130 };
130 131
131 /* Macro to compute the message header size */ 132 /* Macro to compute the message header size */
132 #define GETMSGHDRSZ() 20 133 #define GETMSGHDRSZ() 20
133 134
329 ans->msg_public.msg_hbhid = qry->msg_public.msg_hbhid; 330 ans->msg_public.msg_hbhid = qry->msg_public.msg_hbhid;
330 331
331 /* Add the Session-Id AVP if session is known */ 332 /* Add the Session-Id AVP if session is known */
332 if (sess && dict) { 333 if (sess && dict) {
333 struct dict_object * sess_id_avp; 334 struct dict_object * sess_id_avp;
334 char * sid; 335 os0_t sid;
336 size_t sidlen;
335 struct avp * avp; 337 struct avp * avp;
336 union avp_value val; 338 union avp_value val;
337 339
338 CHECK_FCT( fd_dict_search( dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sess_id_avp, ENOENT) ); 340 CHECK_FCT( fd_dict_search( dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sess_id_avp, ENOENT) );
339 CHECK_FCT( fd_sess_getsid ( sess, &sid ) ); 341 CHECK_FCT( fd_sess_getsid ( sess, &sid, &sidlen ) );
340 CHECK_FCT( fd_msg_avp_new ( sess_id_avp, 0, &avp ) ); 342 CHECK_FCT( fd_msg_avp_new ( sess_id_avp, 0, &avp ) );
341 val.os.data = (unsigned char *)sid; 343 val.os.data = sid;
342 val.os.len = strlen(sid); 344 val.os.len = sidlen;
343 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 345 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
344 CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_FIRST_CHILD, avp ) ); 346 CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_FIRST_CHILD, avp ) );
345 ans->msg_sess = sess; 347 ans->msg_sess = sess;
346 CHECK_FCT( fd_sess_ref_msg(sess) ); 348 CHECK_FCT( fd_sess_ref_msg(sess) );
347 } 349 }
700 msg->msg_public.msg_code, 702 msg->msg_public.msg_code,
701 msg->msg_public.msg_appl, 703 msg->msg_public.msg_appl,
702 msg->msg_public.msg_hbhid, 704 msg->msg_public.msg_hbhid,
703 msg->msg_public.msg_eteid 705 msg->msg_public.msg_eteid
704 ); 706 );
705 fd_log_debug_fstr(fstr, INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s\n", 707 fd_log_debug_fstr(fstr, INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s(%zd)\n",
706 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)"); 708 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);
707 } 709 }
708 710
709 /* Dump an avp object */ 711 /* Dump an avp object */
710 static void obj_dump_avp ( struct avp * avp, int indent, FILE * fstr ) 712 static void obj_dump_avp ( struct avp * avp, int indent, FILE * fstr )
711 { 713 {
1009 } 1011 }
1010 1012
1011 return (msg->msg_routable == 1) ? 1 : 0; 1013 return (msg->msg_routable == 1) ? 1 : 0;
1012 } 1014 }
1013 1015
1016 /* cache the dictionary model for next function to avoid re-searching at every incoming message */
1017 static struct dict_object *cached_avp_rr_model = NULL;
1018 static struct dictionary *cached_avp_rr_dict = NULL;
1019 static pthread_mutex_t cached_avp_rr_lock = PTHREAD_MUTEX_INITIALIZER;
1020
1014 /* Associate source peer */ 1021 /* Associate source peer */
1015 int fd_msg_source_set( struct msg * msg, char * diamid, int add_rr, struct dictionary * dict ) 1022 int fd_msg_source_set( struct msg * msg, DiamId_t diamid, size_t diamidlen, int add_rr, struct dictionary * dict )
1016 { 1023 {
1017 TRACE_ENTRY( "%p %p %d %p", msg, diamid, add_rr, dict); 1024 TRACE_ENTRY( "%p %p %zd %d %p", msg, diamid, diamidlen, add_rr, dict);
1018 1025
1019 /* Check we received a valid message */ 1026 /* Check we received a valid message */
1020 CHECK_PARAMS( CHECK_MSG(msg) && ( (! add_rr) || dict ) ); 1027 CHECK_PARAMS( CHECK_MSG(msg) && ( (! add_rr) || dict ) );
1021 1028
1022 /* Cleanup any previous source */ 1029 /* Cleanup any previous source */
1023 free(msg->msg_src_id); msg->msg_src_id = NULL; 1030 free(msg->msg_src_id); msg->msg_src_id = NULL; msg->msg_src_id_len = 0;
1024 1031
1025 /* If the request is to cleanup the source, we are done */ 1032 /* If the request is to cleanup the source, we are done */
1026 if (diamid == NULL) { 1033 if (diamid == NULL) {
1027 return 0; 1034 return 0;
1028 } 1035 }
1029 1036
1030 /* Otherwise save the new informations */ 1037 /* Otherwise save the new informations */
1031 CHECK_MALLOC( msg->msg_src_id = strdup(diamid) ); 1038 CHECK_MALLOC( msg->msg_src_id = os0dup(diamid, diamidlen) );
1039 msg->msg_src_id_len = diamidlen;
1040
1032 1041
1033 if (add_rr) { 1042 if (add_rr) {
1034 struct dict_object *avp_rr_model; 1043 struct dict_object *avp_rr_model = NULL;
1035 avp_code_t code = AC_ROUTE_RECORD; 1044 avp_code_t code = AC_ROUTE_RECORD;
1036 struct avp *avp; 1045 struct avp *avp;
1037 union avp_value val; 1046 union avp_value val;
1038 1047
1039 /* Find the model for Route-Record in the dictionary */ 1048 /* Lock the cached values */
1040 CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_CODE, &code, &avp_rr_model, ENOENT) ); 1049 CHECK_POSIX( pthread_mutex_lock(&cached_avp_rr_lock) );
1050 if (cached_avp_rr_dict == dict) {
1051 avp_rr_model = cached_avp_rr_model;
1052 }
1053 CHECK_POSIX( pthread_mutex_unlock(&cached_avp_rr_lock) );
1054
1055 /* If it was not cached */
1056 if (!avp_rr_model) {
1057 /* Find the model for Route-Record in the dictionary */
1058 CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_CODE, &code, &avp_rr_model, ENOENT) );
1059
1060 /* Now cache this result */
1061 CHECK_POSIX( pthread_mutex_lock(&cached_avp_rr_lock) );
1062 cached_avp_rr_dict = dict;
1063 cached_avp_rr_model = avp_rr_model;
1064 CHECK_POSIX( pthread_mutex_unlock(&cached_avp_rr_lock) );
1065 }
1041 1066
1042 /* Create the AVP with this model */ 1067 /* Create the AVP with this model */
1043 CHECK_FCT( fd_msg_avp_new ( avp_rr_model, 0, &avp ) ); 1068 CHECK_FCT( fd_msg_avp_new ( avp_rr_model, 0, &avp ) );
1044 1069
1045 /* Set the AVP value with the diameter id */ 1070 /* Set the AVP value with the diameter id */
1046 memset(&val, 0, sizeof(val)); 1071 memset(&val, 0, sizeof(val));
1047 val.os.data = (unsigned char *)diamid; 1072 val.os.data = (uint8_t *)diamid;
1048 val.os.len = strlen(diamid); 1073 val.os.len = diamidlen;
1049 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); 1074 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
1050 1075
1051 /* Add the AVP in the message */ 1076 /* Add the AVP in the message */
1052 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) ); 1077 CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
1053 } 1078 }
1054 1079
1055 /* done */ 1080 /* done */
1056 return 0; 1081 return 0;
1057 } 1082 }
1058 1083
1059 int fd_msg_source_get( struct msg * msg, char ** diamid ) 1084 int fd_msg_source_get( struct msg * msg, DiamId_t* diamid, size_t * diamidlen )
1060 { 1085 {
1061 TRACE_ENTRY( "%p %p", msg, diamid); 1086 TRACE_ENTRY( "%p %p %p", msg, diamid, diamidlen);
1062 1087
1063 /* Check we received valid parameters */ 1088 /* Check we received valid parameters */
1064 CHECK_PARAMS( CHECK_MSG(msg) ); 1089 CHECK_PARAMS( CHECK_MSG(msg) );
1065 CHECK_PARAMS( diamid ); 1090 CHECK_PARAMS( diamid );
1066 1091
1067 /* Copy the informations */ 1092 /* Copy the informations */
1068 *diamid = msg->msg_src_id; 1093 *diamid = msg->msg_src_id;
1094
1095 if (diamidlen)
1096 *diamidlen = msg->msg_src_id_len;
1069 1097
1070 /* done */ 1098 /* done */
1071 return 0; 1099 return 0;
1072 } 1100 }
1073 1101
2222 #define TEST_ACTION_STOP() \ 2250 #define TEST_ACTION_STOP() \
2223 if ((*msg == NULL) || (*action != DISP_ACT_CONT)) \ 2251 if ((*msg == NULL) || (*action != DISP_ACT_CONT)) \
2224 goto out; 2252 goto out;
2225 2253
2226 /* Call all dispatch callbacks for a given message */ 2254 /* Call all dispatch callbacks for a given message */
2227 int fd_msg_dispatch ( struct msg ** msg, struct session * session, enum disp_action *action, const char ** error_code) 2255 int fd_msg_dispatch ( struct msg ** msg, struct session * session, enum disp_action *action, char ** error_code)
2228 { 2256 {
2229 struct dictionary * dict; 2257 struct dictionary * dict;
2230 struct dict_object * app; 2258 struct dict_object * app;
2231 struct dict_object * cmd; 2259 struct dict_object * cmd;
2232 struct avp * avp; 2260 struct avp * avp;
"Welcome to our mercurial repository"