Changeset 1451:6c3485887511 in freeDiameter for libfdproto/dictionary.c
- Timestamp:
- Feb 27, 2020, 11:40:25 PM (4 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libfdproto/dictionary.c
r1444 r1451 35 35 36 36 #include "fdproto-internal.h" 37 #include "dictionary-internal.h" 37 38 #include <inttypes.h> 38 39 … … 49 50 }; 50 51 51 /* The number of lists in an object */52 #define NB_LISTS_PER_OBJ 353 54 52 /* Some eye catchers definitions */ 55 53 #define OBJECT_EYECATCHER (0x0b13c7) 56 54 #define DICT_EYECATCHER (0x00d1c7) 57 58 /* Definition of the dictionary objects */59 struct dict_object {60 enum dict_object_type type; /* What type of object is this? */61 int objeyec;/* eyecatcher for this object */62 int typeyec;/* eyecatcher for this type of object */63 struct dictionary *dico; /* The dictionary this object belongs to */64 65 union {66 struct dict_vendor_data vendor; /* datastr_len = strlen(vendor_name) */67 struct dict_application_data application; /* datastr_len = strlen(application_name) */68 struct dict_type_data type; /* datastr_len = strlen(type_name) */69 struct dict_enumval_data enumval; /* datastr_len = strlen(enum_name) */70 struct dict_avp_data avp; /* datastr_len = strlen(avp_name) */71 struct dict_cmd_data cmd; /* datastr_len = strlen(cmd_name) */72 struct dict_rule_data rule; /* datastr_len = 0 */73 } data; /* The data of this object */74 75 size_t datastr_len; /* cached length of the string inside the data. Saved when the object is created. */76 77 struct dict_object * parent; /* The parent of this object, if any */78 79 struct fd_list list[NB_LISTS_PER_OBJ];/* used to chain objects.*/80 /* More information about the lists :81 82 - the use for each list depends on the type of object. See detail below.83 84 - a sentinel for a list has its 'o' field cleared. (this is the criteria to detect end of a loop)85 86 - The lists are always ordered. The criteria are described below. the functions to order them are referenced in dict_obj_info87 88 - The dict_lock must be held for any list operation.89 90 => VENDORS:91 list[0]: list of the vendors, ordered by their id. The sentinel is g_dict_vendors (vendor with id 0)92 list[1]: sentinel for the list of AVPs from this vendor, ordered by AVP code.93 list[2]: sentinel for the list of AVPs from this vendor, ordered by AVP name (fd_os_cmp).94 95 => APPLICATIONS:96 list[0]: list of the applications, ordered by their id. The sentinel is g_dict_applications (application with id 0)97 list[1]: not used98 list[2]: not used.99 100 => TYPES:101 list[0]: list of the types, ordered by their names. The sentinel is g_list_types.102 list[1]: sentinel for the type_enum list of this type, ordered by their constant name (fd_os_cmp).103 list[2]: sentinel for the type_enum list of this type, ordered by their constant value.104 105 => TYPE_ENUMS:106 list[0]: list of the contants for a given type, ordered by the constant name (fd_os_cmp). Sentinel is a (list[1]) element of a TYPE object.107 list[1]: list of the contants for a given type, ordered by the constant value. Sentinel is a (list[2]) element of a TYPE object.108 list[2]: not used109 110 => AVPS:111 list[0]: list of the AVP from a given vendor, ordered by avp code. Sentinel is a list[1] element of a VENDOR object.112 list[1]: list of the AVP from a given vendor, ordered by avp name (fd_os_cmp). Sentinel is a list[2] element of a VENDOR object.113 list[2]: sentinel for the rule list that apply to this AVP.114 115 => COMMANDS:116 list[0]: list of the commands, ordered by their names (fd_os_cmp). The sentinel is g_list_cmd_name.117 list[1]: list of the commands, ordered by their command code and 'R' flag. The sentinel is g_list_cmd_code.118 list[2]: sentinel for the rule list that apply to this command.119 120 => RULES:121 list[0]: list of the rules for a given (grouped) AVP or Command, ordered by the AVP vendor & code to which they refer. sentinel is list[2] of a command or (grouped) avp.122 list[1]: not used123 list[2]: not used.124 125 */126 127 /* Sentinel for the dispatch callbacks */128 struct fd_list disp_cbs;129 130 };131 132 /* Definition of the dictionary structure */133 struct dictionary {134 int dict_eyec; /* Eye-catcher for the dictionary (DICT_EYECATCHER) */135 136 pthread_rwlock_t dict_lock; /* The global rwlock for the dictionary */137 138 struct dict_object dict_vendors; /* Sentinel for the list of vendors, corresponding to vendor 0 */139 struct dict_object dict_applications; /* Sentinel for the list of applications, corresponding to app 0 */140 struct fd_list dict_types; /* Sentinel for the list of types */141 struct fd_list dict_cmd_name; /* Sentinel for the list of commands, ordered by names */142 struct fd_list dict_cmd_code; /* Sentinel for the list of commands, ordered by codes */143 144 struct dict_object dict_cmd_error; /* Special command object for answers with the 'E' bit set */145 146 int dict_count[DICT_TYPE_MAX + 1]; /* Number of objects of each type */147 };148 55 149 56 /* Forward declarations of dump functions */ … … 178 85 } dict_obj_info[] = { { 0, "(error)", 0, 0, 0, 0, NULL, NULL, {0, 0, 0} } 179 86 180 /* type name datasize parent parenttype 87 /* type name datasize parent parenttype 181 88 eyecatcher dump_data search_fct, haslist[] */ 182 89 183 90 ,{ DICT_VENDOR, "VENDOR", sizeof(struct dict_vendor_data), 0, 0, 184 91 OBJECT_EYECATCHER + 1, dump_vendor_data, search_vendor, { 1, 0, 0 } } 185 92 186 93 ,{ DICT_APPLICATION, "APPLICATION", sizeof(struct dict_application_data), 1, DICT_VENDOR, 187 94 OBJECT_EYECATCHER + 2, dump_application_data, search_application, { 1, 0, 0 } } 188 95 189 96 ,{ DICT_TYPE, "TYPE", sizeof(struct dict_type_data), 1, DICT_APPLICATION, 190 97 OBJECT_EYECATCHER + 3, dump_type_data, search_type, { 1, 0, 0 } } 191 98 192 99 ,{ DICT_ENUMVAL, "ENUMVAL", sizeof(struct dict_enumval_data), 2, DICT_TYPE, 193 100 OBJECT_EYECATCHER + 4, NULL, search_enumval, { 1, 1, 0 } } 194 101 195 102 ,{ DICT_AVP, "AVP", sizeof(struct dict_avp_data), 1, DICT_TYPE, 196 103 OBJECT_EYECATCHER + 5, dump_avp_data, search_avp, { 1, 1, 0 } } 197 104 198 105 ,{ DICT_COMMAND, "COMMAND", sizeof(struct dict_cmd_data), 1, DICT_APPLICATION, 199 106 OBJECT_EYECATCHER + 6, dump_command_data, search_cmd, { 1, 1, 0 } } 200 107 201 108 ,{ DICT_RULE, "RULE", sizeof(struct dict_rule_data), 2, -1 /* special case: grouped avp or command */, 202 109 OBJECT_EYECATCHER + 7, dump_rule_data, search_rule, { 1, 0, 0 } } 203 110 204 111 }; 205 112 206 113 /* Macro to verify a "type" value */ 207 114 #define CHECK_TYPE( type ) ( ((type) > 0) && ((type) <= DICT_TYPE_MAX) ) … … 231 138 str = os0dup( str, *(plen)); \ 232 139 } 233 140 234 141 /* Initialize an object */ 235 142 static void init_object( struct dict_object * obj, enum dict_object_type type ) 236 143 { 237 144 int i; 238 145 239 146 TRACE_ENTRY("%p %d", obj, type); 240 147 241 148 /* Clean the object first */ 242 149 memset ( obj, 0, sizeof(struct dict_object)); 243 150 244 151 CHECK_PARAMS_DO( CHECK_TYPE(type), return ); 245 152 … … 249 156 250 157 /* We don't initialize the data nor the parent here */ 251 158 252 159 /* Now init the lists */ 253 160 for (i=0; i<NB_LISTS_PER_OBJ; i++) { 254 if (_OBINFO(obj).haslist[i] != 0) 161 if (_OBINFO(obj).haslist[i] != 0) 255 162 fd_list_init(&obj->list[i], obj); 256 163 else 257 164 fd_list_init(&obj->list[i], NULL); 258 165 } 259 166 260 167 fd_list_init(&obj->disp_cbs, NULL); 261 168 } … … 266 173 TRACE_ENTRY("%p %p %d", dest, source, type); 267 174 CHECK_PARAMS( dest && source && CHECK_TYPE(type) ); 268 269 /* Generic: copy the full data structure */ 175 176 /* Generic: copy the full data structure */ 270 177 memcpy( &dest->data, source, dict_obj_info[type].datasize ); 271 178 272 179 /* Then strings must be duplicated, not copied */ 273 180 /* This function might be simplified by always defining the "name" field as the first field of the structures, but... it's error-prone */ … … 276 183 DUP_string_len( dest->data.vendor.vendor_name, &dest->datastr_len ); 277 184 break; 278 185 279 186 case DICT_APPLICATION: 280 187 DUP_string_len( dest->data.application.application_name, &dest->datastr_len ); 281 188 break; 282 189 283 190 case DICT_TYPE: 284 191 DUP_string_len( dest->data.type.type_name, &dest->datastr_len ); 285 192 break; 286 193 287 194 case DICT_ENUMVAL: 288 195 DUP_string_len( dest->data.enumval.enum_name, &dest->datastr_len ); 289 196 if (dupos) { 290 197 // we also need to duplicate the octetstring constant value since it is a pointer. 291 dest->data.enumval.enum_value.os.data = os0dup( 292 ((struct dict_enumval_data *)source)->enum_value.os.data, 198 dest->data.enumval.enum_value.os.data = os0dup( 199 ((struct dict_enumval_data *)source)->enum_value.os.data, 293 200 ((struct dict_enumval_data *)source)->enum_value.os.len 294 201 ); … … 299 206 DUP_string_len( dest->data.avp.avp_name, &dest->datastr_len ); 300 207 break; 301 208 302 209 case DICT_COMMAND: 303 210 DUP_string_len( dest->data.cmd.cmd_name, &dest->datastr_len ); 304 211 break; 305 212 306 213 default: 307 214 /* Nothing to do for RULES */ 308 215 ; 309 216 } 310 217 311 218 return 0; 312 219 } … … 316 223 { 317 224 TRACE_ENTRY("%p", obj); 318 225 319 226 CHECK_PARAMS_DO( obj 320 227 && (obj->objeyec == OBJECT_EYECATCHER) … … 334 241 return 0; 335 242 } ); 336 243 337 244 /* The object is probably valid. */ 338 245 return 1; … … 343 250 { 344 251 /* TRACE_ENTRY("%p", obj); */ 345 252 346 253 switch (obj->type) { 347 254 case DICT_VENDOR: 348 255 free( obj->data.vendor.vendor_name ); 349 256 break; 350 257 351 258 case DICT_APPLICATION: 352 259 free( obj->data.application.application_name ); 353 260 break; 354 261 355 262 case DICT_TYPE: 356 263 free( obj->data.type.type_name ); 357 264 break; 358 265 359 266 case DICT_ENUMVAL: 360 267 free( obj->data.enumval.enum_name ); … … 364 271 free( obj->data.avp.avp_name ); 365 272 break; 366 273 367 274 case DICT_COMMAND: 368 275 free( obj->data.cmd.cmd_name ); 369 276 break; 370 277 371 278 default: 372 279 /* nothing to do */ … … 379 286 380 287 /* Destroy all objects in a list - the lock must be held */ 381 static void destroy_list(struct fd_list * head) 288 static void destroy_list(struct fd_list * head) 382 289 { 383 290 /* TRACE_ENTRY("%p", head); */ 384 291 385 292 /* loop in the list */ 386 293 while (!FD_IS_LIST_EMPTY(head)) … … 390 297 } 391 298 } 392 299 393 300 /* Free an object and its sublists */ 394 301 static void destroy_object(struct dict_object * obj) 395 302 { 396 303 int i; 397 304 398 305 /* TRACE_ENTRY("%p", obj); */ 399 306 400 307 /* Update global count */ 401 if (obj->dico) 308 if (obj->dico) 402 309 obj->dico->dict_count[obj->type]--; 403 310 404 311 /* Mark the object as invalid */ 405 312 obj->objeyec = 0xdead; 406 313 407 314 /* First, destroy the data associated to the object */ 408 315 destroy_object_data(obj); 409 316 410 317 for (i=0; i<NB_LISTS_PER_OBJ; i++) { 411 318 if (_OBINFO(obj).haslist[i]) … … 416 323 destroy_list( &obj->list[i] ); 417 324 } 418 325 419 326 /* Unlink all elements from the dispatch list; they will be freed when callback is unregistered */ 420 327 CHECK_POSIX_DO( pthread_rwlock_wrlock(&fd_disp_lock), /* continue */ ); … … 423 330 } 424 331 CHECK_POSIX_DO( pthread_rwlock_unlock(&fd_disp_lock), /* continue */ ); 425 332 426 333 /* Last, destroy the object */ 427 334 free(obj); … … 438 345 /* Compare two values */ 439 346 #define ORDER_scalar( i1, i2 ) \ 440 ((i1 < i2 ) ? -1 : ( i1 > i2 ? 1 : 0 )) 347 ((i1 < i2 ) ? -1 : ( i1 > i2 ? 1 : 0 )) 441 348 442 349 … … 445 352 { 446 353 TRACE_ENTRY("%p %p", o1, o2); 447 354 448 355 return ORDER_scalar( o1->data.vendor.vendor_id, o2->data.vendor.vendor_id ); 449 356 } … … 453 360 { 454 361 TRACE_ENTRY("%p %p", o1, o2); 455 362 456 363 return ORDER_scalar( o1->data.application.application_id, o2->data.application.application_id ); 457 364 } … … 461 368 { 462 369 TRACE_ENTRY("%p %p", o1, o2); 463 370 464 371 return fd_os_cmp( o1->data.type.type_name, o1->datastr_len, o2->data.type.type_name, o2->datastr_len ); 465 372 } … … 469 376 { 470 377 TRACE_ENTRY("%p %p", o1, o2); 471 378 472 379 return fd_os_cmp( o1->data.enumval.enum_name, o1->datastr_len, o2->data.enumval.enum_name, o2->datastr_len ); 473 380 } … … 477 384 { 478 385 TRACE_ENTRY("%p %p", o1, o2); 479 386 480 387 /* The comparison function depends on the type of data */ 481 388 switch ( o1->parent->data.type.type_base ) { 482 389 case AVP_TYPE_OCTETSTRING: 483 return fd_os_cmp( o1->data.enumval.enum_value.os.data, o1->data.enumval.enum_value.os.len, 390 return fd_os_cmp( o1->data.enumval.enum_value.os.data, o1->data.enumval.enum_value.os.len, 484 391 o2->data.enumval.enum_value.os.data, o2->data.enumval.enum_value.os.len); 485 392 486 393 case AVP_TYPE_INTEGER32: 487 394 return ORDER_scalar( o1->data.enumval.enum_value.i32, o2->data.enumval.enum_value.i32 ); … … 513 420 { 514 421 TRACE_ENTRY("%p %p", o1, o2); 515 422 516 423 return ORDER_scalar( o1->data.avp.avp_code, o2->data.avp.avp_code ); 517 424 } … … 521 428 { 522 429 TRACE_ENTRY("%p %p", o1, o2); 523 430 524 431 return fd_os_cmp( o1->data.avp.avp_name, o1->datastr_len, o2->data.avp.avp_name, o2->datastr_len ); 525 432 } … … 529 436 { 530 437 TRACE_ENTRY("%p %p", o1, o2); 531 438 532 439 return fd_os_cmp( o1->data.cmd.cmd_name, o1->datastr_len, o2->data.cmd.cmd_name, o2->datastr_len ); 533 440 } … … 538 445 uint8_t fl1, fl2; 539 446 int cmp = 0; 540 447 541 448 TRACE_ENTRY("%p %p", o1, o2); 542 449 543 450 cmp = ORDER_scalar( o1->data.cmd.cmd_code, o2->data.cmd.cmd_code ); 544 if (cmp) 451 if (cmp) 545 452 return cmp; 546 453 547 454 /* Same command code, we must compare the value of the 'R' flag */ 548 455 fl1 = o1->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST; 549 456 fl2 = o2->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST; 550 457 551 458 /* We want requests first, so we reverse the operators here */ 552 459 return ORDER_scalar(fl2, fl1); 553 460 554 461 } 555 462 … … 558 465 { 559 466 TRACE_ENTRY("%p %p", o1, o2); 560 561 return ORDER_scalar(o1->data.rule.rule_avp->data.avp.avp_vendor, o2->data.rule.rule_avp->data.avp.avp_vendor) 467 468 return ORDER_scalar(o1->data.rule.rule_avp->data.avp.avp_vendor, o2->data.rule.rule_avp->data.avp.avp_vendor) 562 469 ?: ORDER_scalar(o1->data.rule.rule_avp->data.avp.avp_code, o2->data.rule.rule_avp->data.avp.avp_code) ; 563 470 } … … 745 652 int ret = 0; 746 653 vendor_id_t id; 747 654 748 655 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 749 656 750 657 switch (criteria) { 751 658 case VENDOR_BY_ID: … … 753 660 SEARCH_scalar( id, &dict->dict_vendors.list[0], vendor.vendor_id, 1, &dict->dict_vendors ); 754 661 break; 755 662 756 663 case VENDOR_BY_NAME: 757 664 /* "what" is a vendor name */ 758 665 SEARCH_os0( what, &dict->dict_vendors.list[0], vendor.vendor_name, 0); 759 666 break; 760 667 761 668 case VENDOR_OF_APPLICATION: 762 669 /* "what" should be an application object */ 763 670 SEARCH_childs_parent( DICT_APPLICATION, &dict->dict_vendors ); 764 671 break; 765 672 766 673 case VENDOR_OF_AVP: 767 674 /* "what" should be an avp object */ 768 675 SEARCH_sentinel( DICT_AVP, 0, 1 ); 769 676 break; 770 677 771 678 default: 772 679 /* Invalid criteria */ … … 781 688 int ret = 0; 782 689 application_id_t id; 783 690 784 691 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 785 692 786 693 switch (criteria) { 787 694 case APPLICATION_BY_ID: … … 790 697 SEARCH_scalar( id, &dict->dict_applications.list[0], application.application_id, 1, &dict->dict_applications ); 791 698 break; 792 699 793 700 case APPLICATION_BY_NAME: 794 701 /* "what" is an application name */ 795 702 SEARCH_os0( what, &dict->dict_applications.list[0], application.application_name, 0); 796 703 break; 797 704 798 705 case APPLICATION_OF_TYPE: 799 706 /* "what" should be a type object */ 800 707 SEARCH_childs_parent( DICT_TYPE, &dict->dict_applications ); 801 708 break; 802 709 803 710 case APPLICATION_OF_COMMAND: 804 711 /* "what" should be a command object */ 805 712 SEARCH_childs_parent( DICT_COMMAND, &dict->dict_applications ); 806 713 break; 807 714 808 715 default: 809 716 /* Invalid criteria */ … … 817 724 { 818 725 int ret = 0; 819 726 820 727 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 821 728 822 729 switch (criteria) { 823 730 case TYPE_BY_NAME: … … 825 732 SEARCH_os0( what, &dict->dict_types, type.type_name, 1); 826 733 break; 827 734 828 735 case TYPE_OF_ENUMVAL: 829 736 /* "what" should be a type_enum object */ 830 737 SEARCH_childs_parent( DICT_ENUMVAL, NULL ); 831 738 break; 832 739 833 740 case TYPE_OF_AVP: 834 741 /* "what" should be an avp object */ 835 742 SEARCH_childs_parent( DICT_AVP, NULL ); 836 743 break; 837 838 744 745 839 746 default: 840 747 /* Invalid criteria */ … … 848 755 { 849 756 int ret = 0; 850 757 851 758 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 852 759 853 760 switch (criteria) { 854 761 case ENUMVAL_BY_STRUCT: … … 856 763 struct dict_object * parent = NULL; 857 764 struct dict_enumval_request * _what = (struct dict_enumval_request *) what; 858 765 859 766 CHECK_PARAMS( _what && ( _what->type_obj || _what->type_name ) ); 860 767 861 768 if (_what->type_obj != NULL) { 862 769 parent = _what->type_obj; … … 867 774 CHECK_PARAMS( 0 ) ); 868 775 } 869 776 870 777 /* From here the "parent" object is valid */ 871 778 872 779 if ( _what->search.enum_name != NULL ) { 873 780 /* We are looking for this string */ … … 877 784 switch (parent->data.type.type_base) { 878 785 case AVP_TYPE_OCTETSTRING: 879 SEARCH_os( _what->search.enum_value.os.data, 880 _what->search.enum_value.os.len, 881 &parent->list[2], 882 enumval.enum_value.os , 786 SEARCH_os( _what->search.enum_value.os.data, 787 _what->search.enum_value.os.len, 788 &parent->list[2], 789 enumval.enum_value.os , 883 790 1 ); 884 791 break; … … 891 798 (struct dict_object *)NULL); 892 799 break; 893 800 894 801 case AVP_TYPE_INTEGER64: 895 802 SEARCH_scalar( _what->search.enum_value.i64, … … 899 806 (struct dict_object *)NULL); 900 807 break; 901 808 902 809 case AVP_TYPE_UNSIGNED32: 903 810 SEARCH_scalar( _what->search.enum_value.u32, … … 907 814 (struct dict_object *)NULL); 908 815 break; 909 816 910 817 case AVP_TYPE_UNSIGNED64: 911 818 SEARCH_scalar( _what->search.enum_value.u64, … … 915 822 (struct dict_object *)NULL); 916 823 break; 917 824 918 825 case AVP_TYPE_FLOAT32: 919 826 SEARCH_scalar( _what->search.enum_value.f32, … … 923 830 (struct dict_object *)NULL); 924 831 break; 925 832 926 833 case AVP_TYPE_FLOAT64: 927 834 SEARCH_scalar( _what->search.enum_value.f64, … … 931 838 (struct dict_object *)NULL); 932 839 break; 933 840 934 841 default: 935 842 /* Invalid parent type basetype */ … … 937 844 } 938 845 } 939 846 940 847 } 941 848 break; 942 943 849 850 944 851 default: 945 852 /* Invalid criteria */ … … 953 860 { 954 861 int ret = 0; 955 862 956 863 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 957 864 958 865 switch (criteria) { 959 866 case AVP_BY_CODE: … … 965 872 } 966 873 break; 967 874 968 875 case AVP_BY_NAME: 969 876 /* "what" is the AVP name, vendor 0 */ 970 877 SEARCH_os0( what, &dict->dict_vendors.list[2], avp.avp_name, 1); 971 878 break; 972 879 973 880 case AVP_BY_CODE_AND_VENDOR: 974 881 case AVP_BY_NAME_AND_VENDOR: … … 976 883 struct dict_avp_request * _what = (struct dict_avp_request *) what; 977 884 struct dict_object * vendor = NULL; 978 885 979 886 CHECK_PARAMS( (criteria != AVP_BY_NAME_AND_VENDOR) || _what->avp_name ); 980 887 981 888 /* Now look for the vendor first */ 982 889 CHECK_FCT( search_vendor( dict, VENDOR_BY_ID, &_what->avp_vendor, &vendor ) ); … … 988 895 goto end; 989 896 } 990 897 991 898 /* We now have our vendor = head of the appropriate avp list */ 992 899 if (criteria == AVP_BY_NAME_AND_VENDOR) { … … 998 905 } 999 906 break; 1000 907 1001 908 case AVP_BY_STRUCT: 1002 909 { 1003 910 struct dict_avp_request_ex * _what = (struct dict_avp_request_ex *) what; 1004 911 struct dict_object * vendor = NULL; 1005 912 1006 913 CHECK_PARAMS( _what->avp_vendor.vendor || _what->avp_vendor.vendor_id || _what->avp_vendor.vendor_name ); 1007 914 CHECK_PARAMS( _what->avp_data.avp_code || _what->avp_data.avp_name ); 1008 915 1009 916 /* Now look for the vendor first */ 1010 917 if (_what->avp_vendor.vendor) { … … 1017 924 CHECK_FCT( search_vendor( dict, VENDOR_BY_NAME, _what->avp_vendor.vendor_name, &vendor ) ); 1018 925 } 1019 926 1020 927 if (vendor == NULL) { 1021 928 if (result) … … 1025 932 goto end; 1026 933 } 1027 934 1028 935 /* We now have our vendor = head of the appropriate avp list */ 1029 936 if (_what->avp_data.avp_code) { … … 1035 942 } 1036 943 break; 1037 944 1038 945 case AVP_BY_NAME_ALL_VENDORS: 1039 946 { 1040 947 struct fd_list * li; 1041 948 size_t wl = strlen((char *)what); 1042 949 1043 950 /* First, search for vendor 0 */ 1044 951 SEARCH_os0_l( what, wl, &dict->dict_vendors.list[2], avp.avp_name, 1); 1045 952 1046 953 /* If not found, loop for all vendors, until found */ 1047 954 for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) { … … 1050 957 } 1051 958 break; 1052 959 1053 960 default: 1054 961 /* Invalid criteria */ … … 1062 969 { 1063 970 int ret = 0; 1064 971 1065 972 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 1066 973 1067 974 switch (criteria) { 1068 975 case CMD_BY_NAME: … … 1070 977 SEARCH_os0( what, &dict->dict_cmd_name, cmd.cmd_name, 1); 1071 978 break; 1072 979 1073 980 case CMD_BY_CODE_R: 1074 981 case CMD_BY_CODE_A: … … 1076 983 command_code_t code; 1077 984 uint8_t searchfl = 0; 1078 985 1079 986 /* The command code that we are searching */ 1080 987 code = *(command_code_t *) what; 1081 988 1082 989 /* The flag (request or answer) of the command we are searching */ 1083 990 if (criteria == CMD_BY_CODE_R) { 1084 991 searchfl = CMD_FLAG_REQUEST; 1085 992 } 1086 993 1087 994 /* perform the search */ 1088 995 SEARCH_codefl( code, searchfl, &dict->dict_cmd_code ); 1089 996 } 1090 997 break; 1091 998 1092 999 case CMD_ANSWER: 1093 1000 { … … 1095 1002 struct dict_object * req = (struct dict_object *) what; 1096 1003 struct dict_object * ans = NULL; 1097 1098 CHECK_PARAMS( verify_object(req) 1004 1005 CHECK_PARAMS( verify_object(req) 1099 1006 && (req->type == DICT_COMMAND) 1100 1007 && (req->data.cmd.cmd_flag_mask & CMD_FLAG_REQUEST) 1101 1008 && (req->data.cmd.cmd_flag_val & CMD_FLAG_REQUEST) ); 1102 1009 1103 1010 /* The answer is supposed to be the next element in the list, if it exists */ 1104 1011 ans = req->list[1].next->o; … … 1108 1015 goto end; 1109 1016 } 1110 1017 1111 1018 /* Now check that the ans element is really the correct one */ 1112 1019 if ( (ans->data.cmd.cmd_code != req->data.cmd.cmd_code) … … 1117 1024 goto end; 1118 1025 } 1119 1026 1120 1027 if (result) 1121 1028 *result = ans; 1122 1029 ret = 0; 1123 } 1124 break; 1125 1030 } 1031 break; 1032 1126 1033 default: 1127 1034 /* Invalid criteria */ … … 1135 1042 { 1136 1043 int ret = 0; 1137 1044 1138 1045 TRACE_ENTRY("%p %d %p %p", dict, criteria, what, result); 1139 1046 1140 1047 switch (criteria) { 1141 1048 case RULE_BY_AVP_AND_PARENT: … … 1144 1051 struct dict_object * avp = NULL; 1145 1052 struct dict_rule_request * _what = (struct dict_rule_request *) what; 1146 1147 CHECK_PARAMS( _what 1053 1054 CHECK_PARAMS( _what 1148 1055 && (parent = _what->rule_parent) 1149 1056 && (avp = _what->rule_avp ) ); 1150 1151 CHECK_PARAMS( verify_object(parent) 1152 && ((parent->type == DICT_COMMAND) 1057 1058 CHECK_PARAMS( verify_object(parent) 1059 && ((parent->type == DICT_COMMAND) 1153 1060 || ((parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED))) ); 1154 1061 1155 1062 CHECK_PARAMS( verify_object(avp) && (avp->type == DICT_AVP) ); 1156 1063 1157 1064 /* Perform the search */ 1158 1065 SEARCH_ruleavpname( avp->data.avp.avp_name, avp->datastr_len, &parent->list[2]); 1159 1066 1160 1067 } 1161 1068 break; 1162 1069 1163 1070 default: 1164 1071 /* Invalid criteria */ … … 1180 1087 { 1181 1088 struct dict_vendor_data * vendor = (struct dict_vendor_data *)data; 1182 1089 1183 1090 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name); 1184 1091 } … … 1191 1098 { 1192 1099 struct dict_type_data * type = ( struct dict_type_data * ) data; 1193 1194 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-12s \"%s\"", 1195 type_base_name[type->type_base], 1100 1101 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-12s \"%s\"", 1102 type_base_name[type->type_base], 1196 1103 type->type_name); 1197 1104 } … … 1212 1119 } 1213 1120 break; 1214 1121 1215 1122 case AVP_TYPE_INTEGER32: 1216 1123 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%i", enumval->enum_value.i32), return NULL); … … 1236 1143 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", enumval->enum_value.f64), return NULL); 1237 1144 break; 1238 1145 1239 1146 default: 1240 1147 CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "??? (ERROR unknown type %d)", type), return NULL); … … 1245 1152 { 1246 1153 struct dict_avp_data * avp = (struct dict_avp_data * ) data; 1247 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"", 1248 DUMP_AVPFL_val(avp->avp_flag_val), 1249 DUMP_AVPFL_val(avp->avp_flag_mask), 1250 type_base_name[avp->avp_basetype], 1251 avp->avp_code, 1154 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"", 1155 DUMP_AVPFL_val(avp->avp_flag_val), 1156 DUMP_AVPFL_val(avp->avp_flag_mask), 1157 type_base_name[avp->avp_basetype], 1158 avp->avp_code, 1252 1159 avp->avp_name ); 1253 1160 } … … 1255 1162 { 1256 1163 struct dict_cmd_data * cmd = (struct dict_cmd_data *) data; 1257 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", 1164 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", 1258 1165 DUMP_CMDFL_val(cmd->cmd_flag_val), DUMP_CMDFL_val(cmd->cmd_flag_mask), cmd->cmd_code, cmd->cmd_name); 1259 1166 } … … 1262 1169 struct dict_rule_data * rule = (struct dict_rule_data * )data; 1263 1170 return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"", 1264 rule->rule_position, 1265 rule->rule_order, 1266 rule->rule_min, 1171 rule->rule_position, 1172 rule->rule_order, 1173 rule->rule_min, 1267 1174 rule->rule_max, 1268 1175 rule->rule_avp->data.avp.avp_name); … … 1291 1198 { 1292 1199 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{dictobj}(@%p): ", indent, "", obj), return NULL); 1293 1200 1294 1201 if (!verify_object(obj)) { 1295 1202 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); 1296 1203 return *buf; 1297 1204 } 1298 1299 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s p:%p ", 1300 _OBINFO(obj).name, 1205 1206 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s p:%p ", 1207 _OBINFO(obj).name, 1301 1208 obj->parent), return NULL); 1302 1209 1303 1210 if (obj->type == DICT_ENUMVAL) { 1304 1211 CHECK_MALLOC_DO( dump_enumval_data ( FD_DUMP_STD_PARAMS, &obj->data.enumval, obj->parent->data.type.type_base ), return NULL); … … 1306 1213 CHECK_MALLOC_DO( _OBINFO(obj).dump_data(FD_DUMP_STD_PARAMS, &obj->data), return NULL); 1307 1214 } 1308 1215 1309 1216 if (parents) { 1310 1217 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n%*sparent:", indent + 1, ""), return NULL); 1311 1218 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, obj->parent, parents-1, 0, 0 ), return NULL); 1312 1219 } 1313 1220 1314 1221 if (depth) { 1315 1222 int i; … … 1321 1228 } 1322 1229 } 1323 1230 1324 1231 return *buf; 1325 1232 } … … 1328 1235 { 1329 1236 FD_DUMP_HANDLE_OFFSET(); 1330 1237 1331 1238 CHECK_MALLOC_DO( dump_object(FD_DUMP_STD_PARAMS, obj, 1, 2, 0), return NULL); 1332 1239 1333 1240 return *buf; 1334 1241 } … … 1338 1245 int i; 1339 1246 struct fd_list * li; 1340 1247 1341 1248 FD_DUMP_HANDLE_OFFSET(); 1342 1249 1343 1250 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{dictionary}(@%p): ", dict), return NULL); 1344 1251 1345 1252 if ((dict == NULL) || (dict->dict_eyec != DICT_EYECATCHER)) { 1346 1253 return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL"); 1347 1254 } 1348 1255 1349 1256 CHECK_POSIX_DO( pthread_rwlock_rdlock( &dict->dict_lock ), /* ignore */ ); 1350 1257 1351 1258 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): VENDORS / AVP / RULES\n", dict), goto error); 1352 1259 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_vendors, 0, 3, 3 ), goto error); … … 1355 1262 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 3, 3 ), goto error); 1356 1263 } 1357 1264 1358 1265 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): APPLICATIONS\n", dict), goto error); 1359 1266 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_applications, 0, 1, 3 ), goto error); … … 1362 1269 CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 1, 3 ), goto error); 1363 1270 } 1364 1271 1365 1272 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): TYPES / ENUMVAL", dict), goto error); 1366 1273 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_types, 0, 2, 3 ), goto error); 1367 1274 1368 1275 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): COMMANDS / RULES", dict), goto error); 1369 1276 CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_cmd_code, 0, 0, 3 ), goto error); 1370 1277 1371 1278 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict}(@%p): statistics", dict), goto error); 1372 1279 for (i=1; i<=DICT_TYPE_MAX; i++) 1373 1280 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n %5d: %s", dict->dict_count[i], dict_obj_info[i].name), goto error); 1374 1281 1375 1282 CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ ); 1376 1283 return *buf; 1377 error: 1284 error: 1378 1285 /* Free the rwlock */ 1379 1286 CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ ); … … 1387 1294 { 1388 1295 int i; 1389 1296 1390 1297 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<"), return NULL); 1391 1298 for (i = 0; i < value->os.len; i++) { … … 1436 1343 case AVP_TYPE_OCTETSTRING: 1437 1344 return &dump_val_os; 1438 1345 1439 1346 case AVP_TYPE_INTEGER32: 1440 1347 return &dump_val_i32; … … 1454 1361 case AVP_TYPE_FLOAT64: 1455 1362 return &dump_val_f64; 1456 1363 1457 1364 case AVP_TYPE_GROUPED: 1458 1365 TRACE_DEBUG(FULL, "error: grouped AVP with a value!"); … … 1468 1375 1469 1376 /* Formatter for the AVP value dump line */ 1470 static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_val, union avp_value *avp_value, 1471 dump_val_cb_t def_dump_val_cb, 1472 dump_val_cb_t dump_val_cb, 1473 enum dict_avp_basetype datatype, 1474 char * type_name, 1475 char * const_name, 1476 int indent, 1377 static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_val, union avp_value *avp_value, 1378 dump_val_cb_t def_dump_val_cb, 1379 dump_val_cb_t dump_val_cb, 1380 enum dict_avp_basetype datatype, 1381 char * type_name, 1382 char * const_name, 1383 int indent, 1477 1384 int header) 1478 1385 { … … 1480 1387 /* Header for all AVP values dumps: */ 1481 1388 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, INOBJHDR "value ", INOBJHDRVAL), return NULL); 1482 1389 1483 1390 /* If the type is provided, write it */ 1484 1391 if (type_name) { 1485 1392 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "t: '%s' ", type_name), return NULL); 1486 1393 } 1487 1394 1488 1395 /* Always give the base datatype anyway */ 1489 1396 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(%s) ", type_base_name[datatype]), return NULL); … … 1503 1410 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ")"), return NULL); 1504 1411 } 1505 1412 1506 1413 /* Done! */ 1507 1414 return *buf; … … 1515 1422 char * type_name = NULL; 1516 1423 char * const_name = NULL; 1517 1424 1518 1425 FD_DUMP_HANDLE_OFFSET(); 1519 1426 1520 1427 /* Handle invalid parameters */ 1521 1428 if (!avp_value) { … … 1528 1435 return *buf; 1529 1436 } 1530 1437 1531 1438 if (! ( verify_object(model) && (model->type == DICT_AVP) )) { 1532 1439 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(invalid model)"), return NULL); 1533 1440 return *buf; 1534 1441 } 1535 1442 1536 1443 /* Get the type definition of this AVP */ 1537 1444 type = model->parent; … … 1539 1446 struct dict_enumval_request request; 1540 1447 struct dict_object * enumval = NULL; 1541 1448 1542 1449 type_name = type->data.type.type_name; 1543 1450 1544 1451 /* overwrite the dump function ? */ 1545 1452 if (type->data.type.type_dump) 1546 1453 dump_val_cb = type->data.type.type_dump; 1547 1454 1548 1455 /* Now check if the AVP value matches a constant */ 1549 1456 memset(&request, 0, sizeof(request)); … … 1556 1463 } 1557 1464 } 1558 1465 1559 1466 /* And finally, dump the value */ 1560 1467 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 ); … … 1576 1483 { 1577 1484 TRACE_ENTRY("%p %p", object, type); 1578 1485 1579 1486 CHECK_PARAMS( type && verify_object(object) ); 1580 1487 1581 1488 /* Copy the value and return */ 1582 1489 *type = object->type; … … 1587 1494 { 1588 1495 TRACE_ENTRY("%p %p", object, dict); 1589 1496 1590 1497 CHECK_PARAMS( dict && verify_object(object) ); 1591 1498 1592 1499 /* Copy the value and return */ 1593 1500 *dict = object->dico; … … 1600 1507 { 1601 1508 TRACE_ENTRY("%p %p", object, val); 1602 1509 1603 1510 CHECK_PARAMS( val && verify_object(object) ); 1604 1511 1605 1512 /* Copy the value and return */ 1606 1513 memcpy(val, &object->data, _OBINFO(object).datasize);; … … 1616 1523 struct dict_object * vendor = NULL; 1617 1524 struct dict_object * locref = NULL; 1618 1525 1619 1526 TRACE_ENTRY("%p %d(%s) %p %p %p", dict, type, dict_obj_info[CHECK_TYPE(type) ? type : 0].name, data, parent, ref); 1620 1527 1621 1528 /* Check parameters */ 1622 1529 CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) && data ); 1623 1530 1624 1531 /* Check the "parent" parameter */ 1625 1532 switch (dict_obj_info[type].parent) { 1626 1533 case 0: /* parent is forbidden */ 1627 1534 CHECK_PARAMS_DO( parent == NULL, goto error_param ); 1628 1535 1629 1536 case 1: /* parent is optional */ 1630 1537 if (parent == NULL) 1631 1538 break; 1632 1539 1633 1540 case 2: /* parent is mandatory */ 1634 1541 CHECK_PARAMS_DO( verify_object(parent), goto error_param ); 1635 1542 1636 1543 if (type == DICT_RULE ) { /* Special case : grouped AVP or Command parents are allowed */ 1637 CHECK_PARAMS_DO( (parent->type == DICT_COMMAND ) 1544 CHECK_PARAMS_DO( (parent->type == DICT_COMMAND ) 1638 1545 || ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ), goto error_param ); 1639 1546 } else { … … 1641 1548 } 1642 1549 } 1643 1550 1644 1551 /* For AVP object, we must also check that the "vendor" referenced exists */ 1645 1552 if (type == DICT_AVP) { 1646 1553 CHECK_FCT_DO( fd_dict_search( dict, DICT_VENDOR, VENDOR_BY_ID, &(((struct dict_avp_data *)data)->avp_vendor), (void*)&vendor, ENOENT ), 1647 1554 { TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); goto error_param; } ); 1648 1555 1649 1556 /* Also check if a parent is provided, that the type are the same */ 1650 1557 if (parent) { … … 1652 1559 } 1653 1560 } 1654 1561 1655 1562 /* For RULE object, we must also check that the "avp" referenced exists */ 1656 1563 if (type == DICT_RULE) { … … 1658 1565 CHECK_PARAMS_DO( ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP, goto error_param ); 1659 1566 } 1660 1567 1661 1568 /* For COMMAND object, check that the 'R' flag is fixed */ 1662 1569 if (type == DICT_COMMAND) { … … 1669 1576 dupos = 1; 1670 1577 } 1671 1578 1672 1579 /* We have to check that the new values are not equal to the sentinels */ 1673 1580 if (type == DICT_VENDOR) { … … 1677 1584 CHECK_PARAMS_DO( ((struct dict_application_data *)data)->application_id != 0, goto error_param ); 1678 1585 } 1679 1586 1680 1587 /* Parameters are valid, create the new object */ 1681 1588 CHECK_MALLOC( new = malloc(sizeof(struct dict_object)) ); 1682 1589 1683 1590 /* Initialize the data of the new object */ 1684 1591 init_object(new, type); … … 1686 1593 new->dico = dict; 1687 1594 new->parent = parent; 1688 1595 1689 1596 /* We will change the dictionary => acquire the write lock */ 1690 1597 CHECK_POSIX_DO( ret = pthread_rwlock_wrlock(&dict->dict_lock), goto error_free ); 1691 1598 1692 1599 /* Now link the object -- this also checks that no object with same keys already exists */ 1693 1600 switch (type) { … … 1698 1605 goto error_unlock; 1699 1606 break; 1700 1607 1701 1608 case DICT_APPLICATION: 1702 1609 /* An application object is linked in the g_dict_applciations.list[0], by their id */ … … 1705 1612 goto error_unlock; 1706 1613 break; 1707 1614 1708 1615 case DICT_TYPE: 1709 1616 /* A type object is linked in g_list_types by its name */ … … 1712 1619 goto error_unlock; 1713 1620 break; 1714 1621 1715 1622 case DICT_ENUMVAL: 1716 1623 /* A type_enum object is linked in it's parent 'type' object lists 1 and 2 by its name and values */ … … 1718 1625 if (ret) 1719 1626 goto error_unlock; 1720 1627 1721 1628 ret = fd_list_insert_ordered ( &parent->list[2], &new->list[1], (int (*)(void*, void *))order_enum_by_val, (void **)&locref ); 1722 if (ret) { 1723 fd_list_unlink(&new->list[0]); 1724 goto error_unlock; 1629 if (ret) { 1630 fd_list_unlink(&new->list[0]); 1631 goto error_unlock; 1725 1632 } 1726 1633 break; 1727 1634 1728 1635 case DICT_AVP: 1729 1636 /* An avp object is linked in lists 1 and 2 of its vendor, by code and name */ … … 1731 1638 if (ret) 1732 1639 goto error_unlock; 1733 1640 1734 1641 ret = fd_list_insert_ordered ( &vendor->list[2], &new->list[1], (int (*)(void*, void *))order_avp_by_name, (void **)&locref ); 1735 1642 if (ret) { … … 1738 1645 } 1739 1646 break; 1740 1647 1741 1648 case DICT_COMMAND: 1742 1649 /* A command object is linked in g_list_cmd_name and g_list_cmd_code by its name and code */ … … 1744 1651 if (ret) 1745 1652 goto error_unlock; 1746 1653 1747 1654 ret = fd_list_insert_ordered ( &dict->dict_cmd_name, &new->list[0], (int (*)(void*, void *))order_cmd_by_name, (void **)&locref ); 1748 1655 if (ret) { … … 1751 1658 } 1752 1659 break; 1753 1660 1754 1661 case DICT_RULE: 1755 1662 /* A rule object is linked in list[2] of its parent command or AVP by the name of the AVP it refers */ … … 1758 1665 goto error_unlock; 1759 1666 break; 1760 1667 1761 1668 default: 1762 1669 ASSERT(0); 1763 1670 } 1764 1671 1765 1672 /* A new object has been created, increment the global counter */ 1766 1673 dict->dict_count[type]++; 1767 1674 1768 1675 /* Unlock the dictionary */ 1769 1676 CHECK_POSIX_DO( ret = pthread_rwlock_unlock(&dict->dict_lock), goto error_free ); 1770 1677 1771 1678 /* Save the pointer to the new object */ 1772 1679 if (ref) 1773 1680 *ref = new; 1774 1681 1775 1682 return 0; 1776 1683 1777 1684 error_param: 1778 1685 ret = EINVAL; … … 1787 1694 TRACE_DEBUG(FULL, "Vendor %s already in dictionary", new->data.vendor.vendor_name); 1788 1695 /* if we are here, it means the two vendors id are identical */ 1789 if (fd_os_cmp(locref->data.vendor.vendor_name, locref->datastr_len, 1696 if (fd_os_cmp(locref->data.vendor.vendor_name, locref->datastr_len, 1790 1697 new->data.vendor.vendor_name, new->datastr_len)) { 1791 1698 TRACE_DEBUG(INFO, "Conflicting vendor name: %s", new->data.vendor.vendor_name); … … 1793 1700 } 1794 1701 /* Otherwise (same name), we consider the function succeeded, since the (same) object is in the dictionary */ 1795 ret = 0; 1702 ret = 0; 1796 1703 break; 1797 1704 … … 1799 1706 TRACE_DEBUG(FULL, "Application %s already in dictionary", new->data.application.application_name); 1800 1707 /* got same id */ 1801 if (fd_os_cmp(locref->data.application.application_name, locref->datastr_len, 1708 if (fd_os_cmp(locref->data.application.application_name, locref->datastr_len, 1802 1709 new->data.application.application_name, new->datastr_len)) { 1803 1710 TRACE_DEBUG(FULL, "Conflicting application name"); … … 1937 1844 char * buf = NULL; 1938 1845 size_t len = 0, offset=0; 1939 1846 1940 1847 if (type == DICT_ENUMVAL) { 1941 1848 CHECK_MALLOC( dump_enumval_data ( &buf, &len, &offset, data, parent->data.type.type_base )); … … 1943 1850 CHECK_MALLOC( dict_obj_info[CHECK_TYPE(type) ? type : 0].dump_data(&buf, &len, &offset, data) ); 1944 1851 } 1945 1852 1946 1853 TRACE_DEBUG(INFO, "An error occurred while adding the following data in the dictionary: %s", buf); 1947 1854 1948 1855 if (ret == EEXIST) { 1949 1856 offset=0; … … 1964 1871 struct dictionary * dict; 1965 1872 int ret=0; 1966 1873 1967 1874 /* check params */ 1968 1875 CHECK_PARAMS( verify_object(obj) && obj->dico); … … 1971 1878 /* Lock the dictionary for change */ 1972 1879 CHECK_POSIX( pthread_rwlock_wrlock(&dict->dict_lock) ); 1973 1880 1974 1881 /* check the object is not sentinel for another list */ 1975 1882 for (i=0; i<NB_LISTS_PER_OBJ; i++) { … … 1984 1891 } 1985 1892 } 1986 1893 1987 1894 /* ok, now destroy the object */ 1988 1895 if (!ret) 1989 1896 destroy_object(obj); 1990 1897 1991 1898 /* Unlock */ 1992 1899 CHECK_POSIX( pthread_rwlock_unlock(&dict->dict_lock) ); 1993 1900 1994 1901 return ret; 1995 1902 } … … 1999 1906 { 2000 1907 int ret = 0; 2001 1908 2002 1909 TRACE_ENTRY("%p %d(%s) %d %p %p %d", dict, type, dict_obj_info[CHECK_TYPE(type) ? type : 0].name, criteria, what, result, retval); 2003 1910 2004 1911 /* Check param */ 2005 1912 CHECK_PARAMS( dict && (dict->dict_eyec == DICT_EYECATCHER) && CHECK_TYPE(type) ); 2006 1913 2007 1914 /* Lock the dictionary for reading */ 2008 1915 CHECK_POSIX( pthread_rwlock_rdlock(&dict->dict_lock) ); 2009 1916 2010 1917 /* Now call the type-specific search function */ 2011 1918 ret = dict_obj_info[type].search_fct (dict, criteria, what, result); 2012 1919 2013 1920 /* Unlock */ 2014 1921 CHECK_POSIX( pthread_rwlock_unlock(&dict->dict_lock) ); 2015 1922 2016 1923 /* Update the return value as needed */ 2017 1924 if ((result != NULL) && (*result == NULL)) 2018 1925 ret = retval; 2019 1926 2020 1927 return ret; 2021 1928 } … … 2030 1937 } 2031 1938 2032 The following criteria are allowed, with corresponding parent. 1939 The following criteria are allowed, with corresponding parent. 2033 1940 The parent is either struct dictionary * or struct dict_object * 2034 1941 2035 1942 VENDOR_BY_ID : (parent = dictionary) returns list of vendors ordered by ID 2036 1943 APPLICATION_BY_ID : (parent = dictionary) returns list of applications ordered by ID 2037 ** for these two lists, the Vendor with id 0 and applciation with id 0 are excluded. 1944 ** for these two lists, the Vendor with id 0 and applciation with id 0 are excluded. 2038 1945 You must resolve them separatly with dict_search. 2039 1946 2040 1947 TYPE_BY_NAME : (parent = dictionary) returns list of types ordered by name (osstring order) 2041 1948 ENUMVAL_BY_NAME : (parent = type object) return list of constants for this type ordered by name (osstring order) … … 2053 1960 struct dictionary * dict = parent; 2054 1961 struct dict_object * obj_parent = parent; 2055 1962 2056 1963 TRACE_ENTRY("%i %p %p", criteria, parent, sentinel); 2057 1964 2058 1965 CHECK_PARAMS(sentinel && parent); 2059 1966 2060 1967 switch(criteria) { 2061 1968 case VENDOR_BY_ID: /* parent must be the dictionary */ … … 2063 1970 *sentinel = &dict->dict_vendors.list[0]; 2064 1971 break; 2065 1972 2066 1973 case APPLICATION_BY_ID: /* parent must be the dictionary */ 2067 1974 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 2068 1975 *sentinel = &dict->dict_applications.list[0]; 2069 1976 break; 2070 1977 2071 1978 case TYPE_BY_NAME: /* parent must be the dictionary */ 2072 1979 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 2073 1980 *sentinel = &dict->dict_types; 2074 1981 break; 2075 1982 2076 1983 case ENUMVAL_BY_NAME: /* parent must be a type object */ 2077 1984 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_TYPE)); 2078 1985 *sentinel = &obj_parent->list[1]; 2079 1986 break; 2080 1987 2081 1988 case ENUMVAL_BY_VALUE: /* parent must be a type object */ 2082 1989 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_TYPE)); 2083 1990 *sentinel = &obj_parent->list[2]; 2084 1991 break; 2085 1992 2086 1993 case AVP_BY_NAME: /* parent must be a VENDOR object */ 2087 1994 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_VENDOR)); 2088 1995 *sentinel = &obj_parent->list[2]; 2089 1996 break; 2090 1997 2091 1998 case AVP_BY_CODE: /* parent must be a VENDOR object */ 2092 1999 CHECK_PARAMS(verify_object(obj_parent) && (obj_parent->type == DICT_VENDOR)); 2093 2000 *sentinel = &obj_parent->list[1]; 2094 2001 break; 2095 2002 2096 2003 case CMD_BY_NAME: /* parent must be the dictionary */ 2097 2004 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 2098 2005 *sentinel = &dict->dict_cmd_name; 2099 2006 break; 2100 2007 2101 2008 case CMD_BY_CODE_R: /* parent must be the dictionary */ 2102 2009 CHECK_PARAMS(dict->dict_eyec == DICT_EYECATCHER); 2103 2010 *sentinel = &dict->dict_cmd_code; 2104 2011 break; 2105 2012 2106 2013 case RULE_BY_AVP_AND_PARENT: /* parent must be command or grouped AVP */ 2107 2014 CHECK_PARAMS(verify_object(obj_parent)); 2108 2015 CHECK_PARAMS( (obj_parent->type == DICT_COMMAND) || 2109 ((obj_parent->type == DICT_AVP) 2016 ((obj_parent->type == DICT_AVP) 2110 2017 && (obj_parent->data.avp.avp_basetype == AVP_TYPE_GROUPED)) ); 2111 2018 *sentinel = &obj_parent->list[2]; 2112 2019 break; 2113 2020 2114 2021 default: 2115 2022 CHECK_PARAMS(0); 2116 2023 } 2117 2024 2118 2025 return 0; 2119 2026 } … … 2131 2038 { 2132 2039 struct dictionary * new = NULL; 2133 2040 2134 2041 TRACE_ENTRY("%p", dict); 2135 2042 2136 2043 /* Sanity checks */ 2137 2044 ASSERT( (sizeof(type_base_name) / sizeof(type_base_name[0])) == (AVP_TYPE_MAX + 1) ); 2138 2045 ASSERT( (sizeof(dict_obj_info) / sizeof(dict_obj_info[0])) == (DICT_TYPE_MAX + 1) ); 2139 2046 CHECK_PARAMS(dict); 2140 2047 2141 2048 /* Allocate the memory for the dictionary */ 2142 2049 CHECK_MALLOC( new = malloc(sizeof(struct dictionary)) ); 2143 2050 memset(new, 0, sizeof(struct dictionary)); 2144 2051 2145 2052 new->dict_eyec = DICT_EYECATCHER; 2146 2053 2147 2054 /* Initialize the lock for the dictionary */ 2148 2055 CHECK_POSIX( pthread_rwlock_init(&new->dict_lock, NULL) ); 2149 2056 2150 2057 /* Initialize the sentinel for vendors and AVP lists */ 2151 2058 init_object( &new->dict_vendors, DICT_VENDOR ); … … 2155 2062 /* new->dict_vendors.list[0].o = NULL; *//* overwrite since element is also sentinel for this list. */ 2156 2063 new->dict_vendors.dico = new; 2157 2064 2158 2065 /* Initialize the sentinel for applications */ 2159 2066 init_object( &new->dict_applications, DICT_APPLICATION ); … … 2163 2070 /* new->dict_applications.list[0].o = NULL; *//* overwrite since since element is also sentinel for this list. */ 2164 2071 new->dict_applications.dico = new; 2165 2072 2166 2073 /* Initialize the sentinel for types */ 2167 2074 fd_list_init ( &new->dict_types, NULL ); 2168 2075 2169 2076 /* Initialize the sentinels for commands */ 2170 2077 fd_list_init ( &new->dict_cmd_name, NULL ); 2171 2078 fd_list_init ( &new->dict_cmd_code, NULL ); 2172 2079 2173 2080 /* Initialize the error command object */ 2174 2081 init_object( &new->dict_cmd_error, DICT_COMMAND ); … … 2179 2086 new->dict_cmd_error.data.cmd.cmd_flag_val =CMD_FLAG_ERROR; 2180 2087 new->dict_cmd_error.dico = new; 2181 2088 2182 2089 *dict = new; 2183 2090 2184 2091 /* Done */ 2185 2092 return 0; … … 2190 2097 { 2191 2098 int i; 2192 2099 2193 2100 TRACE_ENTRY(""); 2194 2101 CHECK_PARAMS( dict && *dict && ((*dict)->dict_eyec == DICT_EYECATCHER) ); 2195 2102 2196 2103 /* Acquire the write lock to make sure no other operation is ongoing */ 2197 2104 CHECK_POSIX( pthread_rwlock_wrlock(&(*dict)->dict_lock) ); 2198 2105 2199 2106 /* Empty all the lists, free the elements */ 2200 2107 destroy_list ( &(*dict)->dict_cmd_error.list[2] ); … … 2206 2113 destroy_list ( &(*dict)->dict_vendors.list[i] ); 2207 2114 } 2208 2115 2209 2116 /* Dictionary is empty, now destroy the lock */ 2210 2117 CHECK_POSIX( pthread_rwlock_unlock(&(*dict)->dict_lock) ); 2211 2118 CHECK_POSIX( pthread_rwlock_destroy(&(*dict)->dict_lock) ); 2212 2119 2213 2120 free(*dict); 2214 2121 *dict = NULL; 2215 2122 2216 2123 return 0; 2217 2124 } … … 2230 2137 int ret = 0; 2231 2138 struct fd_list * li; 2232 2139 2233 2140 TRACE_ENTRY("%p %p %p", parent, data, cb); 2234 2141 2235 2142 /* Check parameters */ 2236 2143 CHECK_PARAMS( verify_object(parent) ); 2237 CHECK_PARAMS( (parent->type == DICT_COMMAND) 2144 CHECK_PARAMS( (parent->type == DICT_COMMAND) 2238 2145 || ((parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED)) ); 2239 TRACE_DEBUG (FULL, "Iterating on rules of %s: '%s'.", 2240 _OBINFO(parent).name, 2241 parent->type == DICT_COMMAND ? 2146 TRACE_DEBUG (FULL, "Iterating on rules of %s: '%s'.", 2147 _OBINFO(parent).name, 2148 parent->type == DICT_COMMAND ? 2242 2149 parent->data.cmd.cmd_name 2243 2150 : parent->data.avp.avp_name); 2244 2151 2245 2152 /* Acquire the read lock */ 2246 2153 CHECK_POSIX( pthread_rwlock_rdlock(&parent->dico->dict_lock) ); 2247 2154 2248 2155 /* go through the list and call the cb on each rule data */ 2249 2156 for (li = &(parent->list[2]); li->next != &(parent->list[2]); li = li->next) { … … 2252 2159 break; 2253 2160 } 2254 2161 2255 2162 /* Release the lock */ 2256 2163 CHECK_POSIX( pthread_rwlock_unlock(&parent->dico->dict_lock) ); 2257 2164 2258 2165 return ret; 2259 2166 } … … 2265 2172 int i = 0; 2266 2173 struct fd_list * li; 2267 2174 2268 2175 TRACE_ENTRY(); 2269 2176 2270 2177 /* Acquire the read lock */ 2271 2178 CHECK_POSIX_DO( pthread_rwlock_rdlock(&dict->dict_lock), return NULL ); 2272 2179 2273 2180 /* Allocate an array to contain all the elements */ 2274 2181 CHECK_MALLOC_DO( ret = calloc( dict->dict_count[DICT_VENDOR] + 1, sizeof(uint32_t) ), goto out ); 2275 2182 2276 2183 /* Copy the vendors IDs */ 2277 2184 for (li = dict->dict_vendors.list[0].next; li != &(dict->dict_vendors.list[0]); li = li->next) { … … 2280 2187 ASSERT( i <= dict->dict_count[DICT_VENDOR] ); 2281 2188 } 2282 out: 2189 out: 2283 2190 /* Release the lock */ 2284 2191 CHECK_POSIX_DO( pthread_rwlock_unlock(&dict->dict_lock), return NULL ); 2285 2192 2286 2193 return ret; 2287 2194 }
Note: See TracChangeset
for help on using the changeset viewer.