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);
"Welcome to our mercurial repository"