comparison libfdproto/dictionary.c @ 1085:7d7266115a34

Cleaning of the traces in progress
author Sebastien Decugis <sdecugis@freediameter.net>
date Fri, 03 May 2013 19:20:56 +0800
parents b3d623f04b6d
children 44f3e48dfe27
comparison
equal deleted inserted replaced
1084:6b7966ea27fb 1085:7d7266115a34
145 145
146 int dict_count[DICT_TYPE_MAX + 1]; /* Number of objects of each type */ 146 int dict_count[DICT_TYPE_MAX + 1]; /* Number of objects of each type */
147 }; 147 };
148 148
149 /* Forward declarations of dump functions */ 149 /* Forward declarations of dump functions */
150 static void dump_vendor_data ( void * data ); 150 static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data );
151 static void dump_application_data ( void * data ); 151 static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data );
152 static void dump_type_data ( void * data ); 152 static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data );
153 /* the dump function for enum has a different prototype since it need the datatype */ 153 /* the dump function for enum has a different prototype since it need the datatype */
154 static void dump_avp_data ( void * data ); 154 static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_data, void * data );
155 static void dump_command_data ( void * data ); 155 static DECLARE_FD_DUMP_PROTOTYPE(dump_command_data, void * data );
156 static void dump_rule_data ( void * data ); 156 static DECLARE_FD_DUMP_PROTOTYPE(dump_rule_data, void * data );
157 157
158 /* Forward declarations of search functions */ 158 /* Forward declarations of search functions */
159 static int search_vendor ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ); 159 static int search_vendor ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result );
160 static int search_application ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ); 160 static int search_application ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result );
161 static int search_type ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ); 161 static int search_type ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result );
170 char * name; /* string describing this object, for debug */ 170 char * name; /* string describing this object, for debug */
171 size_t datasize; /* The size of the data structure */ 171 size_t datasize; /* The size of the data structure */
172 int parent; /* 0: never; 1: may; 2: must */ 172 int parent; /* 0: never; 1: may; 2: must */
173 enum dict_object_type parenttype; /* The type of the parent, when relevant */ 173 enum dict_object_type parenttype; /* The type of the parent, when relevant */
174 int eyecatcher; /* A kind of signature for this object */ 174 int eyecatcher; /* A kind of signature for this object */
175 void (*dump_data)(void * data ); /* The function to dump the data section */ 175 DECLARE_FD_DUMP_PROTOTYPE( (*dump_data), void * data ); /* The function to dump the data section */
176 int (*search_fct)(struct dictionary * dict, int criteria, const void * what, struct dict_object **result );; /* The function to search an object of this type */ 176 int (*search_fct)(struct dictionary * dict, int criteria, const void * what, struct dict_object **result );; /* The function to search an object of this type */
177 int haslist[NB_LISTS_PER_OBJ]; /* Tell if this list is used */ 177 int haslist[NB_LISTS_PER_OBJ]; /* Tell if this list is used */
178 } dict_obj_info[] = { { 0, "(error)", 0, 0, 0, 0, NULL, NULL, {0, 0, 0} } 178 } dict_obj_info[] = { { 0, "(error)", 0, 0, 0, 0, NULL, NULL, {0, 0, 0} }
179 179
180 /* type name datasize parent parenttype 180 /* type name datasize parent parenttype
1147 /* Dump / debug functions */ 1147 /* Dump / debug functions */
1148 /* */ 1148 /* */
1149 /*******************************************************************************************************/ 1149 /*******************************************************************************************************/
1150 /*******************************************************************************************************/ 1150 /*******************************************************************************************************/
1151 /* The following functions are used to debug the module, and allow to print out the content of the dictionary */ 1151 /* The following functions are used to debug the module, and allow to print out the content of the dictionary */
1152 static void dump_vendor_data ( void * data ) 1152 static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data )
1153 { 1153 {
1154 struct dict_vendor_data * vendor = (struct dict_vendor_data *)data; 1154 struct dict_vendor_data * vendor = (struct dict_vendor_data *)data;
1155 1155
1156 fd_log_debug("data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name); 1156 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name);
1157 } 1157 }
1158 static void dump_application_data ( void * data ) 1158 static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data )
1159 { 1159 {
1160 struct dict_application_data * appli = (struct dict_application_data *) data; 1160 struct dict_application_data * appli = (struct dict_application_data *) data;
1161 fd_log_debug("data: %-6u \"%s\"", appli->application_id, appli->application_name); 1161 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", appli->application_id, appli->application_name);
1162 } 1162 }
1163 static void dump_type_data ( void * data ) 1163 static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data )
1164 { 1164 {
1165 struct dict_type_data * type = ( struct dict_type_data * ) data; 1165 struct dict_type_data * type = ( struct dict_type_data * ) data;
1166 1166
1167 fd_log_debug("data: %-12s \"%s\"", 1167 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-12s \"%s\"",
1168 type_base_name[type->type_base], 1168 type_base_name[type->type_base],
1169 type->type_name); 1169 type->type_name);
1170 } 1170 }
1171 static void dump_enumval_data ( struct dict_enumval_data * enumval, enum dict_avp_basetype type ) 1171 static DECLARE_FD_DUMP_PROTOTYPE(dump_enumval_data, struct dict_enumval_data * enumval, enum dict_avp_basetype type )
1172 { 1172 {
1173 const int LEN_MAX = 20; 1173 const int LEN_MAX = 20;
1174 fd_log_debug("data: (%-12s) \"%s\" -> ", type_base_name[type], enumval->enum_name); 1174 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "data: (%-12s) \"%s\" -> ", type_base_name[type], enumval->enum_name), return NULL);
1175 switch (type) { 1175 switch (type) {
1176 case AVP_TYPE_OCTETSTRING: 1176 case AVP_TYPE_OCTETSTRING:
1177 { 1177 {
1178 int i, n=LEN_MAX; 1178 int i, n=LEN_MAX;
1179 if (enumval->enum_value.os.len < LEN_MAX) 1179 if (enumval->enum_value.os.len < LEN_MAX)
1180 n = enumval->enum_value.os.len; 1180 n = enumval->enum_value.os.len;
1181 for (i=0; i < n; i++) 1181 for (i=0; i < n; i++)
1182 fd_log_debug("0x%2hhX/'%c' ", enumval->enum_value.os.data[i], ASCII(enumval->enum_value.os.data[i])); 1182 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "0x%2hhX/'%c' ", enumval->enum_value.os.data[i], ASCII(enumval->enum_value.os.data[i])), return NULL);
1183 if (n == LEN_MAX) 1183 if (n == LEN_MAX)
1184 fd_log_debug("..."); 1184 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "..."), return NULL);
1185 } 1185 }
1186 break; 1186 break;
1187 1187
1188 case AVP_TYPE_INTEGER32: 1188 case AVP_TYPE_INTEGER32:
1189 fd_log_debug("%i", enumval->enum_value.i32); 1189 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%i", enumval->enum_value.i32), return NULL);
1190 break; 1190 break;
1191 1191
1192 case AVP_TYPE_INTEGER64: 1192 case AVP_TYPE_INTEGER64:
1193 fd_log_debug("%"PRId64, enumval->enum_value.i64); 1193 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%"PRId64, enumval->enum_value.i64), return NULL);
1194 break; 1194 break;
1195 1195
1196 case AVP_TYPE_UNSIGNED32: 1196 case AVP_TYPE_UNSIGNED32:
1197 fd_log_debug("%u", enumval->enum_value.u32); 1197 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%u", enumval->enum_value.u32), return NULL);
1198 break; 1198 break;
1199 1199
1200 case AVP_TYPE_UNSIGNED64: 1200 case AVP_TYPE_UNSIGNED64:
1201 fd_log_debug("%"PRIu64, enumval->enum_value.u64); 1201 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%"PRIu64, enumval->enum_value.u64), return NULL);
1202 break; 1202 break;
1203 1203
1204 case AVP_TYPE_FLOAT32: 1204 case AVP_TYPE_FLOAT32:
1205 fd_log_debug("%f", enumval->enum_value.f32); 1205 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%f", enumval->enum_value.f32), return NULL);
1206 break; 1206 break;
1207 1207
1208 case AVP_TYPE_FLOAT64: 1208 case AVP_TYPE_FLOAT64:
1209 fd_log_debug("%g", enumval->enum_value.f64); 1209 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", enumval->enum_value.f64), return NULL);
1210 break; 1210 break;
1211 1211
1212 default: 1212 default:
1213 fd_log_debug("??? (ERROR unknown type %d)", type); 1213 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "??? (ERROR unknown type %d)", type), return NULL);
1214 } 1214 }
1215 } 1215 return *buf;
1216 static void dump_avp_data ( void * data ) 1216 }
1217 static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_data, void * data )
1217 { 1218 {
1218 struct dict_avp_data * avp = (struct dict_avp_data * ) data; 1219 struct dict_avp_data * avp = (struct dict_avp_data * ) data;
1219 fd_log_debug("data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"", 1220 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"",
1220 DUMP_AVPFL_val(avp->avp_flag_val), 1221 DUMP_AVPFL_val(avp->avp_flag_val),
1221 DUMP_AVPFL_val(avp->avp_flag_mask), 1222 DUMP_AVPFL_val(avp->avp_flag_mask),
1222 type_base_name[avp->avp_basetype], 1223 type_base_name[avp->avp_basetype],
1223 avp->avp_code, 1224 avp->avp_code,
1224 avp->avp_name ); 1225 avp->avp_name );
1225 } 1226 }
1226 static void dump_command_data ( void * data ) 1227 static DECLARE_FD_DUMP_PROTOTYPE(dump_command_data, void * data )
1227 { 1228 {
1228 struct dict_cmd_data * cmd = (struct dict_cmd_data *) data; 1229 struct dict_cmd_data * cmd = (struct dict_cmd_data *) data;
1229 fd_log_debug("data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", 1230 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"",
1230 DUMP_CMDFL_val(cmd->cmd_flag_val), DUMP_CMDFL_val(cmd->cmd_flag_mask), cmd->cmd_code, cmd->cmd_name); 1231 DUMP_CMDFL_val(cmd->cmd_flag_val), DUMP_CMDFL_val(cmd->cmd_flag_mask), cmd->cmd_code, cmd->cmd_name);
1231 } 1232 }
1232 static void dump_rule_data ( void * data ) 1233 static DECLARE_FD_DUMP_PROTOTYPE(dump_rule_data, void * data )
1233 { 1234 {
1234 struct dict_rule_data * rule = (struct dict_rule_data * )data; 1235 struct dict_rule_data * rule = (struct dict_rule_data * )data;
1235 fd_log_debug("data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"", 1236 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"",
1236 rule->rule_position, 1237 rule->rule_position,
1237 rule->rule_order, 1238 rule->rule_order,
1238 rule->rule_min, 1239 rule->rule_min,
1239 rule->rule_max, 1240 rule->rule_max,
1240 rule->rule_avp->data.avp.avp_name); 1241 rule->rule_avp->data.avp.avp_name);
1241 } 1242 }
1242 1243
1243 static void dump_object ( struct dict_object * obj, int parents, int depth, int indent ); 1244 static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent );
1244 1245
1245 static void dump_list ( struct fd_list * sentinel, int parents, int depth, int indent ) 1246 static DECLARE_FD_DUMP_PROTOTYPE(dump_list, struct fd_list * sentinel, int parents, int depth, int indent )
1246 { 1247 {
1247 struct fd_list * li = sentinel; 1248 struct fd_list * li = sentinel;
1248 /* We don't lock here, the caller must have taken the dictionary lock for reading already */ 1249 /* We don't lock here, the caller must have taken the dictionary lock for reading already */
1249 while (li->next != sentinel) 1250 while (li->next != sentinel)
1250 { 1251 {
1251 li = li->next; 1252 li = li->next;
1252 dump_object( _O(li->o), parents, depth, indent ); 1253 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, _O(li->o), parents, depth, indent ), return NULL);
1253 } 1254 }
1254 } 1255 }
1255 1256
1256 static void dump_object ( struct dict_object * obj, int parents, int depth, int indent ) 1257 static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent )
1257 { 1258 {
1258 if (obj == NULL) 1259 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{dictobj}(@%p): ", indent, "", obj), return NULL);
1259 return; 1260
1260 1261 if (!verify_object(obj)) {
1261 if (parents) 1262 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL\n"), return NULL);
1262 dump_object (obj->parent, parents-1, 0, indent + 1 ); 1263 return *buf;
1263 1264 }
1264 fd_log_debug("%*s@%p: %s%s (p:%-9p) ", 1265
1265 indent, 1266 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s p:%p ",
1266 "", 1267 _OBINFO(obj).name,
1267 obj, 1268 obj->parent), return NULL);
1268 verify_object(obj) ? "" : "INVALID ", 1269
1269 _OBINFO(obj).name, 1270 if (obj->type == DICT_ENUMVAL) {
1270 obj->parent); 1271 CHECK_MALLOC_DO( dump_enumval_data ( FD_DUMP_STD_PARAMS, &obj->data.enumval, obj->parent->data.type.type_base ), return NULL);
1271 1272 } else {
1272 if (obj->type == DICT_ENUMVAL) 1273 CHECK_MALLOC_DO( _OBINFO(obj).dump_data(FD_DUMP_STD_PARAMS, &obj->data), return NULL);
1273 dump_enumval_data ( &obj->data.enumval, obj->parent->data.type.type_base ); 1274 }
1274 else 1275
1275 _OBINFO(obj).dump_data(&obj->data); 1276 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL);
1277
1278 if (parents) {
1279 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*sparent:", indent + 1, ""), return NULL);
1280 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, obj->parent, parents-1, 0, 0 ), return NULL);
1281 }
1276 1282
1277 if (depth) { 1283 if (depth) {
1278 int i; 1284 int i;
1279 for (i=0; i<NB_LISTS_PER_OBJ; i++) { 1285 for (i=0; i<NB_LISTS_PER_OBJ; i++) {
1280 if ((obj->list[i].o == NULL) && (obj->list[i].next != &obj->list[i])) { 1286 if ((obj->list[i].o == NULL) && (obj->list[i].next != &obj->list[i])) {
1281 fd_log_debug("%*s>%p: list[%d]:", indent, "", obj, i); 1287 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*slist[%d]:\n", indent + 1, "", i), return NULL);
1282 dump_list(&obj->list[i], parents, depth - 1, indent + 2); 1288 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &obj->list[i], 0, depth - 1, indent + 2), return NULL);
1283 } 1289 }
1284 } 1290 }
1285 } 1291 }
1286 } 1292
1287 1293 return *buf;
1288 void fd_dict_dump_object(struct dict_object * obj) 1294 }
1289 { 1295
1290 fd_log_debug("Dictionary object %p dump:", obj); 1296 DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_object, struct dict_object * obj)
1291 dump_object( obj, 1, 2, 2 ); 1297 {
1292 } 1298 size_t o = 0;
1293 1299
1294 void fd_dict_dump(struct dictionary * dict) 1300 if (!offset)
1301 offset = &o;
1302
1303 CHECK_MALLOC_DO( dump_object(FD_DUMP_STD_PARAMS, obj, 1, 2, 0), return NULL);
1304
1305 return *buf;
1306 }
1307
1308 DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump, struct dictionary * dict)
1295 { 1309 {
1296 int i; 1310 int i;
1297 struct fd_list * li; 1311 struct fd_list * li;
1298 1312 size_t o = 0;
1299 CHECK_PARAMS_DO(dict && (dict->dict_eyec == DICT_EYECATCHER), return); 1313
1314 if (!offset)
1315 offset = &o;
1316
1317 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{dictionary}(@%p): ", dict), return NULL);
1318
1319 if ((dict == NULL) || (dict->dict_eyec != DICT_EYECATCHER)) {
1320 return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL\n");
1321 }
1300 1322
1301 CHECK_POSIX_DO( pthread_rwlock_rdlock( &dict->dict_lock ), /* ignore */ ); 1323 CHECK_POSIX_DO( pthread_rwlock_rdlock( &dict->dict_lock ), /* ignore */ );
1302 1324
1303 fd_log_debug("######################################################"); 1325 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict:%p > vendors, AVPs and related rules}\n", dict), goto error);
1304 fd_log_debug("###### Dumping vendors, AVPs and related rules #######"); 1326 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_vendors, 0, 3, 3 ), goto error);
1305
1306 dump_object( &dict->dict_vendors, 0, 3, 0 );
1307 for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) 1327 for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next)
1308 dump_object( li->o, 0, 3, 0 ); 1328 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 3, 3 ), goto error);
1309 1329
1310 fd_log_debug("###### Dumping applications #######"); 1330 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {dict:%p > applications}\n", dict), goto error);
1311 1331 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_applications, 0, 1, 3 ), goto error);
1312 dump_object( &dict->dict_applications, 0, 1, 0 );
1313 for (li = dict->dict_applications.list[0].next; li != &dict->dict_applications.list[0]; li = li->next) 1332 for (li = dict->dict_applications.list[0].next; li != &dict->dict_applications.list[0]; li = li->next)
1314 dump_object( li->o, 0, 1, 0 ); 1333 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 1, 3 ), goto error);
1315 1334
1316 fd_log_debug("###### Dumping types #######"); 1335 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {dict:%p > types}\n", dict), goto error);
1317 1336 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_types, 0, 2, 3 ), goto error);
1318 dump_list( &dict->dict_types, 0, 2, 0 ); 1337
1319 1338 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {dict:%p > commands}\n", dict), goto error);
1320 fd_log_debug("###### Dumping commands per name #######"); 1339 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_cmd_code, 0, 0, 3 ), goto error);
1321 1340
1322 dump_list( &dict->dict_cmd_name, 0, 2, 0 ); 1341 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {dict:%p > statistics}\n", dict), goto error);
1323
1324 fd_log_debug("###### Dumping commands per code and flags #######");
1325
1326 dump_list( &dict->dict_cmd_code, 0, 0, 0 );
1327
1328 fd_log_debug("###### Statistics #######");
1329
1330 for (i=1; i<=DICT_TYPE_MAX; i++) 1342 for (i=1; i<=DICT_TYPE_MAX; i++)
1331 fd_log_debug(" %5d objects of type %s", dict->dict_count[i], dict_obj_info[i].name); 1343 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " %5d: %s\n", dict->dict_count[i], dict_obj_info[i].name), goto error);
1332 1344
1333 fd_log_debug("######################################################"); 1345 CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ );
1334 1346 return *buf;
1347 error:
1335 /* Free the rwlock */ 1348 /* Free the rwlock */
1336 CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ ); 1349 CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ );
1350 return NULL;
1337 } 1351 }
1338 1352
1339 /**************************** Dump AVP values ********************************/ 1353 /**************************** Dump AVP values ********************************/
1340 1354
1341 /* Default dump functions */ 1355 /* Default dump functions */
1342 static int dump_val_os(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) 1356 static DECLARE_FD_DUMP_PROTOTYPE(dump_val_os, union avp_value * value)
1343 { 1357 {
1344 int i; 1358 int i;
1345 CHECK_FCT( dump_add_str(outstr, offset, outlen, "<") ); 1359
1360 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<"), return NULL);
1346 for (i = 0; i < value->os.len; i++) { 1361 for (i = 0; i < value->os.len; i++) {
1347 if (i == 1024) { /* Dump only up to 1024 bytes of the buffer */ 1362 if (i == 1024) { /* Dump only up to 1024 bytes of the buffer */
1348 CHECK_FCT( dump_add_str(outstr, offset, outlen, "[...] (len=%zd)", value->os.len) ); 1363 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "[...] (len=%zd)", value->os.len), return NULL);
1349 break; 1364 break;
1350 } 1365 }
1351 CHECK_FCT( dump_add_str(outstr, offset, outlen, "%s%02.2X", (i==0 ? "" : " "), value->os.data[i]) ); 1366 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s%02hhX", (i==0 ? "" : " "), value->os.data[i]), return NULL);
1352 } 1367 }
1353 CHECK_FCT( dump_add_str(outstr, offset, outlen, ">") ); 1368 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ">"), return NULL);
1354 return 0; 1369 return *buf;
1355 } 1370 }
1356 1371
1357 static int dump_val_i32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) 1372 static DECLARE_FD_DUMP_PROTOTYPE(dump_val_i32, union avp_value * value)
1358 { 1373 {
1359 CHECK_FCT( dump_add_str(outstr, offset, outlen, "%i (0x%x)", value->i32, value->i32) ); 1374 return fd_dump_extend( FD_DUMP_STD_PARAMS, "%i (0x%x)", value->i32, value->i32);
1360 return 0; 1375 }
1361 } 1376
1362 1377 static DECLARE_FD_DUMP_PROTOTYPE(dump_val_i64, union avp_value * value)
1363 static int dump_val_i64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) 1378 {
1364 { 1379 return fd_dump_extend( FD_DUMP_STD_PARAMS, "%" PRId64 " (0x%" PRIx64 ")", value->i64, value->i64);
1365 CHECK_FCT( dump_add_str(outstr, offset, outlen, "%lli (0x%llx)", value->i64, value->i64) ); 1380 }
1366 return 0; 1381
1367 } 1382 static DECLARE_FD_DUMP_PROTOTYPE(dump_val_u32, union avp_value * value)
1368 1383 {
1369 static int dump_val_u32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) 1384 return fd_dump_extend( FD_DUMP_STD_PARAMS, "%u (0x%x)", value->u32, value->u32);
1370 { 1385 }
1371 CHECK_FCT( dump_add_str(outstr, offset, outlen, "%u (0x%x)", value->u32, value->u32) ); 1386
1372 return 0; 1387 static DECLARE_FD_DUMP_PROTOTYPE(dump_val_u64, union avp_value * value)
1373 } 1388 {
1374 1389 return fd_dump_extend( FD_DUMP_STD_PARAMS, "%" PRIu64 " (0x%" PRIx64 ")", value->u64, value->u64);
1375 static int dump_val_u64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) 1390 }
1376 { 1391
1377 CHECK_FCT( dump_add_str(outstr, offset, outlen, "%llu (0x%llx)", value->u64, value->u64) ); 1392 static DECLARE_FD_DUMP_PROTOTYPE(dump_val_f32, union avp_value * value)
1378 return 0; 1393 {
1379 } 1394 return fd_dump_extend( FD_DUMP_STD_PARAMS, "%f", value->f32);
1380 1395 }
1381 static int dump_val_f32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) 1396
1382 { 1397 static DECLARE_FD_DUMP_PROTOTYPE(dump_val_f64, union avp_value * value)
1383 CHECK_FCT( dump_add_str(outstr, offset, outlen, "%f", value->f32) ); 1398 {
1384 return 0; 1399 return fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", value->f64);
1385 }
1386
1387 static int dump_val_f64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
1388 {
1389 CHECK_FCT( dump_add_str(outstr, offset, outlen, "%g", value->f64) );
1390 return 0;
1391 } 1400 }
1392 1401
1393 /* Get the dump function for basic dict_avp_basetype */ 1402 /* Get the dump function for basic dict_avp_basetype */
1394 static int (*get_default_dump_val_cb(enum dict_avp_basetype datatype))(union avp_value *, char **, size_t *, size_t *) 1403 static DECLARE_FD_DUMP_PROTOTYPE((*get_default_dump_val_cb(enum dict_avp_basetype datatype)), union avp_value *)
1395 { 1404 {
1396 switch (datatype) { 1405 switch (datatype) {
1397 case AVP_TYPE_OCTETSTRING: 1406 case AVP_TYPE_OCTETSTRING:
1398 return &dump_val_os; 1407 return &dump_val_os;
1399 1408
1423 1432
1424 /* indent inside an object (duplicate from messages.c) */ 1433 /* indent inside an object (duplicate from messages.c) */
1425 #define INOBJHDR "%*s " 1434 #define INOBJHDR "%*s "
1426 #define INOBJHDRVAL indent<0 ? 1 : indent, indent<0 ? "-" : "|" 1435 #define INOBJHDRVAL indent<0 ? 1 : indent, indent<0 ? "-" : "|"
1427 1436
1437 typedef DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb_t), union avp_value *);
1438
1428 /* Formatter for the AVP value dump line */ 1439 /* Formatter for the AVP value dump line */
1429 static int dump_avp_val(union avp_value *avp_value, 1440 static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_val, union avp_value *avp_value,
1430 int (*def_dump_val_cb)(union avp_value *, char **, size_t *, size_t *), 1441 dump_val_cb_t def_dump_val_cb,
1431 char * (*dump_val_cb)(union avp_value *), 1442 dump_val_cb_t dump_val_cb,
1432 enum dict_avp_basetype datatype, 1443 enum dict_avp_basetype datatype,
1433 char * type_name, 1444 char * type_name,
1434 char * const_name, 1445 char * const_name,
1435 int indent, 1446 int indent,
1436 char **outstr,
1437 size_t *offset,
1438 size_t *outlen,
1439 int header) 1447 int header)
1440 { 1448 {
1441 if (header) { 1449 if (header) {
1442 /* Header for all AVP values dumps: */ 1450 /* Header for all AVP values dumps: */
1443 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "value ", INOBJHDRVAL) ); 1451 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, INOBJHDR "value ", INOBJHDRVAL), return NULL);
1444 1452
1445 /* If the type is provided, write it */ 1453 /* If the type is provided, write it */
1446 if (type_name) { 1454 if (type_name) {
1447 CHECK_FCT( dump_add_str(outstr, offset, outlen, "t: '%s' ", type_name) ); 1455 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "t: '%s' ", type_name), return NULL);
1448 } 1456 }
1449 1457
1450 /* Always give the base datatype anyway */ 1458 /* Always give the base datatype anyway */
1451 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(%s) ", type_base_name[datatype]) ); 1459 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(%s) ", type_base_name[datatype]), return NULL);
1452 1460
1453 /* Now, the value */ 1461 /* Now, the value */
1454 CHECK_FCT( dump_add_str(outstr, offset, outlen, "v: ") ); 1462 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "v: "), return NULL);
1455 } 1463 }
1456 if (const_name) { 1464 if (const_name) {
1457 CHECK_FCT( dump_add_str(outstr, offset, outlen, "'%s' (", const_name) ); 1465 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s' (", const_name), return NULL);
1458 } 1466 }
1459 if (dump_val_cb) { 1467 if (dump_val_cb) {
1460 char * str; 1468 CHECK_MALLOC_DO( (*dump_val_cb)( FD_DUMP_STD_PARAMS, avp_value), fd_dump_extend( FD_DUMP_STD_PARAMS, "(dump failed)"));
1461 CHECK_MALLOC_DO( str = (*dump_val_cb)(avp_value), dump_add_str(outstr, offset, outlen, "(dump failed)") );
1462 CHECK_FCT( dump_add_str(outstr, offset, outlen, "%s", str) );
1463 free(str);
1464 } else { 1469 } else {
1465 CHECK_FCT( (*def_dump_val_cb)(avp_value, outstr, offset, outlen) ); 1470 CHECK_MALLOC_DO( (*def_dump_val_cb)( FD_DUMP_STD_PARAMS, avp_value), return NULL);
1466 } 1471 }
1467 if (const_name) { 1472 if (const_name) {
1468 CHECK_FCT( dump_add_str(outstr, offset, outlen, ")") ); 1473 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ")"), return NULL);
1469 } 1474 }
1470 1475
1471 /* Done! */ 1476 /* Done! */
1472 return 0; 1477 return *buf;
1473 } 1478 }
1474 1479
1475 /* Dump the value of an AVP of known type into the returned str */ 1480 /* Dump the value of an AVP of known type into the returned str */
1476 int fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, char **outstr, size_t *offset, size_t *outlen, int header) 1481 DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_avp_value, union avp_value *avp_value, struct dict_object * model, int indent, int header)
1477 { 1482 {
1478 char * (*dump_val_cb)(union avp_value *avp_value) = NULL; 1483 DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb), union avp_value *avp_value) = NULL;
1479 struct dict_object * type = NULL; 1484 struct dict_object * type = NULL;
1480 char * type_name = NULL; 1485 char * type_name = NULL;
1481 char * const_name = NULL; 1486 char * const_name = NULL;
1487 size_t o = 0;
1488
1489 if (!offset)
1490 offset = &o;
1482 1491
1483 /* Check the parameters are correct */ 1492 /* Check the parameters are correct */
1484 CHECK_PARAMS( avp_value && verify_object(model) && (model->type == DICT_AVP) ); 1493 CHECK_PARAMS_DO( avp_value && verify_object(model) && (model->type == DICT_AVP), return NULL );
1485 1494
1486 /* Get the type definition of this AVP */ 1495 /* Get the type definition of this AVP */
1487 type = model->parent; 1496 type = model->parent;
1488 if (type) { 1497 if (type) {
1489 struct dict_enumval_request request; 1498 struct dict_enumval_request request;
1499 memset(&request, 0, sizeof(request)); 1508 memset(&request, 0, sizeof(request));
1500 request.type_obj = type; 1509 request.type_obj = type;
1501 memcpy(&request.search.enum_value, avp_value, sizeof(union avp_value)); 1510 memcpy(&request.search.enum_value, avp_value, sizeof(union avp_value));
1502 /* bypass checks */ 1511 /* bypass checks */
1503 if ((search_enumval( type->dico, ENUMVAL_BY_STRUCT, &request, &enumval ) == 0) && (enumval)) { 1512 if ((search_enumval( type->dico, ENUMVAL_BY_STRUCT, &request, &enumval ) == 0) && (enumval)) {
1504 /* We found a cosntant, get its name */ 1513 /* We found a constant, get its name */
1505 const_name = enumval->data.enumval.enum_name; 1514 const_name = enumval->data.enumval.enum_name;
1506 } 1515 }
1507 } 1516 }
1508 1517
1509 /* And finally, dump the value */ 1518 /* And finally, dump the value */
1510 CHECK_FCT( dump_avp_val(avp_value, get_default_dump_val_cb(model->data.avp.avp_basetype), dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent, outstr, offset, outlen, header) ); 1519 CHECK_MALLOC_DO( dump_avp_val(FD_DUMP_STD_PARAMS, avp_value, get_default_dump_val_cb(model->data.avp.avp_basetype), dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent, header), return NULL );
1511 return 0; 1520 return *buf;
1512 } 1521 }
1513 1522
1514 /*******************************************************************************************************/ 1523 /*******************************************************************************************************/
1515 /*******************************************************************************************************/ 1524 /*******************************************************************************************************/
1516 /* */ 1525 /* */
1571 CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) && data ); 1580 CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) && data );
1572 1581
1573 /* Check the "parent" parameter */ 1582 /* Check the "parent" parameter */
1574 switch (dict_obj_info[type].parent) { 1583 switch (dict_obj_info[type].parent) {
1575 case 0: /* parent is forbidden */ 1584 case 0: /* parent is forbidden */
1576 CHECK_PARAMS( parent == NULL ); 1585 CHECK_PARAMS_DO( parent == NULL, goto error_param );
1577 1586
1578 case 1: /* parent is optional */ 1587 case 1: /* parent is optional */
1579 if (parent == NULL) 1588 if (parent == NULL)
1580 break; 1589 break;
1581 1590
1582 case 2: /* parent is mandatory */ 1591 case 2: /* parent is mandatory */
1583 CHECK_PARAMS( verify_object(parent) ); 1592 CHECK_PARAMS_DO( verify_object(parent), goto error_param );
1584 1593
1585 if (type == DICT_RULE ) { /* Special case : grouped AVP or Command parents are allowed */ 1594 if (type == DICT_RULE ) { /* Special case : grouped AVP or Command parents are allowed */
1586 CHECK_PARAMS( (parent->type == DICT_COMMAND ) 1595 CHECK_PARAMS_DO( (parent->type == DICT_COMMAND )
1587 || ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ) ); 1596 || ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ), goto error_param );
1588 } else { 1597 } else {
1589 CHECK_PARAMS( parent->type == dict_obj_info[type].parenttype ); 1598 CHECK_PARAMS_DO( parent->type == dict_obj_info[type].parenttype, goto error_param );
1590 } 1599 }
1591 } 1600 }
1592 1601
1593 /* For AVP object, we must also check that the "vendor" referenced exists */ 1602 /* For AVP object, we must also check that the "vendor" referenced exists */
1594 if (type == DICT_AVP) { 1603 if (type == DICT_AVP) {
1595 CHECK_FCT_DO( fd_dict_search( dict, DICT_VENDOR, VENDOR_BY_ID, &(((struct dict_avp_data *)data)->avp_vendor), (void*)&vendor, ENOENT ), 1604 CHECK_FCT_DO( fd_dict_search( dict, DICT_VENDOR, VENDOR_BY_ID, &(((struct dict_avp_data *)data)->avp_vendor), (void*)&vendor, ENOENT ),
1596 { TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); return EINVAL; } ); 1605 { TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); goto error_param; } );
1597 1606
1598 /* Also check if a parent is provided, that the type are the same */ 1607 /* Also check if a parent is provided, that the type are the same */
1599 if (parent) { 1608 if (parent) {
1600 CHECK_PARAMS( parent->data.type.type_base == ((struct dict_avp_data *)data)->avp_basetype ); 1609 CHECK_PARAMS_DO( parent->data.type.type_base == ((struct dict_avp_data *)data)->avp_basetype, goto error_param );
1601 } 1610 }
1602 } 1611 }
1603 1612
1604 /* For RULE object, we must also check that the "avp" referenced exists */ 1613 /* For RULE object, we must also check that the "avp" referenced exists */
1605 if (type == DICT_RULE) { 1614 if (type == DICT_RULE) {
1606 CHECK_PARAMS( verify_object(((struct dict_rule_data *)data)->rule_avp) ); 1615 CHECK_PARAMS_DO( verify_object(((struct dict_rule_data *)data)->rule_avp), goto error_param );
1607 CHECK_PARAMS( ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP ); 1616 CHECK_PARAMS_DO( ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP, goto error_param );
1608 } 1617 }
1609 1618
1610 /* For COMMAND object, check that the 'R' flag is fixed */ 1619 /* For COMMAND object, check that the 'R' flag is fixed */
1611 if (type == DICT_COMMAND) { 1620 if (type == DICT_COMMAND) {
1612 CHECK_PARAMS( ((struct dict_cmd_data *)data)->cmd_flag_mask & CMD_FLAG_REQUEST ); 1621 CHECK_PARAMS_DO( ((struct dict_cmd_data *)data)->cmd_flag_mask & CMD_FLAG_REQUEST, goto error_param );
1613 } 1622 }
1614 1623
1615 /* We have to check that the new values are not equal to the sentinels */ 1624 /* We have to check that the new values are not equal to the sentinels */
1616 if (type == DICT_VENDOR) { 1625 if (type == DICT_VENDOR) {
1617 CHECK_PARAMS( ((struct dict_vendor_data *)data)->vendor_id != 0 ); 1626 CHECK_PARAMS_DO( ((struct dict_vendor_data *)data)->vendor_id != 0, goto error_param );
1618 } 1627 }
1619 if (type == DICT_APPLICATION) { 1628 if (type == DICT_APPLICATION) {
1620 CHECK_PARAMS( ((struct dict_application_data *)data)->application_id != 0 ); 1629 CHECK_PARAMS_DO( ((struct dict_application_data *)data)->application_id != 0, goto error_param );
1621 } 1630 }
1622 1631
1623 /* Parameters are valid, create the new object */ 1632 /* Parameters are valid, create the new object */
1624 CHECK_MALLOC( new = malloc(sizeof(struct dict_object)) ); 1633 CHECK_MALLOC( new = malloc(sizeof(struct dict_object)) );
1625 1634
1715 if (ref) 1724 if (ref)
1716 *ref = new; 1725 *ref = new;
1717 1726
1718 return 0; 1727 return 0;
1719 1728
1729 error_param:
1730 ret = EINVAL;
1731 goto all_errors;
1732
1720 error_unlock: 1733 error_unlock:
1721 CHECK_POSIX_DO( pthread_rwlock_unlock(&dict->dict_lock), /* continue */ ); 1734 CHECK_POSIX_DO( pthread_rwlock_unlock(&dict->dict_lock), /* continue */ );
1722 if (ret == EEXIST) { 1735 if (ret == EEXIST) {
1723 /* We have a duplicate key in locref. Check if the pointed object is the same or not */ 1736 /* We have a duplicate key in locref. Check if the pointed object is the same or not */
1724 switch (type) { 1737 switch (type) {
1725 case DICT_VENDOR: 1738 case DICT_VENDOR:
1726 TRACE_DEBUG(FULL, "Vendor %s already in dictionary", new->data.vendor.vendor_name); 1739 TRACE_DEBUG(FULL, "Vendor %s already in dictionary", new->data.vendor.vendor_name);
1727 /* if we are here, it means the two vendors id are identical */ 1740 /* if we are here, it means the two vendors id are identical */
1728 if (fd_os_cmp(locref->data.vendor.vendor_name, locref->datastr_len, 1741 if (fd_os_cmp(locref->data.vendor.vendor_name, locref->datastr_len,
1729 new->data.vendor.vendor_name, new->datastr_len)) { 1742 new->data.vendor.vendor_name, new->datastr_len)) {
1730 TRACE_DEBUG(FULL, "Conflicting vendor name"); 1743 TRACE_DEBUG(INFO, "Conflicting vendor name: %s", new->data.vendor.vendor_name);
1731 break; 1744 break;
1732 } 1745 }
1733 /* Otherwise (same name), we consider the function succeeded, since the (same) object is in the dictionary */ 1746 /* Otherwise (same name), we consider the function succeeded, since the (same) object is in the dictionary */
1734 ret = 0; 1747 ret = 0;
1735 break; 1748 break;
1863 break; 1876 break;
1864 } 1877 }
1865 ret = 0; 1878 ret = 0;
1866 break; 1879 break;
1867 } 1880 }
1868 if (ret) { 1881 if (!ret) {
1869 TRACE_DEBUG(INFO, "An existing object with different non-key data was found: EEXIST");
1870 if (TRACE_BOOL(INFO)) {
1871 fd_log_debug("New object to insert:");
1872 dump_object(new, 0, 0, 3);
1873 fd_log_debug("Object already in dictionary:");
1874 dump_object(locref, 0, 0 , 3);
1875 }
1876 } else {
1877 TRACE_DEBUG(FULL, "An existing object with the same data was found, ignoring the error..."); 1882 TRACE_DEBUG(FULL, "An existing object with the same data was found, ignoring the error...");
1878 } 1883 }
1879 if (ref) 1884 if (ref)
1880 *ref = locref; 1885 *ref = locref;
1881 } else { 1886 }
1882 CHECK_FCT_DO( ret, ); /* log the error */ 1887 all_errors:
1883 } 1888 if (ret != 0) {
1884 1889 char * buf = NULL;
1890 size_t len = 0;
1891
1892 CHECK_MALLOC( dict_obj_info[CHECK_TYPE(type) ? type : 0].dump_data(&buf, &len, NULL, data) );
1893 TRACE_DEBUG(INFO, "An error occurred while adding the following data in the dictionary: %s", buf);
1894
1895 if (ret == EEXIST) {
1896 CHECK_MALLOC( dump_object(&buf, &len, NULL, locref, 0, 0, 0) );
1897 TRACE_DEBUG(INFO, "Conflicting entry in the dictionary: %s", buf);
1898 }
1899 free(buf);
1900 }
1885 error_free: 1901 error_free:
1886 free(new); 1902 free(new);
1887 return ret; 1903 return ret;
1888 } 1904 }
1889 1905
"Welcome to our mercurial repository"