Mercurial > hg > freeDiameter
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; |