Mercurial > hg > freeDiameter
comparison libfdproto/messages.c @ 1092:e40374ddfeef
Optimization: do not attempt resolving dictionary objects again when it already failed during message parsing
author | Sebastien Decugis <sdecugis@freediameter.net> |
---|---|
date | Mon, 06 May 2013 11:30:34 +0800 |
parents | 7d7266115a34 |
children | 44f3e48dfe27 |
comparison
equal
deleted
inserted
replaced
1091:a7d8273b7506 | 1092:e40374ddfeef |
---|---|
86 /* The following structure represents an AVP instance. */ | 86 /* The following structure represents an AVP instance. */ |
87 struct avp { | 87 struct avp { |
88 struct msg_avp_chain avp_chain; /* Chaining information of this AVP */ | 88 struct msg_avp_chain avp_chain; /* Chaining information of this AVP */ |
89 int avp_eyec; /* Must be equal to MSG_AVP_EYEC */ | 89 int avp_eyec; /* Must be equal to MSG_AVP_EYEC */ |
90 struct dict_object *avp_model; /* If not NULL, pointer to the dictionary object of this avp */ | 90 struct dict_object *avp_model; /* If not NULL, pointer to the dictionary object of this avp */ |
91 struct { | |
92 avp_code_t mnf_code; | |
93 vendor_id_t mnf_vendor; | |
94 } avp_model_not_found; /* When model resolution has failed, store a copy of the data here to avoid searching again */ | |
91 struct avp_hdr avp_public; /* AVP data that can be managed by other modules */ | 95 struct avp_hdr avp_public; /* AVP data that can be managed by other modules */ |
92 | 96 |
93 uint8_t *avp_source; /* If the message was parsed from a buffer, pointer to the AVP data start in the buffer. */ | 97 uint8_t *avp_source; /* If the message was parsed from a buffer, pointer to the AVP data start in the buffer. */ |
94 uint8_t *avp_rawdata; /* when the data can not be interpreted, the raw data is copied here. The header is not part of it. */ | 98 uint8_t *avp_rawdata; /* when the data can not be interpreted, the raw data is copied here. The header is not part of it. */ |
95 size_t avp_rawlen; /* The length of the raw buffer. */ | 99 size_t avp_rawlen; /* The length of the raw buffer. */ |
110 /* The following structure represents an instance of a message (command and children AVPs). */ | 114 /* The following structure represents an instance of a message (command and children AVPs). */ |
111 struct msg { | 115 struct msg { |
112 struct msg_avp_chain msg_chain; /* List of the AVPs in the message */ | 116 struct msg_avp_chain msg_chain; /* List of the AVPs in the message */ |
113 int msg_eyec; /* Must be equal to MSG_MSG_EYEC */ | 117 int msg_eyec; /* Must be equal to MSG_MSG_EYEC */ |
114 struct dict_object *msg_model; /* If not NULL, pointer to the dictionary object of this message */ | 118 struct dict_object *msg_model; /* If not NULL, pointer to the dictionary object of this message */ |
119 struct { | |
120 command_code_t mnf_code; | |
121 uint8_t mnf_flags; | |
122 } msg_model_not_found; /* When model resolution has failed, store a copy of the data here to avoid searching again */ | |
115 struct msg_hdr msg_public; /* Message data that can be managed by extensions. */ | 123 struct msg_hdr msg_public; /* Message data that can be managed by extensions. */ |
116 | 124 |
117 uint8_t *msg_rawbuffer; /* data buffer that was received, saved during fd_msg_parse_buffer and freed in fd_msg_parse_dict */ | 125 uint8_t *msg_rawbuffer; /* data buffer that was received, saved during fd_msg_parse_buffer and freed in fd_msg_parse_dict */ |
118 int msg_routable; /* Is this a routable message? (0: undef, 1: routable, 2: non routable) */ | 126 int msg_routable; /* Is this a routable message? (0: undef, 1: routable, 2: non routable) */ |
119 struct msg *msg_query; /* the associated query if the message is a received answer */ | 127 struct msg *msg_query; /* the associated query if the message is a received answer */ |
344 ans->msg_public.msg_eteid = qry->msg_public.msg_eteid; | 352 ans->msg_public.msg_eteid = qry->msg_public.msg_eteid; |
345 ans->msg_public.msg_hbhid = qry->msg_public.msg_hbhid; | 353 ans->msg_public.msg_hbhid = qry->msg_public.msg_hbhid; |
346 | 354 |
347 /* Add the Session-Id AVP if session is known */ | 355 /* Add the Session-Id AVP if session is known */ |
348 if (sess && dict) { | 356 if (sess && dict) { |
349 struct dict_object * sess_id_avp; | 357 static struct dict_object * sess_id_avp = NULL; |
350 os0_t sid; | 358 os0_t sid; |
351 size_t sidlen; | 359 size_t sidlen; |
352 struct avp * avp; | 360 struct avp * avp; |
353 union avp_value val; | 361 union avp_value val; |
354 | 362 |
355 CHECK_FCT( fd_dict_search( dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sess_id_avp, ENOENT) ); | 363 if (!sess_id_avp) { |
364 CHECK_FCT( fd_dict_search( dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sess_id_avp, ENOENT) ); | |
365 } | |
356 CHECK_FCT( fd_sess_getsid ( sess, &sid, &sidlen ) ); | 366 CHECK_FCT( fd_sess_getsid ( sess, &sid, &sidlen ) ); |
357 CHECK_FCT( fd_msg_avp_new ( sess_id_avp, 0, &avp ) ); | 367 CHECK_FCT( fd_msg_avp_new ( sess_id_avp, 0, &avp ) ); |
358 val.os.data = sid; | 368 val.os.data = sid; |
359 val.os.len = sidlen; | 369 val.os.len = sidlen; |
360 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); | 370 CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) ); |
1966 /* We just erase the old model */ | 1976 /* We just erase the old model */ |
1967 avp->avp_model = NULL; | 1977 avp->avp_model = NULL; |
1968 } | 1978 } |
1969 } | 1979 } |
1970 | 1980 |
1971 /* Now try and resolve the model from the avp code and vendor */ | 1981 /* Check if we already searched for this model without success */ |
1972 if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { | 1982 if ((avp->avp_model_not_found.mnf_code != avp->avp_public.avp_code) |
1973 struct dict_avp_request_ex avpreq; | 1983 || (avp->avp_model_not_found.mnf_vendor != avp->avp_public.avp_vendor)) { |
1974 memset(&avpreq, 0, sizeof(avpreq)); | 1984 |
1975 avpreq.avp_vendor.vendor_id = avp->avp_public.avp_vendor; | 1985 /* Now try and resolve the model from the avp code and vendor */ |
1976 avpreq.avp_data.avp_code = avp->avp_public.avp_code; | 1986 if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { |
1977 CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_STRUCT, &avpreq, &avp->avp_model, 0)); | 1987 struct dict_avp_request_ex avpreq; |
1978 } else { | 1988 memset(&avpreq, 0, sizeof(avpreq)); |
1979 /* no vendor */ | 1989 avpreq.avp_vendor.vendor_id = avp->avp_public.avp_vendor; |
1980 CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_CODE, &avp->avp_public.avp_code, &avp->avp_model, 0)); | 1990 avpreq.avp_data.avp_code = avp->avp_public.avp_code; |
1991 CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_STRUCT, &avpreq, &avp->avp_model, 0)); | |
1992 } else { | |
1993 /* no vendor */ | |
1994 CHECK_FCT( fd_dict_search ( dict, DICT_AVP, AVP_BY_CODE, &avp->avp_public.avp_code, &avp->avp_model, 0)); | |
1995 } | |
1996 | |
1997 if (!avp->avp_model) { | |
1998 avp->avp_model_not_found.mnf_code = avp->avp_public.avp_code; | |
1999 avp->avp_model_not_found.mnf_vendor = avp->avp_public.avp_vendor; | |
2000 } | |
1981 } | 2001 } |
1982 | 2002 |
1983 /* First handle the case where we have not found this AVP in the dictionary */ | 2003 /* First handle the case where we have not found this AVP in the dictionary */ |
1984 if (!avp->avp_model) { | 2004 if (!avp->avp_model) { |
1985 | 2005 |
2140 | 2160 |
2141 TRACE_ENTRY("%p %p %d %p", dict, msg, only_hdr, error_info); | 2161 TRACE_ENTRY("%p %p %d %p", dict, msg, only_hdr, error_info); |
2142 | 2162 |
2143 CHECK_PARAMS( CHECK_MSG(msg) ); | 2163 CHECK_PARAMS( CHECK_MSG(msg) ); |
2144 | 2164 |
2165 /* First, check if we already have a model. */ | |
2166 if (msg->msg_model != NULL) { | |
2167 /* Check if this model is still valid for the message data */ | |
2168 enum dict_object_type dicttype; | |
2169 struct dict_cmd_data data; | |
2170 ASSERT(((fd_dict_gettype(msg->msg_model, &dicttype) == 0) && (dicttype == DICT_COMMAND))); | |
2171 (void)fd_dict_getval( msg->msg_model, &data); | |
2172 if ((data.cmd_code != msg->msg_public.msg_code) | |
2173 || ((data.cmd_flag_val & data.cmd_flag_mask) != (msg->msg_public.msg_flags && data.cmd_flag_mask))) { | |
2174 msg->msg_model = NULL; | |
2175 } else { | |
2176 goto chain; | |
2177 } | |
2178 } | |
2179 | |
2180 /* Check if we already searched for this model without success */ | |
2181 if ((msg->msg_model_not_found.mnf_code == msg->msg_public.msg_code) | |
2182 && (msg->msg_model_not_found.mnf_flags == msg->msg_public.msg_flags)) { | |
2183 goto no_model; | |
2184 } else { | |
2185 msg->msg_model_not_found.mnf_code = 0; | |
2186 } | |
2187 | |
2145 /* Look for the model from the header */ | 2188 /* Look for the model from the header */ |
2146 CHECK_FCT_DO( ret = fd_dict_search ( dict, DICT_COMMAND, | 2189 CHECK_FCT_DO( ret = fd_dict_search ( dict, DICT_COMMAND, |
2147 (msg->msg_public.msg_flags & CMD_FLAG_REQUEST) ? CMD_BY_CODE_R : CMD_BY_CODE_A, | 2190 (msg->msg_public.msg_flags & CMD_FLAG_REQUEST) ? CMD_BY_CODE_R : CMD_BY_CODE_A, |
2148 &msg->msg_public.msg_code, | 2191 &msg->msg_public.msg_code, |
2149 &msg->msg_model, ENOTSUP), | 2192 &msg->msg_model, ENOTSUP), |
2150 { | 2193 { |
2151 if ((ret == ENOTSUP) && (error_info)) { | 2194 if (ret == ENOTSUP) { |
2152 error_info->pei_errcode = "DIAMETER_COMMAND_UNSUPPORTED"; | 2195 /* update the model not found info */ |
2153 error_info->pei_protoerr = 1; | 2196 msg->msg_model_not_found.mnf_code = msg->msg_public.msg_code; |
2197 msg->msg_model_not_found.mnf_flags = msg->msg_public.msg_flags; | |
2198 goto no_model; | |
2154 } | 2199 } |
2155 return ret; | 2200 return ret; |
2156 } ); | 2201 } ); |
2157 | 2202 chain: |
2158 if (!only_hdr) { | 2203 if (!only_hdr) { |
2159 /* Then process the children */ | 2204 /* Then process the children */ |
2160 ret = parsedict_do_chain(dict, &msg->msg_chain.children, 1, error_info); | 2205 ret = parsedict_do_chain(dict, &msg->msg_chain.children, 1, error_info); |
2161 | 2206 |
2162 /* Free the raw buffer if any */ | 2207 /* Free the raw buffer if any */ |
2165 msg->msg_rawbuffer=NULL; | 2210 msg->msg_rawbuffer=NULL; |
2166 } | 2211 } |
2167 } | 2212 } |
2168 | 2213 |
2169 return ret; | 2214 return ret; |
2215 no_model: | |
2216 if (error_info) { | |
2217 error_info->pei_errcode = "DIAMETER_COMMAND_UNSUPPORTED"; | |
2218 error_info->pei_protoerr = 1; | |
2219 } | |
2220 return ENOTSUP; | |
2170 } | 2221 } |
2171 | 2222 |
2172 int fd_msg_parse_dict ( msg_or_avp * object, struct dictionary * dict, struct fd_pei *error_info ) | 2223 int fd_msg_parse_dict ( msg_or_avp * object, struct dictionary * dict, struct fd_pei *error_info ) |
2173 { | 2224 { |
2174 TRACE_ENTRY("%p %p %p", dict, object, error_info); | 2225 TRACE_ENTRY("%p %p %p", dict, object, error_info); |