| OLD | NEW |
| (Empty) |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
| 2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 4 /* | |
| 5 * pkix_pl_object.c | |
| 6 * | |
| 7 * Object Construction, Destruction and Callback Functions | |
| 8 * | |
| 9 */ | |
| 10 | |
| 11 #include "pkix_pl_object.h" | |
| 12 | |
| 13 #ifdef PKIX_USER_OBJECT_TYPE | |
| 14 /* --Class-Table-Initializers------------------------------------ */ | |
| 15 | |
| 16 /* | |
| 17 * Create storage space for 20 Class Table buckets. | |
| 18 * These are only for user-defined types. System types are registered | |
| 19 * separately by PKIX_PL_Initialize. | |
| 20 */ | |
| 21 | |
| 22 static pkix_pl_HT_Elem* | |
| 23 pkix_Raw_ClassTable_Buckets[] = { | |
| 24 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
| 25 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL | |
| 26 }; | |
| 27 | |
| 28 /* | |
| 29 * Allocate static memory for a ClassTable. | |
| 30 * XXX This assumes the bucket pointer will fit into a PKIX_UInt32 | |
| 31 */ | |
| 32 static pkix_pl_PrimHashTable pkix_Raw_ClassTable = { | |
| 33 (void *)pkix_Raw_ClassTable_Buckets, /* Buckets */ | |
| 34 20 /* Number of Buckets */ | |
| 35 }; | |
| 36 static pkix_pl_PrimHashTable * classTable = &pkix_Raw_ClassTable; | |
| 37 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 38 | |
| 39 /* --Private-Functions-------------------------------------------- */ | |
| 40 | |
| 41 /* | |
| 42 * FUNCTION: pkix_pl_Object_GetHeader | |
| 43 * DESCRIPTION: | |
| 44 * | |
| 45 * Shifts Object pointed to by "object" by the sizeof(PKIX_PL_Object) and | |
| 46 * stores the value at "pObjectHeader". | |
| 47 * | |
| 48 * PARAMETERS: | |
| 49 * "object" | |
| 50 * Address of Object to shift. Must be non-NULL. | |
| 51 * "pObjectHeader" | |
| 52 * Address where object pointer will be stored. Must be non-NULL. | |
| 53 * "plContext" | |
| 54 * Platform-specific context pointer. | |
| 55 * THREAD SAFETY: | |
| 56 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 57 * RETURNS: | |
| 58 * Returns NULL if the function succeeds. | |
| 59 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 60 */ | |
| 61 static PKIX_Error * | |
| 62 pkix_pl_Object_GetHeader( | |
| 63 PKIX_PL_Object *object, | |
| 64 PKIX_PL_Object **pObjectHeader, | |
| 65 void *plContext) | |
| 66 { | |
| 67 PKIX_PL_Object *header = NULL; | |
| 68 PKIX_UInt32 objType; | |
| 69 | |
| 70 PKIX_ENTER(OBJECT, "pkix_pl_Object_GetHeader"); | |
| 71 PKIX_NULLCHECK_TWO(object, pObjectHeader); | |
| 72 | |
| 73 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); | |
| 74 | |
| 75 /* The header is sizeof(PKIX_PL_Object) before the object pointer */ | |
| 76 header = (PKIX_PL_Object *)((char *)object - sizeof(PKIX_PL_Object)); | |
| 77 | |
| 78 objType = header->type; | |
| 79 | |
| 80 if (objType >= PKIX_NUMTYPES) { /* if this is a user-defined type */ | |
| 81 #ifdef PKIX_USER_OBJECT_TYPE | |
| 82 pkix_ClassTable_Entry *ctEntry = NULL; | |
| 83 | |
| 84 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
| 85 PR_Lock(classTableLock); | |
| 86 | |
| 87 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup | |
| 88 (classTable, | |
| 89 (void *)&objType, | |
| 90 objType, | |
| 91 NULL, | |
| 92 (void **)&ctEntry, | |
| 93 plContext), | |
| 94 PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
| 95 | |
| 96 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
| 97 PR_Unlock(classTableLock); | |
| 98 | |
| 99 if (ctEntry == NULL) { | |
| 100 PKIX_ERROR_FATAL(PKIX_UNKNOWNOBJECTTYPE); | |
| 101 } | |
| 102 #else | |
| 103 PORT_Assert(objType < PKIX_NUMTYPES); | |
| 104 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
| 105 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 106 goto cleanup; | |
| 107 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 108 } | |
| 109 | |
| 110 #ifdef PKIX_OBJECT_LEAK_TEST | |
| 111 PORT_Assert(header && header->magicHeader == PKIX_MAGIC_HEADER); | |
| 112 #endif /* PKIX_OBJECT_LEAK_TEST */ | |
| 113 | |
| 114 if ((header == NULL)|| | |
| 115 (header->magicHeader != PKIX_MAGIC_HEADER)) { | |
| 116 PKIX_ERROR_ALLOC_ERROR(); | |
| 117 } | |
| 118 | |
| 119 *pObjectHeader = header; | |
| 120 | |
| 121 cleanup: | |
| 122 | |
| 123 PKIX_RETURN(OBJECT); | |
| 124 } | |
| 125 | |
| 126 /* | |
| 127 * FUNCTION: pkix_Destroy_Object | |
| 128 * DESCRIPTION: | |
| 129 * | |
| 130 * Destroys and deallocates Object pointed to by "object". The caller is | |
| 131 * assumed to hold the Object's lock, which is acquired in | |
| 132 * PKIX_PL_Object_DecRef(). | |
| 133 * | |
| 134 * PARAMETERS: | |
| 135 * "object" | |
| 136 * Address of Object to destroy. Must be non-NULL. | |
| 137 * "plContext" | |
| 138 * Platform-specific context pointer. | |
| 139 * THREAD SAFETY: | |
| 140 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 141 * RETURNS: | |
| 142 * Returns NULL if the function succeeds. | |
| 143 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 144 */ | |
| 145 static PKIX_Error * | |
| 146 pkix_pl_Object_Destroy( | |
| 147 PKIX_PL_Object *object, | |
| 148 void *plContext) | |
| 149 { | |
| 150 PKIX_PL_Object *objectHeader = NULL; | |
| 151 | |
| 152 PKIX_ENTER(OBJECT, "pkix_pl_Object_Destroy"); | |
| 153 PKIX_NULLCHECK_ONE(object); | |
| 154 | |
| 155 #ifdef PKIX_OBJECT_LEAK_TEST | |
| 156 PKIX_CHECK_FATAL(pkix_pl_Object_GetHeader(object, &objectHeader, plConte
xt), | |
| 157 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 158 #else | |
| 159 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
| 160 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 161 #endif /* PKIX_OBJECT_LEAK_TEST */ | |
| 162 | |
| 163 /* Attempt to delete an object still being used */ | |
| 164 if (objectHeader->references != 0) { | |
| 165 PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED); | |
| 166 } | |
| 167 | |
| 168 PKIX_DECREF(objectHeader->stringRep); | |
| 169 | |
| 170 /* Destroy this object's lock */ | |
| 171 PKIX_OBJECT_DEBUG("\tCalling PR_DestroyLock).\n"); | |
| 172 PR_DestroyLock(objectHeader->lock); | |
| 173 objectHeader->lock = NULL; | |
| 174 object = NULL; | |
| 175 | |
| 176 objectHeader->magicHeader = PKIX_MAGIC_HEADER_DESTROYED; | |
| 177 | |
| 178 #ifdef PKIX_OBJECT_LEAK_TEST | |
| 179 memset(objectHeader, 0xbf, systemClasses[PKIX_OBJECT_TYPE].typeObjectSiz
e); | |
| 180 #endif | |
| 181 | |
| 182 PKIX_FREE(objectHeader); | |
| 183 | |
| 184 cleanup: | |
| 185 #ifdef PKIX_OBJECT_LEAK_TEST | |
| 186 fatal: | |
| 187 #endif | |
| 188 | |
| 189 PKIX_RETURN(OBJECT); | |
| 190 } | |
| 191 | |
| 192 /* --Default-Callbacks-------------------------------------------- */ | |
| 193 | |
| 194 /* | |
| 195 * FUNCTION: pkix_pl_Object_Equals_Default | |
| 196 * DESCRIPTION: | |
| 197 * | |
| 198 * Default Object_Equals callback: Compares the address of the Object pointed | |
| 199 * to by "firstObject" with the address of the Object pointed to by | |
| 200 * "secondObject" and stores the Boolean result at "pResult". | |
| 201 * | |
| 202 * PARAMETERS: | |
| 203 * "firstObject" | |
| 204 * Address of first Object to compare. Must be non-NULL. | |
| 205 * "secondObject" | |
| 206 * Address of second Object to compare. Must be non-NULL. | |
| 207 * "pResult" | |
| 208 * Address where Boolean result will be stored. Must be non-NULL. | |
| 209 * "plContext" | |
| 210 * Platform-specific context pointer. | |
| 211 * THREAD SAFETY: | |
| 212 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 213 * RETURNS: | |
| 214 * Returns NULL if the function succeeds. | |
| 215 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 216 */ | |
| 217 static PKIX_Error * | |
| 218 pkix_pl_Object_Equals_Default( | |
| 219 PKIX_PL_Object *firstObject, | |
| 220 PKIX_PL_Object *secondObject, | |
| 221 PKIX_Boolean *pResult, | |
| 222 void *plContext) | |
| 223 { | |
| 224 PKIX_ENTER(OBJECT, "pkix_pl_Object_Equals_Default"); | |
| 225 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); | |
| 226 | |
| 227 /* Just compare pointer values */ | |
| 228 *pResult = (firstObject == secondObject)?PKIX_TRUE:PKIX_FALSE; | |
| 229 | |
| 230 PKIX_RETURN(OBJECT); | |
| 231 } | |
| 232 | |
| 233 /* | |
| 234 * FUNCTION: pkix_pl_Object_ToString_Default | |
| 235 * DESCRIPTION: | |
| 236 * | |
| 237 * Default Object_ToString callback: Creates a string consisting of the | |
| 238 * typename and address of the Object pointed to by "object" and stores | |
| 239 * the result at "pString". The format for the string is | |
| 240 * "TypeName@Address: <address>", where the default typename is "Object". | |
| 241 * | |
| 242 * PARAMETERS: | |
| 243 * "object" | |
| 244 * Address of Object to convert to a string. Must be non-NULL. | |
| 245 * "pString" | |
| 246 * Address where object pointer will be stored. Must be non-NULL. | |
| 247 * "plContext" | |
| 248 * Platform-specific context pointer. | |
| 249 * THREAD SAFETY: | |
| 250 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 251 * RETURNS: | |
| 252 * Returns NULL if the function succeeds. | |
| 253 * Returns an Object Error if the function fails in a non-fatal way. | |
| 254 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 255 */ | |
| 256 static PKIX_Error * | |
| 257 pkix_pl_Object_ToString_Default( | |
| 258 PKIX_PL_Object *object, | |
| 259 PKIX_PL_String **pString, | |
| 260 void *plContext) | |
| 261 { | |
| 262 PKIX_PL_String *formatString = NULL; | |
| 263 PKIX_PL_String *descString = NULL; | |
| 264 char *format = "%s@Address: %x"; | |
| 265 char *description = NULL; | |
| 266 PKIX_UInt32 objType; | |
| 267 | |
| 268 PKIX_ENTER(OBJECT, "pkix_pl_Object_ToString_Default"); | |
| 269 PKIX_NULLCHECK_TWO(object, pString); | |
| 270 | |
| 271 PKIX_CHECK(PKIX_PL_Object_GetType(object, &objType, plContext), | |
| 272 PKIX_OBJECTGETTYPEFAILED); | |
| 273 | |
| 274 if (objType >= PKIX_NUMTYPES){ | |
| 275 #ifdef PKIX_USER_OBJECT_TYPE | |
| 276 pkix_ClassTable_Entry *ctEntry = NULL; | |
| 277 | |
| 278 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
| 279 PR_Lock(classTableLock); | |
| 280 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
| 281 (classTable, | |
| 282 (void *)&objType, | |
| 283 objType, | |
| 284 NULL, | |
| 285 (void **)&ctEntry, | |
| 286 plContext); | |
| 287 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
| 288 PR_Unlock(classTableLock); | |
| 289 if (pkixErrorResult){ | |
| 290 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
| 291 } | |
| 292 | |
| 293 if (ctEntry == NULL){ | |
| 294 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCLASSTABLEENTRY); | |
| 295 } else { | |
| 296 description = ctEntry->description; | |
| 297 if (description == NULL) { | |
| 298 description = "User Type Object"; | |
| 299 } | |
| 300 } | |
| 301 #else | |
| 302 PORT_Assert (0); | |
| 303 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
| 304 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 305 goto cleanup; | |
| 306 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 307 } else { | |
| 308 description = systemClasses[objType].description; | |
| 309 } | |
| 310 PKIX_CHECK(PKIX_PL_String_Create | |
| 311 (PKIX_ESCASCII, | |
| 312 (void *)format, | |
| 313 0, | |
| 314 &formatString, | |
| 315 plContext), | |
| 316 PKIX_STRINGCREATEFAILED); | |
| 317 | |
| 318 PKIX_CHECK(PKIX_PL_String_Create | |
| 319 (PKIX_ESCASCII, | |
| 320 (void *)description, | |
| 321 0, | |
| 322 &descString, | |
| 323 plContext), | |
| 324 PKIX_STRINGCREATEFAILED); | |
| 325 | |
| 326 PKIX_CHECK(PKIX_PL_Sprintf | |
| 327 (pString, | |
| 328 plContext, | |
| 329 formatString, | |
| 330 descString, | |
| 331 object), | |
| 332 PKIX_SPRINTFFAILED); | |
| 333 | |
| 334 cleanup: | |
| 335 | |
| 336 PKIX_DECREF(formatString); | |
| 337 PKIX_DECREF(descString); | |
| 338 | |
| 339 PKIX_RETURN(OBJECT); | |
| 340 } | |
| 341 | |
| 342 /* | |
| 343 * FUNCTION: pkix_pl_Object_Hashcode_Default | |
| 344 * DESCRIPTION: | |
| 345 * | |
| 346 * Default Object_Hashcode callback. Creates the a hashcode value using the | |
| 347 * address of the Object pointed to by "object" and stores the result at | |
| 348 * "pValue". | |
| 349 * | |
| 350 * XXX This isn't great since addresses are not uniformly distributed. | |
| 351 * | |
| 352 * PARAMETERS: | |
| 353 * "object" | |
| 354 * Address of Object to compute hashcode for. Must be non-NULL. | |
| 355 * "pValue" | |
| 356 * Address where PKIX_UInt32 will be stored. Must be non-NULL. | |
| 357 * "plContext" | |
| 358 * Platform-specific context pointer. | |
| 359 * THREAD SAFETY: | |
| 360 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 361 * RETURNS: | |
| 362 * Returns NULL if the function succeeds. | |
| 363 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 364 */ | |
| 365 static PKIX_Error * | |
| 366 pkix_pl_Object_Hashcode_Default( | |
| 367 PKIX_PL_Object *object, | |
| 368 PKIX_UInt32 *pValue, | |
| 369 void *plContext) | |
| 370 { | |
| 371 PKIX_ENTER(OBJECT, "pkix_pl_Object_Hashcode_Default"); | |
| 372 PKIX_NULLCHECK_TWO(object, pValue); | |
| 373 | |
| 374 *pValue = (PKIX_UInt32)((char *)object - (char *)NULL); | |
| 375 | |
| 376 PKIX_RETURN(OBJECT); | |
| 377 } | |
| 378 | |
| 379 /* | |
| 380 * FUNCTION: pkix_pl_Object_RetrieveEqualsCallback | |
| 381 * DESCRIPTION: | |
| 382 * | |
| 383 * Retrieves Equals callback function of Object pointed to by "object and | |
| 384 * stores it at "pEqualsCallback". If the object's type is one of the system | |
| 385 * types, its callback function is retrieved from the systemClasses array; | |
| 386 * otherwise, its callback function is retrieve from the classTable hash | |
| 387 * table where user-defined types are stored. | |
| 388 * | |
| 389 * PARAMETERS: | |
| 390 * "object" | |
| 391 * Address of Object whose equals callback is desired. Must be non-NULL. | |
| 392 * "pEqualsCallback" | |
| 393 * Address where EqualsCallback function pointer will be stored. | |
| 394 * Must be non-NULL. | |
| 395 * "plContext" | |
| 396 * Platform-specific context pointer. | |
| 397 * THREAD SAFETY: | |
| 398 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 399 * RETURNS: | |
| 400 * Returns NULL if the function succeeds. | |
| 401 * Returns an Object Error if the function fails in a non-fatal way. | |
| 402 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 403 */ | |
| 404 PKIX_Error * | |
| 405 pkix_pl_Object_RetrieveEqualsCallback( | |
| 406 PKIX_PL_Object *object, | |
| 407 PKIX_PL_EqualsCallback *pEqualsCallback, | |
| 408 void *plContext) | |
| 409 { | |
| 410 PKIX_PL_Object *objectHeader = NULL; | |
| 411 PKIX_PL_EqualsCallback func = NULL; | |
| 412 pkix_ClassTable_Entry entry; | |
| 413 PKIX_UInt32 objType; | |
| 414 | |
| 415 PKIX_ENTER(OBJECT, "pkix_pl_Object_RetrieveEqualsCallback"); | |
| 416 PKIX_NULLCHECK_TWO(object, pEqualsCallback); | |
| 417 | |
| 418 PKIX_CHECK(pkix_pl_Object_GetHeader | |
| 419 (object, &objectHeader, plContext), | |
| 420 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 421 | |
| 422 objType = objectHeader->type; | |
| 423 | |
| 424 if (objType >= PKIX_NUMTYPES){ | |
| 425 #ifdef PKIX_USER_OBJECT_TYPE | |
| 426 pkix_ClassTable_Entry *ctEntry = NULL; | |
| 427 | |
| 428 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
| 429 PR_Lock(classTableLock); | |
| 430 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
| 431 (classTable, | |
| 432 (void *)&objType, | |
| 433 objType, | |
| 434 NULL, | |
| 435 (void **)&ctEntry, | |
| 436 plContext); | |
| 437 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
| 438 PR_Unlock(classTableLock); | |
| 439 if (pkixErrorResult){ | |
| 440 PKIX_ERROR(PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
| 441 } | |
| 442 | |
| 443 if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) { | |
| 444 PKIX_ERROR(PKIX_UNDEFINEDEQUALSCALLBACK); | |
| 445 } else { | |
| 446 *pEqualsCallback = ctEntry->equalsFunction; | |
| 447 } | |
| 448 #else | |
| 449 PORT_Assert (0); | |
| 450 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
| 451 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 452 goto cleanup; | |
| 453 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 454 } else { | |
| 455 entry = systemClasses[objType]; | |
| 456 func = entry.equalsFunction; | |
| 457 if (func == NULL){ | |
| 458 func = pkix_pl_Object_Equals_Default; | |
| 459 } | |
| 460 *pEqualsCallback = func; | |
| 461 } | |
| 462 | |
| 463 cleanup: | |
| 464 | |
| 465 PKIX_RETURN(OBJECT); | |
| 466 } | |
| 467 | |
| 468 /* | |
| 469 * FUNCTION: pkix_pl_Object_RegisterSelf | |
| 470 * DESCRIPTION: | |
| 471 * Registers PKIX_OBJECT_TYPE and its related functions with systemClasses[] | |
| 472 * THREAD SAFETY: | |
| 473 * Not Thread Safe - for performance and complexity reasons | |
| 474 * | |
| 475 * Since this function is only called by PKIX_PL_Initialize, which should | |
| 476 * only be called once, it is acceptable that this function is not | |
| 477 * thread-safe. | |
| 478 * | |
| 479 * PKIX_PL_Object should have all function pointes to be to NULL: they | |
| 480 * work as proxy function to a real objects. | |
| 481 * | |
| 482 */ | |
| 483 PKIX_Error * | |
| 484 pkix_pl_Object_RegisterSelf(void *plContext) | |
| 485 { | |
| 486 pkix_ClassTable_Entry entry; | |
| 487 | |
| 488 PKIX_ENTER(ERROR, "pkix_pl_Object_RegisterSelf"); | |
| 489 | |
| 490 entry.description = "Object"; | |
| 491 entry.objCounter = 0; | |
| 492 entry.typeObjectSize = sizeof(PKIX_PL_Object); | |
| 493 entry.destructor = NULL; | |
| 494 entry.equalsFunction = NULL; | |
| 495 entry.hashcodeFunction = NULL; | |
| 496 entry.toStringFunction = NULL; | |
| 497 entry.comparator = NULL; | |
| 498 entry.duplicateFunction = NULL; | |
| 499 | |
| 500 systemClasses[PKIX_OBJECT_TYPE] = entry; | |
| 501 | |
| 502 PKIX_RETURN(ERROR); | |
| 503 } | |
| 504 | |
| 505 /* --Public-Functions------------------------------------------------------- */ | |
| 506 | |
| 507 /* | |
| 508 * FUNCTION: PKIX_PL_Object_Alloc (see comments in pkix_pl_system.h) | |
| 509 */ | |
| 510 PKIX_Error * | |
| 511 PKIX_PL_Object_Alloc( | |
| 512 PKIX_TYPENUM objType, | |
| 513 PKIX_UInt32 size, | |
| 514 PKIX_PL_Object **pObject, | |
| 515 void *plContext) | |
| 516 { | |
| 517 PKIX_PL_Object *object = NULL; | |
| 518 pkix_ClassTable_Entry *ctEntry = NULL; | |
| 519 | |
| 520 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Alloc"); | |
| 521 PKIX_NULLCHECK_ONE(pObject); | |
| 522 | |
| 523 /* | |
| 524 * We need to ensure that user-defined types have been registered. | |
| 525 * All system types have already been registered by PKIX_PL_Initialize. | |
| 526 */ | |
| 527 | |
| 528 if (objType >= PKIX_NUMTYPES) { /* i.e. if this is a user-defined type *
/ | |
| 529 #ifdef PKIX_USER_OBJECT_TYPE | |
| 530 PKIX_Boolean typeRegistered; | |
| 531 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
| 532 PR_Lock(classTableLock); | |
| 533 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
| 534 (classTable, | |
| 535 (void *)&objType, | |
| 536 objType, | |
| 537 NULL, | |
| 538 (void **)&ctEntry, | |
| 539 plContext); | |
| 540 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
| 541 PR_Unlock(classTableLock); | |
| 542 if (pkixErrorResult){ | |
| 543 PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE); | |
| 544 } | |
| 545 | |
| 546 typeRegistered = (ctEntry != NULL); | |
| 547 | |
| 548 if (!typeRegistered) { | |
| 549 PKIX_ERROR_FATAL(PKIX_UNKNOWNTYPEARGUMENT); | |
| 550 } | |
| 551 #else | |
| 552 PORT_Assert (0); | |
| 553 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
| 554 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 555 goto cleanup; | |
| 556 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 557 } else { | |
| 558 ctEntry = &systemClasses[objType]; | |
| 559 } | |
| 560 | |
| 561 PORT_Assert(size == ctEntry->typeObjectSize); | |
| 562 | |
| 563 /* Allocate space for the object header and the requested size */ | |
| 564 #ifdef PKIX_OBJECT_LEAK_TEST | |
| 565 PKIX_CHECK(PKIX_PL_Calloc | |
| 566 (1, | |
| 567 ((PKIX_UInt32)sizeof (PKIX_PL_Object))+size, | |
| 568 (void **)&object, | |
| 569 plContext), | |
| 570 PKIX_MALLOCFAILED); | |
| 571 #else | |
| 572 PKIX_CHECK(PKIX_PL_Malloc | |
| 573 (((PKIX_UInt32)sizeof (PKIX_PL_Object))+size, | |
| 574 (void **)&object, | |
| 575 plContext), | |
| 576 PKIX_MALLOCFAILED); | |
| 577 #endif /* PKIX_OBJECT_LEAK_TEST */ | |
| 578 | |
| 579 /* Initialize all object fields */ | |
| 580 object->magicHeader = PKIX_MAGIC_HEADER; | |
| 581 object->type = objType; | |
| 582 object->references = 1; /* Default to a single reference */ | |
| 583 object->stringRep = NULL; | |
| 584 object->hashcode = 0; | |
| 585 object->hashcodeCached = 0; | |
| 586 | |
| 587 /* Cannot use PKIX_PL_Mutex because it depends on Object */ | |
| 588 /* Using NSPR Locks instead */ | |
| 589 PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n"); | |
| 590 object->lock = PR_NewLock(); | |
| 591 if (object->lock == NULL) { | |
| 592 PKIX_ERROR_ALLOC_ERROR(); | |
| 593 } | |
| 594 | |
| 595 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); | |
| 596 | |
| 597 | |
| 598 /* Return a pointer to the user data. Need to offset by object size */ | |
| 599 *pObject = object + 1; | |
| 600 object = NULL; | |
| 601 | |
| 602 /* Atomically increment object counter */ | |
| 603 PR_ATOMIC_INCREMENT((PRInt32*)&ctEntry->objCounter); | |
| 604 | |
| 605 cleanup: | |
| 606 | |
| 607 PKIX_FREE(object); | |
| 608 | |
| 609 PKIX_RETURN(OBJECT); | |
| 610 } | |
| 611 | |
| 612 /* | |
| 613 * FUNCTION: PKIX_PL_Object_IsTypeRegistered (see comments in pkix_pl_system.h) | |
| 614 */ | |
| 615 PKIX_Error * | |
| 616 PKIX_PL_Object_IsTypeRegistered( | |
| 617 PKIX_UInt32 objType, | |
| 618 PKIX_Boolean *pBool, | |
| 619 void *plContext) | |
| 620 { | |
| 621 #ifdef PKIX_USER_OBJECT_TYPE | |
| 622 pkix_ClassTable_Entry *ctEntry = NULL; | |
| 623 #endif | |
| 624 | |
| 625 PKIX_ENTER(OBJECT, "PKIX_PL_Object_IsTypeRegistered"); | |
| 626 PKIX_NULLCHECK_ONE(pBool); | |
| 627 | |
| 628 /* first, we handle the system types */ | |
| 629 if (objType < PKIX_NUMTYPES) { | |
| 630 *pBool = PKIX_TRUE; | |
| 631 goto cleanup; | |
| 632 } | |
| 633 | |
| 634 #ifndef PKIX_USER_OBJECT_TYPE | |
| 635 PORT_Assert (0); | |
| 636 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
| 637 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 638 #else | |
| 639 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
| 640 PR_Lock(classTableLock); | |
| 641 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
| 642 (classTable, | |
| 643 (void *)&objType, | |
| 644 objType, | |
| 645 NULL, | |
| 646 (void **)&ctEntry, | |
| 647 plContext); | |
| 648 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
| 649 PR_Unlock(classTableLock); | |
| 650 | |
| 651 if (pkixErrorResult){ | |
| 652 PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE); | |
| 653 } | |
| 654 | |
| 655 *pBool = (ctEntry != NULL); | |
| 656 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 657 | |
| 658 cleanup: | |
| 659 | |
| 660 PKIX_RETURN(OBJECT); | |
| 661 } | |
| 662 | |
| 663 #ifdef PKIX_USER_OBJECT_TYPE | |
| 664 /* | |
| 665 * FUNCTION: PKIX_PL_Object_RegisterType (see comments in pkix_pl_system.h) | |
| 666 */ | |
| 667 PKIX_Error * | |
| 668 PKIX_PL_Object_RegisterType( | |
| 669 PKIX_UInt32 objType, | |
| 670 char *description, | |
| 671 PKIX_PL_DestructorCallback destructor, | |
| 672 PKIX_PL_EqualsCallback equalsFunction, | |
| 673 PKIX_PL_HashcodeCallback hashcodeFunction, | |
| 674 PKIX_PL_ToStringCallback toStringFunction, | |
| 675 PKIX_PL_ComparatorCallback comparator, | |
| 676 PKIX_PL_DuplicateCallback duplicateFunction, | |
| 677 void *plContext) | |
| 678 { | |
| 679 pkix_ClassTable_Entry *ctEntry = NULL; | |
| 680 pkix_pl_Integer *key = NULL; | |
| 681 | |
| 682 PKIX_ENTER(OBJECT, "PKIX_PL_Object_RegisterType"); | |
| 683 | |
| 684 /* | |
| 685 * System types are registered on startup by PKIX_PL_Initialize. | |
| 686 * These can not be overwritten. | |
| 687 */ | |
| 688 | |
| 689 if (objType < PKIX_NUMTYPES) { /* if this is a system type */ | |
| 690 PKIX_ERROR(PKIX_CANTREREGISTERSYSTEMTYPE); | |
| 691 } | |
| 692 | |
| 693 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
| 694 PR_Lock(classTableLock); | |
| 695 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup | |
| 696 (classTable, | |
| 697 (void *)&objType, | |
| 698 objType, | |
| 699 NULL, | |
| 700 (void **)&ctEntry, | |
| 701 plContext), | |
| 702 PKIX_PRIMHASHTABLELOOKUPFAILED); | |
| 703 | |
| 704 /* If the type is already registered, throw an error */ | |
| 705 if (ctEntry) { | |
| 706 PKIX_ERROR(PKIX_TYPEALREADYREGISTERED); | |
| 707 } | |
| 708 | |
| 709 PKIX_CHECK(PKIX_PL_Malloc | |
| 710 (((PKIX_UInt32)sizeof (pkix_ClassTable_Entry)), | |
| 711 (void **)&ctEntry, | |
| 712 plContext), | |
| 713 PKIX_MALLOCFAILED); | |
| 714 | |
| 715 /* Set Default Values if none specified */ | |
| 716 | |
| 717 if (description == NULL){ | |
| 718 description = "Object"; | |
| 719 } | |
| 720 | |
| 721 if (equalsFunction == NULL) { | |
| 722 equalsFunction = pkix_pl_Object_Equals_Default; | |
| 723 } | |
| 724 | |
| 725 if (toStringFunction == NULL) { | |
| 726 toStringFunction = pkix_pl_Object_ToString_Default; | |
| 727 } | |
| 728 | |
| 729 if (hashcodeFunction == NULL) { | |
| 730 hashcodeFunction = pkix_pl_Object_Hashcode_Default; | |
| 731 } | |
| 732 | |
| 733 ctEntry->destructor = destructor; | |
| 734 ctEntry->equalsFunction = equalsFunction; | |
| 735 ctEntry->toStringFunction = toStringFunction; | |
| 736 ctEntry->hashcodeFunction = hashcodeFunction; | |
| 737 ctEntry->comparator = comparator; | |
| 738 ctEntry->duplicateFunction = duplicateFunction; | |
| 739 ctEntry->description = description; | |
| 740 | |
| 741 PKIX_CHECK(PKIX_PL_Malloc | |
| 742 (((PKIX_UInt32)sizeof (pkix_pl_Integer)), | |
| 743 (void **)&key, | |
| 744 plContext), | |
| 745 PKIX_COULDNOTMALLOCNEWKEY); | |
| 746 | |
| 747 key->ht_int = objType; | |
| 748 | |
| 749 PKIX_CHECK(pkix_pl_PrimHashTable_Add | |
| 750 (classTable, | |
| 751 (void *)key, | |
| 752 (void *)ctEntry, | |
| 753 objType, | |
| 754 NULL, | |
| 755 plContext), | |
| 756 PKIX_PRIMHASHTABLEADDFAILED); | |
| 757 | |
| 758 cleanup: | |
| 759 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
| 760 PR_Unlock(classTableLock); | |
| 761 | |
| 762 PKIX_RETURN(OBJECT); | |
| 763 } | |
| 764 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 765 | |
| 766 /* | |
| 767 * FUNCTION: PKIX_PL_Object_IncRef (see comments in pkix_pl_system.h) | |
| 768 */ | |
| 769 PKIX_Error * | |
| 770 PKIX_PL_Object_IncRef( | |
| 771 PKIX_PL_Object *object, | |
| 772 void *plContext) | |
| 773 { | |
| 774 PKIX_PL_Object *objectHeader = NULL; | |
| 775 PKIX_PL_NssContext *context = NULL; | |
| 776 PKIX_Int32 refCount = 0; | |
| 777 | |
| 778 PKIX_ENTER(OBJECT, "PKIX_PL_Object_IncRef"); | |
| 779 PKIX_NULLCHECK_ONE(object); | |
| 780 | |
| 781 if (plContext){ | |
| 782 /* | |
| 783 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't | |
| 784 * have a header therefore we cannot verify its type before | |
| 785 * casting. | |
| 786 */ | |
| 787 context = (PKIX_PL_NssContext *) plContext; | |
| 788 if (context->arena != NULL) { | |
| 789 goto cleanup; | |
| 790 } | |
| 791 } | |
| 792 | |
| 793 if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) { | |
| 794 goto cleanup; | |
| 795 } | |
| 796 | |
| 797 /* Shift pointer from user data to object header */ | |
| 798 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
| 799 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 800 | |
| 801 /* This object should never have zero references */ | |
| 802 refCount = PR_ATOMIC_INCREMENT(&objectHeader->references); | |
| 803 | |
| 804 if (refCount <= 1) { | |
| 805 PKIX_THROW(FATAL, PKIX_OBJECTWITHNONPOSITIVEREFERENCES); | |
| 806 } | |
| 807 | |
| 808 cleanup: | |
| 809 | |
| 810 PKIX_RETURN(OBJECT); | |
| 811 } | |
| 812 | |
| 813 /* | |
| 814 * FUNCTION: PKIX_PL_Object_DecRef (see comments in pkix_pl_system.h) | |
| 815 */ | |
| 816 PKIX_Error * | |
| 817 PKIX_PL_Object_DecRef( | |
| 818 PKIX_PL_Object *object, | |
| 819 void *plContext) | |
| 820 { | |
| 821 PKIX_Int32 refCount = 0; | |
| 822 PKIX_PL_Object *objectHeader = NULL; | |
| 823 PKIX_PL_NssContext *context = NULL; | |
| 824 | |
| 825 PKIX_ENTER(OBJECT, "PKIX_PL_Object_DecRef"); | |
| 826 PKIX_NULLCHECK_ONE(object); | |
| 827 | |
| 828 if (plContext){ | |
| 829 /* | |
| 830 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't | |
| 831 * have a header therefore we cannot verify its type before | |
| 832 * casting. | |
| 833 */ | |
| 834 context = (PKIX_PL_NssContext *) plContext; | |
| 835 if (context->arena != NULL) { | |
| 836 goto cleanup; | |
| 837 } | |
| 838 } | |
| 839 | |
| 840 if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) { | |
| 841 goto cleanup; | |
| 842 } | |
| 843 | |
| 844 /* Shift pointer from user data to object header */ | |
| 845 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
| 846 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 847 | |
| 848 refCount = PR_ATOMIC_DECREMENT(&objectHeader->references); | |
| 849 | |
| 850 if (refCount == 0) { | |
| 851 PKIX_PL_DestructorCallback destructor = NULL; | |
| 852 pkix_ClassTable_Entry *ctEntry = NULL; | |
| 853 PKIX_UInt32 objType = objectHeader->type; | |
| 854 | |
| 855 /* first, special handling for system types */ | |
| 856 if (objType >= PKIX_NUMTYPES){ | |
| 857 #ifdef PKIX_USER_OBJECT_TYPE | |
| 858 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
| 859 PR_Lock(classTableLock); | |
| 860 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
| 861 (classTable, | |
| 862 (void *)&objType, | |
| 863 objType, | |
| 864 NULL, | |
| 865 (void **)&ctEntry, | |
| 866 plContext); | |
| 867 PKIX_OBJECT_DEBUG | |
| 868 ("\tCalling PR_Unlock).\n"); | |
| 869 PR_Unlock(classTableLock); | |
| 870 if (pkixErrorResult){ | |
| 871 PKIX_ERROR_FATAL | |
| 872 (PKIX_ERRORINGETTINGDESTRUCTOR); | |
| 873 } | |
| 874 | |
| 875 if (ctEntry != NULL){ | |
| 876 destructor = ctEntry->destructor; | |
| 877 } | |
| 878 #else | |
| 879 PORT_Assert (0); | |
| 880 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
| 881 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 882 goto cleanup; | |
| 883 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 884 } else { | |
| 885 ctEntry = &systemClasses[objType]; | |
| 886 destructor = ctEntry->destructor; | |
| 887 } | |
| 888 | |
| 889 if (destructor != NULL){ | |
| 890 /* Call destructor on user data if necessary */ | |
| 891 pkixErrorResult = destructor(object, plContext); | |
| 892 if (pkixErrorResult) { | |
| 893 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 894 PKIX_DoAddError(stdVarsPtr, pkixErrorResult, plContext); | |
| 895 pkixErrorResult = NULL; | |
| 896 } | |
| 897 } | |
| 898 | |
| 899 /* Atomically decrement object counter */ | |
| 900 PR_ATOMIC_DECREMENT((PRInt32*)&ctEntry->objCounter); | |
| 901 | |
| 902 /* pkix_pl_Object_Destroy assumes the lock is held */ | |
| 903 /* It will call unlock and destroy the object */ | |
| 904 pkixErrorResult = pkix_pl_Object_Destroy(object, plContext); | |
| 905 goto cleanup; | |
| 906 } | |
| 907 | |
| 908 if (refCount < 0) { | |
| 909 PKIX_ERROR_ALLOC_ERROR(); | |
| 910 } | |
| 911 | |
| 912 cleanup: | |
| 913 | |
| 914 PKIX_RETURN(OBJECT); | |
| 915 } | |
| 916 | |
| 917 | |
| 918 | |
| 919 /* | |
| 920 * FUNCTION: PKIX_PL_Object_Equals (see comments in pkix_pl_system.h) | |
| 921 */ | |
| 922 PKIX_Error * | |
| 923 PKIX_PL_Object_Equals( | |
| 924 PKIX_PL_Object *firstObject, | |
| 925 PKIX_PL_Object *secondObject, | |
| 926 PKIX_Boolean *pResult, | |
| 927 void *plContext) | |
| 928 { | |
| 929 PKIX_PL_Object *firstObjectHeader = NULL; | |
| 930 PKIX_PL_Object *secondObjectHeader = NULL; | |
| 931 PKIX_PL_EqualsCallback func = NULL; | |
| 932 pkix_ClassTable_Entry entry; | |
| 933 PKIX_UInt32 objType; | |
| 934 | |
| 935 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Equals"); | |
| 936 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); | |
| 937 | |
| 938 PKIX_CHECK(pkix_pl_Object_GetHeader | |
| 939 (firstObject, &firstObjectHeader, plContext), | |
| 940 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 941 | |
| 942 PKIX_CHECK(pkix_pl_Object_GetHeader | |
| 943 (secondObject, &secondObjectHeader, plContext), | |
| 944 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 945 | |
| 946 /* if hashcodes are cached but not equal, objects can't be equal */ | |
| 947 if (firstObjectHeader->hashcodeCached && | |
| 948 secondObjectHeader->hashcodeCached){ | |
| 949 if (firstObjectHeader->hashcode != | |
| 950 secondObjectHeader->hashcode){ | |
| 951 *pResult = PKIX_FALSE; | |
| 952 goto cleanup; | |
| 953 } | |
| 954 } | |
| 955 | |
| 956 objType = firstObjectHeader->type; | |
| 957 | |
| 958 if (objType >= PKIX_NUMTYPES) { | |
| 959 #ifdef PKIX_USER_OBJECT_TYPE | |
| 960 pkix_ClassTable_Entry *ctEntry = NULL; | |
| 961 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
| 962 PR_Lock(classTableLock); | |
| 963 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
| 964 (classTable, | |
| 965 (void *)&firstObjectHeader->type, | |
| 966 firstObjectHeader->type, | |
| 967 NULL, | |
| 968 (void **)&ctEntry, | |
| 969 plContext); | |
| 970 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
| 971 PR_Unlock(classTableLock); | |
| 972 | |
| 973 if (pkixErrorResult){ | |
| 974 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
| 975 } | |
| 976 | |
| 977 if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) { | |
| 978 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); | |
| 979 } else { | |
| 980 func = ctEntry->equalsFunction; | |
| 981 } | |
| 982 #else | |
| 983 PORT_Assert (0); | |
| 984 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
| 985 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 986 goto cleanup; | |
| 987 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 988 } else { | |
| 989 entry = systemClasses[objType]; | |
| 990 func = entry.equalsFunction; | |
| 991 if (func == NULL){ | |
| 992 func = pkix_pl_Object_Equals_Default; | |
| 993 } | |
| 994 } | |
| 995 | |
| 996 PKIX_CHECK(func(firstObject, secondObject, pResult, plContext), | |
| 997 PKIX_OBJECTSPECIFICFUNCTIONFAILED); | |
| 998 | |
| 999 cleanup: | |
| 1000 | |
| 1001 PKIX_RETURN(OBJECT); | |
| 1002 } | |
| 1003 | |
| 1004 /* | |
| 1005 * FUNCTION: PKIX_PL_Object_Duplicate (see comments in pkix_pl_system.h) | |
| 1006 */ | |
| 1007 PKIX_Error * | |
| 1008 PKIX_PL_Object_Duplicate( | |
| 1009 PKIX_PL_Object *firstObject, | |
| 1010 PKIX_PL_Object **pNewObject, | |
| 1011 void *plContext) | |
| 1012 { | |
| 1013 PKIX_PL_Object *firstObjectHeader = NULL; | |
| 1014 PKIX_PL_DuplicateCallback func = NULL; | |
| 1015 pkix_ClassTable_Entry entry; | |
| 1016 PKIX_UInt32 objType; | |
| 1017 | |
| 1018 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Duplicate"); | |
| 1019 PKIX_NULLCHECK_TWO(firstObject, pNewObject); | |
| 1020 | |
| 1021 PKIX_CHECK(pkix_pl_Object_GetHeader | |
| 1022 (firstObject, &firstObjectHeader, plContext), | |
| 1023 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 1024 | |
| 1025 objType = firstObjectHeader->type; | |
| 1026 | |
| 1027 if (objType >= PKIX_NUMTYPES) { | |
| 1028 #ifdef PKIX_USER_OBJECT_TYPE | |
| 1029 pkix_ClassTable_Entry *ctEntry = NULL; | |
| 1030 | |
| 1031 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
| 1032 PR_Lock(classTableLock); | |
| 1033 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
| 1034 (classTable, | |
| 1035 (void *)&objType, | |
| 1036 objType, | |
| 1037 NULL, | |
| 1038 (void **)&ctEntry, | |
| 1039 plContext); | |
| 1040 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
| 1041 PR_Unlock(classTableLock); | |
| 1042 | |
| 1043 if (pkixErrorResult){ | |
| 1044 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
| 1045 } | |
| 1046 | |
| 1047 if ((ctEntry == NULL) || (ctEntry->duplicateFunction == NULL)) { | |
| 1048 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); | |
| 1049 } else { | |
| 1050 func = ctEntry->duplicateFunction; | |
| 1051 } | |
| 1052 #else | |
| 1053 PORT_Assert (0); | |
| 1054 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
| 1055 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 1056 goto cleanup; | |
| 1057 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 1058 } else { | |
| 1059 entry = systemClasses[objType]; | |
| 1060 func = entry.duplicateFunction; | |
| 1061 if (!func){ | |
| 1062 PKIX_ERROR_FATAL(PKIX_UNDEFINEDDUPLICATEFUNCTION); | |
| 1063 } | |
| 1064 } | |
| 1065 | |
| 1066 PKIX_CHECK(func(firstObject, pNewObject, plContext), | |
| 1067 PKIX_OBJECTSPECIFICFUNCTIONFAILED); | |
| 1068 | |
| 1069 cleanup: | |
| 1070 | |
| 1071 PKIX_RETURN(OBJECT); | |
| 1072 } | |
| 1073 | |
| 1074 /* | |
| 1075 * FUNCTION: PKIX_PL_Object_Hashcode (see comments in pkix_pl_system.h) | |
| 1076 */ | |
| 1077 PKIX_Error * | |
| 1078 PKIX_PL_Object_Hashcode( | |
| 1079 PKIX_PL_Object *object, | |
| 1080 PKIX_UInt32 *pValue, | |
| 1081 void *plContext) | |
| 1082 { | |
| 1083 PKIX_PL_Object *objectHeader = NULL; | |
| 1084 PKIX_PL_HashcodeCallback func = NULL; | |
| 1085 pkix_ClassTable_Entry entry; | |
| 1086 PKIX_UInt32 objectHash; | |
| 1087 | |
| 1088 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Hashcode"); | |
| 1089 PKIX_NULLCHECK_TWO(object, pValue); | |
| 1090 | |
| 1091 /* Shift pointer from user data to object header */ | |
| 1092 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
| 1093 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 1094 | |
| 1095 /* if we don't have a cached copy from before, we create one */ | |
| 1096 if (!objectHeader->hashcodeCached){ | |
| 1097 | |
| 1098 PKIX_UInt32 objType = objectHeader->type; | |
| 1099 | |
| 1100 /* first, special handling for system types */ | |
| 1101 if (objType >= PKIX_NUMTYPES){ | |
| 1102 #ifdef PKIX_USER_OBJECT_TYPE | |
| 1103 pkix_ClassTable_Entry *ctEntry = NULL; | |
| 1104 | |
| 1105 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
| 1106 PR_Lock(classTableLock); | |
| 1107 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
| 1108 (classTable, | |
| 1109 (void *)&objType, | |
| 1110 objType, | |
| 1111 NULL, | |
| 1112 (void **)&ctEntry, | |
| 1113 plContext); | |
| 1114 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
| 1115 PR_Unlock(classTableLock); | |
| 1116 | |
| 1117 if (pkixErrorResult){ | |
| 1118 PKIX_ERROR_FATAL | |
| 1119 (PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
| 1120 } | |
| 1121 | |
| 1122 if ((ctEntry == NULL) || | |
| 1123 (ctEntry->hashcodeFunction == NULL)) { | |
| 1124 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); | |
| 1125 } | |
| 1126 | |
| 1127 func = ctEntry->hashcodeFunction; | |
| 1128 #else | |
| 1129 PORT_Assert (0); | |
| 1130 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
| 1131 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 1132 goto cleanup; | |
| 1133 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 1134 } else { | |
| 1135 entry = systemClasses[objType]; | |
| 1136 func = entry.hashcodeFunction; | |
| 1137 if (func == NULL){ | |
| 1138 func = pkix_pl_Object_Hashcode_Default; | |
| 1139 } | |
| 1140 } | |
| 1141 | |
| 1142 PKIX_CHECK(func(object, &objectHash, plContext), | |
| 1143 PKIX_OBJECTSPECIFICFUNCTIONFAILED); | |
| 1144 | |
| 1145 if (!objectHeader->hashcodeCached){ | |
| 1146 | |
| 1147 PKIX_CHECK(pkix_LockObject(object, plContext), | |
| 1148 PKIX_ERRORLOCKINGOBJECT); | |
| 1149 | |
| 1150 if (!objectHeader->hashcodeCached){ | |
| 1151 /* save cached copy in case we need it again */ | |
| 1152 objectHeader->hashcode = objectHash; | |
| 1153 objectHeader->hashcodeCached = PKIX_TRUE; | |
| 1154 } | |
| 1155 | |
| 1156 PKIX_CHECK(pkix_UnlockObject(object, plContext), | |
| 1157 PKIX_ERRORUNLOCKINGOBJECT); | |
| 1158 } | |
| 1159 } | |
| 1160 | |
| 1161 *pValue = objectHeader->hashcode; | |
| 1162 | |
| 1163 cleanup: | |
| 1164 | |
| 1165 PKIX_RETURN(OBJECT); | |
| 1166 } | |
| 1167 | |
| 1168 /* | |
| 1169 * FUNCTION: PKIX_PL_Object_ToString (see comments in pkix_pl_system.h) | |
| 1170 */ | |
| 1171 PKIX_Error * | |
| 1172 PKIX_PL_Object_ToString( | |
| 1173 PKIX_PL_Object *object, | |
| 1174 PKIX_PL_String **pString, | |
| 1175 void *plContext) | |
| 1176 { | |
| 1177 PKIX_PL_Object *objectHeader = NULL; | |
| 1178 PKIX_PL_ToStringCallback func = NULL; | |
| 1179 pkix_ClassTable_Entry entry; | |
| 1180 PKIX_PL_String *objectString = NULL; | |
| 1181 | |
| 1182 PKIX_ENTER(OBJECT, "PKIX_PL_Object_ToString"); | |
| 1183 PKIX_NULLCHECK_TWO(object, pString); | |
| 1184 | |
| 1185 /* Shift pointer from user data to object header */ | |
| 1186 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
| 1187 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 1188 | |
| 1189 /* if we don't have a cached copy from before, we create one */ | |
| 1190 if (!objectHeader->stringRep){ | |
| 1191 | |
| 1192 PKIX_UInt32 objType = objectHeader->type; | |
| 1193 | |
| 1194 if (objType >= PKIX_NUMTYPES){ | |
| 1195 #ifdef PKIX_USER_OBJECT_TYPE | |
| 1196 pkix_ClassTable_Entry *ctEntry = NULL; | |
| 1197 | |
| 1198 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
| 1199 PR_Lock(classTableLock); | |
| 1200 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
| 1201 (classTable, | |
| 1202 (void *)&objType, | |
| 1203 objType, | |
| 1204 NULL, | |
| 1205 (void **)&ctEntry, | |
| 1206 plContext); | |
| 1207 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
| 1208 PR_Unlock(classTableLock); | |
| 1209 if (pkixErrorResult){ | |
| 1210 PKIX_ERROR_FATAL | |
| 1211 (PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
| 1212 } | |
| 1213 | |
| 1214 if ((ctEntry == NULL) || | |
| 1215 (ctEntry->toStringFunction == NULL)) { | |
| 1216 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); | |
| 1217 } | |
| 1218 | |
| 1219 func = ctEntry->toStringFunction; | |
| 1220 #else | |
| 1221 PORT_Assert (0); | |
| 1222 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
| 1223 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 1224 goto cleanup; | |
| 1225 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 1226 } else { | |
| 1227 entry = systemClasses[objType]; | |
| 1228 func = entry.toStringFunction; | |
| 1229 if (func == NULL){ | |
| 1230 func = pkix_pl_Object_ToString_Default; | |
| 1231 } | |
| 1232 } | |
| 1233 | |
| 1234 PKIX_CHECK(func(object, &objectString, plContext), | |
| 1235 PKIX_OBJECTSPECIFICFUNCTIONFAILED); | |
| 1236 | |
| 1237 if (!objectHeader->stringRep){ | |
| 1238 | |
| 1239 PKIX_CHECK(pkix_LockObject(object, plContext), | |
| 1240 PKIX_ERRORLOCKINGOBJECT); | |
| 1241 | |
| 1242 if (!objectHeader->stringRep){ | |
| 1243 /* save a cached copy */ | |
| 1244 objectHeader->stringRep = objectString; | |
| 1245 objectString = NULL; | |
| 1246 } | |
| 1247 | |
| 1248 PKIX_CHECK(pkix_UnlockObject(object, plContext), | |
| 1249 PKIX_ERRORUNLOCKINGOBJECT); | |
| 1250 } | |
| 1251 } | |
| 1252 | |
| 1253 | |
| 1254 *pString = objectHeader->stringRep; | |
| 1255 objectHeader->stringRep = NULL; | |
| 1256 | |
| 1257 cleanup: | |
| 1258 if (objectHeader) { | |
| 1259 PKIX_DECREF(objectHeader->stringRep); | |
| 1260 } | |
| 1261 PKIX_DECREF(objectString); | |
| 1262 | |
| 1263 PKIX_RETURN(OBJECT); | |
| 1264 } | |
| 1265 | |
| 1266 /* | |
| 1267 * FUNCTION: PKIX_PL_Object_InvalidateCache (see comments in pkix_pl_system.h) | |
| 1268 */ | |
| 1269 PKIX_Error * | |
| 1270 PKIX_PL_Object_InvalidateCache( | |
| 1271 PKIX_PL_Object *object, | |
| 1272 void *plContext) | |
| 1273 { | |
| 1274 PKIX_PL_Object *objectHeader = NULL; | |
| 1275 | |
| 1276 PKIX_ENTER(OBJECT, "PKIX_PL_Object_InvalidateCache"); | |
| 1277 PKIX_NULLCHECK_ONE(object); | |
| 1278 | |
| 1279 /* Shift pointer from user data to object header */ | |
| 1280 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
| 1281 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 1282 | |
| 1283 PKIX_CHECK(pkix_LockObject(object, plContext), | |
| 1284 PKIX_ERRORLOCKINGOBJECT); | |
| 1285 | |
| 1286 /* invalidate hashcode */ | |
| 1287 objectHeader->hashcode = 0; | |
| 1288 objectHeader->hashcodeCached = PKIX_FALSE; | |
| 1289 | |
| 1290 PKIX_DECREF(objectHeader->stringRep); | |
| 1291 | |
| 1292 PKIX_CHECK(pkix_UnlockObject(object, plContext), | |
| 1293 PKIX_ERRORUNLOCKINGOBJECT); | |
| 1294 | |
| 1295 cleanup: | |
| 1296 | |
| 1297 PKIX_RETURN(OBJECT); | |
| 1298 } | |
| 1299 | |
| 1300 /* | |
| 1301 * FUNCTION: PKIX_PL_Object_Compare (see comments in pkix_pl_system.h) | |
| 1302 */ | |
| 1303 PKIX_Error * | |
| 1304 PKIX_PL_Object_Compare( | |
| 1305 PKIX_PL_Object *firstObject, | |
| 1306 PKIX_PL_Object *secondObject, | |
| 1307 PKIX_Int32 *pResult, | |
| 1308 void *plContext) | |
| 1309 { | |
| 1310 PKIX_PL_Object *firstObjectHeader = NULL; | |
| 1311 PKIX_PL_Object *secondObjectHeader = NULL; | |
| 1312 PKIX_PL_ComparatorCallback func = NULL; | |
| 1313 pkix_ClassTable_Entry entry; | |
| 1314 PKIX_UInt32 objType; | |
| 1315 | |
| 1316 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Compare"); | |
| 1317 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); | |
| 1318 | |
| 1319 /* Shift pointer from user data to object header */ | |
| 1320 PKIX_CHECK(pkix_pl_Object_GetHeader | |
| 1321 (firstObject, &firstObjectHeader, plContext), | |
| 1322 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 1323 | |
| 1324 /* Shift pointer from user data to object header */ | |
| 1325 PKIX_CHECK(pkix_pl_Object_GetHeader | |
| 1326 (secondObject, &secondObjectHeader, plContext), | |
| 1327 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 1328 | |
| 1329 objType = firstObjectHeader->type; | |
| 1330 | |
| 1331 if (objType >= PKIX_NUMTYPES){ | |
| 1332 #ifdef PKIX_USER_OBJECT_TYPE | |
| 1333 pkix_ClassTable_Entry *ctEntry = NULL; | |
| 1334 | |
| 1335 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
| 1336 PR_Lock(classTableLock); | |
| 1337 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
| 1338 (classTable, | |
| 1339 (void *)&objType, | |
| 1340 objType, | |
| 1341 NULL, | |
| 1342 (void **)&ctEntry, | |
| 1343 plContext); | |
| 1344 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
| 1345 PR_Unlock(classTableLock); | |
| 1346 if (pkixErrorResult){ | |
| 1347 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
| 1348 } | |
| 1349 | |
| 1350 if ((ctEntry == NULL) || (ctEntry->comparator == NULL)) { | |
| 1351 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCOMPARATOR); | |
| 1352 } | |
| 1353 | |
| 1354 func = ctEntry->comparator; | |
| 1355 #else | |
| 1356 PORT_Assert (0); | |
| 1357 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
| 1358 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 1359 goto cleanup; | |
| 1360 #endif /* PKIX_USER_OBJECT_TYPE */ | |
| 1361 } else { | |
| 1362 /* special handling for system types */ | |
| 1363 entry = systemClasses[objType]; | |
| 1364 func = entry.comparator; | |
| 1365 if (!func){ | |
| 1366 PKIX_ERROR(PKIX_UNDEFINEDCOMPARATOR); | |
| 1367 } | |
| 1368 } | |
| 1369 | |
| 1370 PKIX_CHECK(func(firstObject, secondObject, pResult, plContext), | |
| 1371 PKIX_OBJECTSPECIFICFUNCTIONFAILED); | |
| 1372 | |
| 1373 cleanup: | |
| 1374 | |
| 1375 PKIX_RETURN(OBJECT); | |
| 1376 } | |
| 1377 | |
| 1378 /* | |
| 1379 * FUNCTION: PKIX_PL_Object_Lock (see comments in pkix_pl_system.h) | |
| 1380 */ | |
| 1381 PKIX_Error * | |
| 1382 PKIX_PL_Object_Lock( | |
| 1383 PKIX_PL_Object *object, | |
| 1384 void *plContext) | |
| 1385 { | |
| 1386 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Lock"); | |
| 1387 PKIX_NULLCHECK_ONE(object); | |
| 1388 | |
| 1389 PKIX_CHECK(pkix_LockObject(object, plContext), | |
| 1390 PKIX_LOCKOBJECTFAILED); | |
| 1391 | |
| 1392 cleanup: | |
| 1393 | |
| 1394 PKIX_RETURN(OBJECT); | |
| 1395 } | |
| 1396 | |
| 1397 /* | |
| 1398 * FUNCTION: PKIX_PL_Object_Unlock (see comments in pkix_pl_system.h) | |
| 1399 */ | |
| 1400 PKIX_Error * | |
| 1401 PKIX_PL_Object_Unlock( | |
| 1402 PKIX_PL_Object *object, | |
| 1403 void *plContext) | |
| 1404 { | |
| 1405 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Unlock"); | |
| 1406 PKIX_NULLCHECK_ONE(object); | |
| 1407 | |
| 1408 PKIX_CHECK(pkix_UnlockObject(object, plContext), | |
| 1409 PKIX_UNLOCKOBJECTFAILED); | |
| 1410 | |
| 1411 cleanup: | |
| 1412 | |
| 1413 PKIX_RETURN(OBJECT); | |
| 1414 } | |
| 1415 | |
| 1416 | |
| 1417 /* | |
| 1418 * FUNCTION: PKIX_PL_Object_GetType (see comments in pkix_pl_system.h) | |
| 1419 */ | |
| 1420 PKIX_Error * | |
| 1421 PKIX_PL_Object_GetType( | |
| 1422 PKIX_PL_Object *object, | |
| 1423 PKIX_UInt32 *pType, | |
| 1424 void *plContext) | |
| 1425 { | |
| 1426 PKIX_PL_Object *objectHeader = NULL; | |
| 1427 | |
| 1428 PKIX_ENTER(OBJECT, "PKIX_PL_Object_GetType"); | |
| 1429 PKIX_NULLCHECK_TWO(object, pType); | |
| 1430 | |
| 1431 /* Shift pointer from user data to object header */ | |
| 1432 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
| 1433 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
| 1434 | |
| 1435 *pType = objectHeader->type; | |
| 1436 | |
| 1437 cleanup: | |
| 1438 | |
| 1439 PKIX_RETURN(OBJECT); | |
| 1440 } | |
| OLD | NEW |