Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/libpkix/pkix/util/pkix_logger.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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_logger.c | |
6 * | |
7 * Logger Object Functions | |
8 * | |
9 */ | |
10 | |
11 #include "pkix_logger.h" | |
12 #ifndef PKIX_ERROR_DESCRIPTION | |
13 #include "prprf.h" | |
14 #endif | |
15 | |
16 /* Global variable to keep PKIX_Logger List */ | |
17 PKIX_List *pkixLoggers = NULL; | |
18 | |
19 /* | |
20 * Once the Logger has been set, for any logging related operations, we have | |
21 * to go through the List to find a match, and if found, issue the | |
22 * corresponding callback. The overhead to check for DEBUG and TRACE in each | |
23 * PKIX function entering and exiting is very expensive (400X), and redundant | |
24 * if they are not the interest of the Logger. Therefore, the PKIX_Logger List | |
25 * pkixLoggers is separated into two lists based on its Loggers' trace level. | |
26 * | |
27 * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or | |
28 * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors | |
29 * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and | |
30 * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to | |
31 * pkixLoggersDebugTrace. | |
32 * | |
33 * Currently we provide five logging levels and the default setting are by: | |
34 * | |
35 * PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level | |
36 * PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level | |
37 * WARNING is not invoked as default | |
38 * PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs | |
39 * compilation -DPKIX_<component>DEBUG flag to turn on | |
40 * PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE | |
41 * level. TRACE provides duplicate information of DEBUG, but needs no | |
42 * recompilation and cannot choose component. To allow application | |
43 * to use DEBUG level, TRACE is put as last. | |
44 * | |
45 */ | |
46 PKIX_List *pkixLoggersErrors = NULL; | |
47 PKIX_List *pkixLoggersDebugTrace = NULL; | |
48 | |
49 /* To ensure atomic update on pkixLoggers lists */ | |
50 PKIX_PL_MonitorLock *pkixLoggerLock = NULL; | |
51 | |
52 /* --Private-Functions-------------------------------------------- */ | |
53 | |
54 /* | |
55 * FUNCTION: pkix_Logger_CheckErrors | |
56 * DESCRIPTION: | |
57 * | |
58 * This function goes through each PKIX_Logger at "pkixLoggersList" and | |
59 * checks if "maxLevel" and "logComponent" satisfies what is specified in the | |
60 * PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and | |
61 * passes a PKIX_PL_String that is the concatenation of "message" and | |
62 * "message2" to the application for processing. | |
63 * Since this call is inserted into a handful of PKIX macros, no macros are | |
64 * applied in this function, to avoid infinite recursion. | |
65 * If an error occurs, this call is aborted. | |
66 * | |
67 * PARAMETERS: | |
68 * "pkixLoggersList" | |
69 * A list of PKIX_Loggers to be examined for invoking callback. Must be | |
70 * non-NULL. | |
71 * "message" | |
72 * Address of "message" to be logged. Must be non-NULL. | |
73 * "message2" | |
74 * Address of "message2" to be concatenated and logged. May be NULL. | |
75 * "logComponent" | |
76 * A PKIX_UInt32 that indicates the component the message is from. | |
77 * "maxLevel" | |
78 * A PKIX_UInt32 that represents the level of severity of the message. | |
79 * "plContext" | |
80 * Platform-specific context pointer. | |
81 * THREAD SAFETY: | |
82 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
83 * RETURNS: | |
84 * Returns NULL if the function succeeds | |
85 * Returns a Fatal Error if the function fails in an unrecoverable way | |
86 */ | |
87 PKIX_Error * | |
88 pkix_Logger_Check( | |
89 PKIX_List *pkixLoggersList, | |
90 const char *message, | |
91 const char *message2, | |
92 PKIX_ERRORCLASS logComponent, | |
93 PKIX_UInt32 currentLevel, | |
94 void *plContext) | |
95 { | |
96 PKIX_Logger *logger = NULL; | |
97 PKIX_List *savedPkixLoggersErrors = NULL; | |
98 PKIX_List *savedPkixLoggersDebugTrace = NULL; | |
99 PKIX_PL_String *formatString = NULL; | |
100 PKIX_PL_String *messageString = NULL; | |
101 PKIX_PL_String *message2String = NULL; | |
102 PKIX_PL_String *msgString = NULL; | |
103 PKIX_Error *error = NULL; | |
104 PKIX_Boolean needLogging = PKIX_FALSE; | |
105 PKIX_UInt32 i, length; | |
106 | |
107 /* | |
108 * We cannot use any the PKIX_ macros here, since this function is | |
109 * called from some of these macros. It can create infinite recursion. | |
110 */ | |
111 | |
112 if ((pkixLoggersList == NULL) || (message == NULL)) { | |
113 return(NULL); | |
114 } | |
115 | |
116 /* | |
117 * Disable all subsequent loggings to avoid recursion. The result is | |
118 * if other thread is calling this function at the same time, there | |
119 * won't be any logging because the pkixLoggersErrors and | |
120 * pkixLoggersDebugTrace are set to null. | |
121 * It would be nice if we provide control per thread (e.g. make | |
122 * plContext threadable) then we can avoid the recursion by setting | |
123 * flag at plContext. Then other thread's logging won't be affected. | |
124 * | |
125 * Also we need to use a reentrant Lock. Although we avoid recursion | |
126 * for TRACE. When there is an ERROR occurs in subsequent call, this | |
127 * function will be called. | |
128 */ | |
129 | |
130 error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext); | |
131 if (error) { return(NULL); } | |
132 | |
133 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; | |
134 pkixLoggersDebugTrace = NULL; | |
135 savedPkixLoggersErrors = pkixLoggersErrors; | |
136 pkixLoggersErrors = NULL; | |
137 | |
138 /* Convert message and message2 to String */ | |
139 error = PKIX_PL_String_Create | |
140 (PKIX_ESCASCII, message, 0, &messageString, plContext); | |
141 if (error) { goto cleanup; } | |
142 | |
143 if (message2) { | |
144 error = PKIX_PL_String_Create | |
145 (PKIX_ESCASCII, message2, 0, &message2String, plContext); | |
146 if (error) { goto cleanup; } | |
147 error = PKIX_PL_String_Create | |
148 (PKIX_ESCASCII, "%s %s", 0, &formatString, plContext); | |
149 if (error) { goto cleanup; } | |
150 | |
151 } else { | |
152 error = PKIX_PL_String_Create | |
153 (PKIX_ESCASCII, "%s", 0, &formatString, plContext); | |
154 if (error) { goto cleanup; } | |
155 | |
156 } | |
157 | |
158 error = PKIX_PL_Sprintf | |
159 (&msgString, | |
160 plContext, | |
161 formatString, | |
162 messageString, | |
163 message2String); | |
164 if (error) { goto cleanup; } | |
165 | |
166 /* Go through the Logger list */ | |
167 | |
168 error = PKIX_List_GetLength(pkixLoggersList, &length, plContext); | |
169 if (error) { goto cleanup; } | |
170 | |
171 for (i = 0; i < length; i++) { | |
172 | |
173 error = PKIX_List_GetItem | |
174 (pkixLoggersList, | |
175 i, | |
176 (PKIX_PL_Object **) &logger, | |
177 plContext); | |
178 if (error) { goto cleanup; } | |
179 | |
180 /* Intended logging level less or equal than the max */ | |
181 needLogging = (currentLevel <= logger->maxLevel); | |
182 | |
183 if (needLogging && (logger->callback)) { | |
184 | |
185 /* | |
186 * We separate Logger into two lists based on log level | |
187 * but log level is not modified. We need to check here to | |
188 * avoid logging the higher log level (lower value) twice. | |
189 */ | |
190 if (pkixLoggersList == pkixLoggersErrors) { | |
191 needLogging = needLogging && | |
192 (currentLevel <= PKIX_LOGGER_LEVEL_WARNING); | |
193 } else if (pkixLoggersList == pkixLoggersDebugTrace) { | |
194 needLogging = needLogging && | |
195 (currentLevel > PKIX_LOGGER_LEVEL_WARNING); | |
196 } | |
197 | |
198 if (needLogging) { | |
199 if (logComponent == logger->logComponent) { | |
200 needLogging = PKIX_TRUE; | |
201 } else { | |
202 needLogging = PKIX_FALSE; | |
203 } | |
204 } | |
205 | |
206 if (needLogging) { | |
207 error = logger->callback | |
208 (logger, | |
209 msgString, | |
210 currentLevel, | |
211 logComponent, | |
212 plContext); | |
213 if (error) { goto cleanup; } | |
214 } | |
215 } | |
216 | |
217 error = PKIX_PL_Object_DecRef | |
218 ((PKIX_PL_Object *)logger, plContext); | |
219 logger = NULL; | |
220 if (error) { goto cleanup; } | |
221 | |
222 } | |
223 | |
224 cleanup: | |
225 | |
226 if (formatString) { | |
227 error = PKIX_PL_Object_DecRef | |
228 ((PKIX_PL_Object *)formatString, plContext); | |
229 } | |
230 | |
231 if (messageString) { | |
232 error = PKIX_PL_Object_DecRef | |
233 ((PKIX_PL_Object *)messageString, plContext); | |
234 } | |
235 | |
236 if (message2String) { | |
237 error = PKIX_PL_Object_DecRef | |
238 ((PKIX_PL_Object *)message2String, plContext); | |
239 } | |
240 | |
241 if (msgString) { | |
242 error = PKIX_PL_Object_DecRef | |
243 ((PKIX_PL_Object *)msgString, plContext); | |
244 } | |
245 | |
246 if (logger) { | |
247 error = PKIX_PL_Object_DecRef | |
248 ((PKIX_PL_Object *)logger, plContext); | |
249 } | |
250 | |
251 if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) { | |
252 pkixLoggersErrors = savedPkixLoggersErrors; | |
253 } | |
254 | |
255 if (pkixLoggersDebugTrace == NULL && | |
256 savedPkixLoggersDebugTrace != NULL) { | |
257 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; | |
258 } | |
259 | |
260 error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext); | |
261 if (error) { return(NULL); } | |
262 | |
263 return(NULL); | |
264 } | |
265 | |
266 PKIX_Error * | |
267 pkix_Logger_CheckWithCode( | |
268 PKIX_List *pkixLoggersList, | |
269 PKIX_UInt32 errorCode, | |
270 const char *message2, | |
271 PKIX_ERRORCLASS logComponent, | |
272 PKIX_UInt32 currentLevel, | |
273 void *plContext) | |
274 { | |
275 char error[32]; | |
276 char *errorString = NULL; | |
277 | |
278 PKIX_ENTER(LOGGER, "pkix_Logger_CheckWithCode"); | |
279 #if defined PKIX_ERROR_DESCRIPTION | |
280 errorString = PKIX_ErrorText[errorCode]; | |
281 #else | |
282 PR_snprintf(error, 32, "Error code: %d", errorCode); | |
283 errorString = error; | |
284 #endif /* PKIX_ERROR_DESCRIPTION */ | |
285 | |
286 pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString, | |
287 message2, logComponent, | |
288 currentLevel, plContext); | |
289 PKIX_RETURN(LOGGER); | |
290 } | |
291 | |
292 /* | |
293 * FUNCTION: pkix_Logger_Destroy | |
294 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
295 */ | |
296 static PKIX_Error * | |
297 pkix_Logger_Destroy( | |
298 PKIX_PL_Object *object, | |
299 void *plContext) | |
300 { | |
301 PKIX_Logger *logger = NULL; | |
302 | |
303 PKIX_ENTER(LOGGER, "pkix_Logger_Destroy"); | |
304 PKIX_NULLCHECK_ONE(object); | |
305 | |
306 /* Check that this object is a logger */ | |
307 PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), | |
308 PKIX_OBJECTNOTLOGGER); | |
309 | |
310 logger = (PKIX_Logger *)object; | |
311 | |
312 /* We have a valid logger. DecRef its item and recurse on next */ | |
313 | |
314 logger->callback = NULL; | |
315 PKIX_DECREF(logger->context); | |
316 logger->logComponent = (PKIX_ERRORCLASS)NULL; | |
317 | |
318 cleanup: | |
319 | |
320 PKIX_RETURN(LOGGER); | |
321 } | |
322 | |
323 /* | |
324 * FUNCTION: pkix_Logger_ToString | |
325 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) | |
326 */ | |
327 static PKIX_Error * | |
328 pkix_Logger_ToString( | |
329 PKIX_PL_Object *object, | |
330 PKIX_PL_String **pString, | |
331 void *plContext) | |
332 { | |
333 PKIX_Logger *logger = NULL; | |
334 char *asciiFormat = NULL; | |
335 PKIX_PL_String *formatString = NULL; | |
336 PKIX_PL_String *contextString = NULL; | |
337 PKIX_PL_String *componentString = NULL; | |
338 PKIX_PL_String *loggerString = NULL; | |
339 | |
340 PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper"); | |
341 PKIX_NULLCHECK_TWO(object, pString); | |
342 | |
343 /* Check that this object is a logger */ | |
344 PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), | |
345 PKIX_OBJECTNOTLOGGER); | |
346 | |
347 logger = (PKIX_Logger *)object; | |
348 | |
349 asciiFormat = | |
350 "[\n" | |
351 "\tLogger: \n" | |
352 "\tContext: %s\n" | |
353 "\tMaximum Level: %d\n" | |
354 "\tComponent Name: %s\n" | |
355 "]\n"; | |
356 | |
357 PKIX_CHECK(PKIX_PL_String_Create | |
358 (PKIX_ESCASCII, | |
359 asciiFormat, | |
360 0, | |
361 &formatString, | |
362 plContext), | |
363 PKIX_STRINGCREATEFAILED); | |
364 | |
365 PKIX_TOSTRING(logger->context, &contextString, plContext, | |
366 PKIX_OBJECTTOSTRINGFAILED); | |
367 | |
368 PKIX_CHECK(PKIX_PL_String_Create | |
369 (PKIX_ESCASCII, | |
370 (void *)PKIX_ERRORCLASSNAMES[logger->logComponent], | |
371 0, | |
372 &componentString, | |
373 plContext), | |
374 PKIX_STRINGCREATEFAILED); | |
375 | |
376 PKIX_CHECK(PKIX_PL_Sprintf | |
377 (&loggerString, | |
378 plContext, | |
379 formatString, | |
380 contextString, | |
381 logger->maxLevel, | |
382 componentString), | |
383 PKIX_SPRINTFFAILED); | |
384 | |
385 *pString = loggerString; | |
386 | |
387 cleanup: | |
388 | |
389 PKIX_DECREF(formatString); | |
390 PKIX_DECREF(contextString); | |
391 PKIX_RETURN(LOGGER); | |
392 } | |
393 | |
394 /* | |
395 * FUNCTION: pkix_Logger_Equals | |
396 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) | |
397 */ | |
398 static PKIX_Error * | |
399 pkix_Logger_Equals( | |
400 PKIX_PL_Object *first, | |
401 PKIX_PL_Object *second, | |
402 PKIX_Boolean *pResult, | |
403 void *plContext) | |
404 { | |
405 PKIX_UInt32 secondType; | |
406 PKIX_Boolean cmpResult; | |
407 PKIX_Logger *firstLogger = NULL; | |
408 PKIX_Logger *secondLogger = NULL; | |
409 | |
410 PKIX_ENTER(LOGGER, "pkix_Logger_Equals"); | |
411 PKIX_NULLCHECK_THREE(first, second, pResult); | |
412 | |
413 /* test that first is a Logger */ | |
414 PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext), | |
415 PKIX_FIRSTOBJECTNOTLOGGER); | |
416 | |
417 /* | |
418 * Since we know first is a Logger, if both references are | |
419 * identical, they must be equal | |
420 */ | |
421 if (first == second){ | |
422 *pResult = PKIX_TRUE; | |
423 goto cleanup; | |
424 } | |
425 | |
426 /* | |
427 * If second isn't a Logger, we don't throw an error. | |
428 * We simply return a Boolean result of FALSE | |
429 */ | |
430 *pResult = PKIX_FALSE; | |
431 PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), | |
432 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); | |
433 if (secondType != PKIX_LOGGER_TYPE) goto cleanup; | |
434 | |
435 firstLogger = (PKIX_Logger *)first; | |
436 secondLogger = (PKIX_Logger *)second; | |
437 | |
438 cmpResult = PKIX_FALSE; | |
439 | |
440 if (firstLogger->callback != secondLogger->callback) { | |
441 goto cleanup; | |
442 } | |
443 | |
444 if (firstLogger->logComponent != secondLogger->logComponent) { | |
445 goto cleanup; | |
446 } | |
447 | |
448 PKIX_EQUALS | |
449 (firstLogger->context, | |
450 secondLogger->context, | |
451 &cmpResult, | |
452 plContext, | |
453 PKIX_OBJECTEQUALSFAILED); | |
454 | |
455 if (cmpResult == PKIX_FALSE) { | |
456 goto cleanup; | |
457 } | |
458 | |
459 if (firstLogger->maxLevel != secondLogger->maxLevel) { | |
460 goto cleanup; | |
461 } | |
462 | |
463 *pResult = cmpResult; | |
464 | |
465 cleanup: | |
466 | |
467 PKIX_RETURN(LOGGER); | |
468 } | |
469 | |
470 /* | |
471 * FUNCTION: pkix_Logger_Hashcode | |
472 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) | |
473 */ | |
474 static PKIX_Error * | |
475 pkix_Logger_Hashcode( | |
476 PKIX_PL_Object *object, | |
477 PKIX_UInt32 *pHashcode, | |
478 void *plContext) | |
479 { | |
480 PKIX_Logger *logger = NULL; | |
481 PKIX_UInt32 hash = 0; | |
482 PKIX_UInt32 tempHash = 0; | |
483 | |
484 PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode"); | |
485 PKIX_NULLCHECK_TWO(object, pHashcode); | |
486 | |
487 PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), | |
488 PKIX_OBJECTNOTLOGGER); | |
489 | |
490 logger = (PKIX_Logger *)object; | |
491 | |
492 PKIX_HASHCODE(logger->context, &tempHash, plContext, | |
493 PKIX_OBJECTHASHCODEFAILED); | |
494 | |
495 hash = (((((PKIX_UInt32) logger->callback + tempHash) << 7) + | |
496 logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent; | |
497 | |
498 *pHashcode = hash; | |
499 | |
500 cleanup: | |
501 | |
502 PKIX_RETURN(LOGGER); | |
503 } | |
504 | |
505 | |
506 /* | |
507 * FUNCTION: pkix_Logger_Duplicate | |
508 * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) | |
509 */ | |
510 static PKIX_Error * | |
511 pkix_Logger_Duplicate( | |
512 PKIX_PL_Object *object, | |
513 PKIX_PL_Object **pNewObject, | |
514 void *plContext) | |
515 { | |
516 PKIX_Logger *logger = NULL; | |
517 PKIX_Logger *dupLogger = NULL; | |
518 | |
519 PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate"); | |
520 PKIX_NULLCHECK_TWO(object, pNewObject); | |
521 | |
522 PKIX_CHECK(pkix_CheckType | |
523 ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext), | |
524 PKIX_OBJECTNOTLOGGER); | |
525 | |
526 logger = (PKIX_Logger *) object; | |
527 | |
528 PKIX_CHECK(PKIX_PL_Object_Alloc | |
529 (PKIX_LOGGER_TYPE, | |
530 sizeof (PKIX_Logger), | |
531 (PKIX_PL_Object **)&dupLogger, | |
532 plContext), | |
533 PKIX_COULDNOTCREATELOGGEROBJECT); | |
534 | |
535 dupLogger->callback = logger->callback; | |
536 dupLogger->maxLevel = logger->maxLevel; | |
537 | |
538 PKIX_DUPLICATE | |
539 (logger->context, | |
540 &dupLogger->context, | |
541 plContext, | |
542 PKIX_OBJECTDUPLICATEFAILED); | |
543 | |
544 dupLogger->logComponent = logger->logComponent; | |
545 | |
546 *pNewObject = (PKIX_PL_Object *) dupLogger; | |
547 | |
548 cleanup: | |
549 | |
550 if (PKIX_ERROR_RECEIVED){ | |
551 PKIX_DECREF(dupLogger); | |
552 } | |
553 | |
554 PKIX_RETURN(LOGGER); | |
555 } | |
556 | |
557 /* | |
558 * FUNCTION: pkix_Logger_RegisterSelf | |
559 * DESCRIPTION: | |
560 * Registers PKIX_LOGGER_TYPE and its related functions with systemClasses[] | |
561 * THREAD SAFETY: | |
562 * Not Thread Safe - for performance and complexity reasons | |
563 * | |
564 * Since this function is only called by PKIX_PL_Initialize, which should | |
565 * only be called once, it is acceptable that this function is not | |
566 * thread-safe. | |
567 */ | |
568 PKIX_Error * | |
569 pkix_Logger_RegisterSelf(void *plContext) | |
570 { | |
571 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
572 pkix_ClassTable_Entry entry; | |
573 | |
574 PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf"); | |
575 | |
576 entry.description = "Logger"; | |
577 entry.objCounter = 0; | |
578 entry.typeObjectSize = sizeof(PKIX_Logger); | |
579 entry.destructor = pkix_Logger_Destroy; | |
580 entry.equalsFunction = pkix_Logger_Equals; | |
581 entry.hashcodeFunction = pkix_Logger_Hashcode; | |
582 entry.toStringFunction = pkix_Logger_ToString; | |
583 entry.comparator = NULL; | |
584 entry.duplicateFunction = pkix_Logger_Duplicate; | |
585 | |
586 systemClasses[PKIX_LOGGER_TYPE] = entry; | |
587 | |
588 PKIX_RETURN(LOGGER); | |
589 } | |
590 | |
591 /* --Public-Logger-Functions--------------------------------------------- */ | |
592 | |
593 /* | |
594 * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h) | |
595 */ | |
596 PKIX_Error * | |
597 PKIX_Logger_Create( | |
598 PKIX_Logger_LogCallback callback, | |
599 PKIX_PL_Object *loggerContext, | |
600 PKIX_Logger **pLogger, | |
601 void *plContext) | |
602 { | |
603 PKIX_Logger *logger = NULL; | |
604 | |
605 PKIX_ENTER(LOGGER, "PKIX_Logger_Create"); | |
606 PKIX_NULLCHECK_ONE(pLogger); | |
607 | |
608 PKIX_CHECK(PKIX_PL_Object_Alloc | |
609 (PKIX_LOGGER_TYPE, | |
610 sizeof (PKIX_Logger), | |
611 (PKIX_PL_Object **)&logger, | |
612 plContext), | |
613 PKIX_COULDNOTCREATELOGGEROBJECT); | |
614 | |
615 logger->callback = callback; | |
616 logger->maxLevel = 0; | |
617 logger->logComponent = (PKIX_ERRORCLASS)NULL; | |
618 | |
619 PKIX_INCREF(loggerContext); | |
620 logger->context = loggerContext; | |
621 | |
622 *pLogger = logger; | |
623 logger = NULL; | |
624 | |
625 cleanup: | |
626 | |
627 PKIX_DECREF(logger); | |
628 | |
629 PKIX_RETURN(LOGGER); | |
630 } | |
631 | |
632 /* | |
633 * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h) | |
634 */ | |
635 PKIX_Error * | |
636 PKIX_Logger_GetLogCallback( | |
637 PKIX_Logger *logger, | |
638 PKIX_Logger_LogCallback *pCallback, | |
639 void *plContext) | |
640 { | |
641 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback"); | |
642 PKIX_NULLCHECK_TWO(logger, pCallback); | |
643 | |
644 *pCallback = logger->callback; | |
645 | |
646 PKIX_RETURN(LOGGER); | |
647 } | |
648 | |
649 /* | |
650 * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h) | |
651 */ | |
652 PKIX_Error * | |
653 PKIX_Logger_GetLoggerContext( | |
654 PKIX_Logger *logger, | |
655 PKIX_PL_Object **pLoggerContext, | |
656 void *plContext) | |
657 { | |
658 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex"); | |
659 PKIX_NULLCHECK_TWO(logger, pLoggerContext); | |
660 | |
661 PKIX_INCREF(logger->context); | |
662 *pLoggerContext = logger->context; | |
663 | |
664 cleanup: | |
665 PKIX_RETURN(LOGGER); | |
666 } | |
667 | |
668 /* | |
669 * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h) | |
670 */ | |
671 PKIX_Error * | |
672 PKIX_Logger_GetMaxLoggingLevel( | |
673 PKIX_Logger *logger, | |
674 PKIX_UInt32 *pLevel, | |
675 void *plContext) | |
676 { | |
677 PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel"); | |
678 PKIX_NULLCHECK_TWO(logger, pLevel); | |
679 | |
680 *pLevel = logger->maxLevel; | |
681 | |
682 PKIX_RETURN(LOGGER); | |
683 } | |
684 | |
685 /* | |
686 * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h) | |
687 */ | |
688 PKIX_Error * | |
689 PKIX_Logger_SetMaxLoggingLevel( | |
690 PKIX_Logger *logger, | |
691 PKIX_UInt32 level, | |
692 void *plContext) | |
693 { | |
694 PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel"); | |
695 PKIX_NULLCHECK_ONE(logger); | |
696 | |
697 if (level > PKIX_LOGGER_LEVEL_MAX) { | |
698 PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM); | |
699 } else { | |
700 logger->maxLevel = level; | |
701 } | |
702 | |
703 cleanup: | |
704 | |
705 PKIX_RETURN(LOGGER); | |
706 } | |
707 | |
708 /* | |
709 * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h) | |
710 */ | |
711 PKIX_Error * | |
712 PKIX_Logger_GetLoggingComponent( | |
713 PKIX_Logger *logger, | |
714 PKIX_ERRORCLASS *pComponent, | |
715 void *plContext) | |
716 { | |
717 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent"); | |
718 PKIX_NULLCHECK_TWO(logger, pComponent); | |
719 | |
720 *pComponent = logger->logComponent; | |
721 | |
722 PKIX_RETURN(LOGGER); | |
723 } | |
724 | |
725 /* | |
726 * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h) | |
727 */ | |
728 PKIX_Error * | |
729 PKIX_Logger_SetLoggingComponent( | |
730 PKIX_Logger *logger, | |
731 PKIX_ERRORCLASS component, | |
732 void *plContext) | |
733 { | |
734 PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent"); | |
735 PKIX_NULLCHECK_ONE(logger); | |
736 | |
737 logger->logComponent = component; | |
738 | |
739 PKIX_RETURN(LOGGER); | |
740 } | |
741 | |
742 | |
743 /* | |
744 * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are | |
745 * documented as not thread-safe. However they are thread-safe now. We need | |
746 * the lock when accessing the logger lists. | |
747 */ | |
748 | |
749 /* | |
750 * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h) | |
751 */ | |
752 PKIX_Error * | |
753 PKIX_GetLoggers( | |
754 PKIX_List **pLoggers, /* list of PKIX_Logger */ | |
755 void *plContext) | |
756 { | |
757 PKIX_List *list = NULL; | |
758 PKIX_List *savedPkixLoggersDebugTrace = NULL; | |
759 PKIX_List *savedPkixLoggersErrors = NULL; | |
760 PKIX_Logger *logger = NULL; | |
761 PKIX_Logger *dupLogger = NULL; | |
762 PKIX_UInt32 i, length; | |
763 PKIX_Boolean locked = PKIX_FALSE; | |
764 | |
765 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers"); | |
766 PKIX_NULLCHECK_ONE(pLoggers); | |
767 | |
768 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), | |
769 PKIX_MONITORLOCKENTERFAILED); | |
770 locked = PKIX_TRUE; | |
771 | |
772 /* | |
773 * Temporarily disable DEBUG/TRACE Logging to avoid possible | |
774 * deadlock: | |
775 * When the Logger List is being accessed, e.g. by PKIX_ENTER or | |
776 * PKIX_DECREF, pkix_Logger_Check may check whether logging | |
777 * is requested, creating a deadlock situation. | |
778 */ | |
779 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; | |
780 pkixLoggersDebugTrace = NULL; | |
781 savedPkixLoggersErrors = pkixLoggersErrors; | |
782 pkixLoggersErrors = NULL; | |
783 | |
784 if (pkixLoggers == NULL) { | |
785 length = 0; | |
786 } else { | |
787 PKIX_CHECK(PKIX_List_GetLength | |
788 (pkixLoggers, &length, plContext), | |
789 PKIX_LISTGETLENGTHFAILED); | |
790 } | |
791 | |
792 /* Create a list and copy the pkixLoggers item to the list */ | |
793 PKIX_CHECK(PKIX_List_Create(&list, plContext), | |
794 PKIX_LISTCREATEFAILED); | |
795 | |
796 for (i = 0; i < length; i++) { | |
797 | |
798 PKIX_CHECK(PKIX_List_GetItem | |
799 (pkixLoggers, | |
800 i, | |
801 (PKIX_PL_Object **) &logger, | |
802 plContext), | |
803 PKIX_LISTGETITEMFAILED); | |
804 | |
805 PKIX_CHECK(pkix_Logger_Duplicate | |
806 ((PKIX_PL_Object *)logger, | |
807 (PKIX_PL_Object **)&dupLogger, | |
808 plContext), | |
809 PKIX_LOGGERDUPLICATEFAILED); | |
810 | |
811 PKIX_CHECK(PKIX_List_AppendItem | |
812 (list, | |
813 (PKIX_PL_Object *) dupLogger, | |
814 plContext), | |
815 PKIX_LISTAPPENDITEMFAILED); | |
816 | |
817 PKIX_DECREF(logger); | |
818 PKIX_DECREF(dupLogger); | |
819 } | |
820 | |
821 /* Set the list to be immutable */ | |
822 PKIX_CHECK(PKIX_List_SetImmutable(list, plContext), | |
823 PKIX_LISTSETIMMUTABLEFAILED); | |
824 | |
825 *pLoggers = list; | |
826 | |
827 cleanup: | |
828 | |
829 PKIX_DECREF(logger); | |
830 | |
831 /* Restore logging capability */ | |
832 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; | |
833 pkixLoggersErrors = savedPkixLoggersErrors; | |
834 | |
835 if (locked) { | |
836 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), | |
837 PKIX_MONITORLOCKEXITFAILED); | |
838 } | |
839 | |
840 PKIX_RETURN(LOGGER); | |
841 } | |
842 | |
843 /* | |
844 * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h) | |
845 */ | |
846 PKIX_Error * | |
847 PKIX_SetLoggers( | |
848 PKIX_List *loggers, /* list of PKIX_Logger */ | |
849 void *plContext) | |
850 { | |
851 PKIX_List *list = NULL; | |
852 PKIX_List *savedPkixLoggersErrors = NULL; | |
853 PKIX_List *savedPkixLoggersDebugTrace = NULL; | |
854 PKIX_Logger *logger = NULL; | |
855 PKIX_Logger *dupLogger = NULL; | |
856 PKIX_Boolean locked = PKIX_FALSE; | |
857 PKIX_UInt32 i, length; | |
858 | |
859 PKIX_ENTER(LOGGER, "PKIX_SetLoggers"); | |
860 | |
861 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), | |
862 PKIX_MONITORLOCKENTERFAILED); | |
863 locked = PKIX_TRUE; | |
864 | |
865 /* Disable tracing, etc. to avoid recursion and deadlock */ | |
866 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; | |
867 pkixLoggersDebugTrace = NULL; | |
868 savedPkixLoggersErrors = pkixLoggersErrors; | |
869 pkixLoggersErrors = NULL; | |
870 | |
871 /* discard any prior loggers */ | |
872 PKIX_DECREF(pkixLoggers); | |
873 PKIX_DECREF(savedPkixLoggersErrors); | |
874 PKIX_DECREF(savedPkixLoggersDebugTrace); | |
875 | |
876 if (loggers != NULL) { | |
877 | |
878 PKIX_CHECK(PKIX_List_Create(&list, plContext), | |
879 PKIX_LISTCREATEFAILED); | |
880 | |
881 PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext), | |
882 PKIX_LISTGETLENGTHFAILED); | |
883 | |
884 for (i = 0; i < length; i++) { | |
885 | |
886 PKIX_CHECK(PKIX_List_GetItem | |
887 (loggers, | |
888 i, | |
889 (PKIX_PL_Object **) &logger, | |
890 plContext), | |
891 PKIX_LISTGETITEMFAILED); | |
892 | |
893 PKIX_CHECK(pkix_Logger_Duplicate | |
894 ((PKIX_PL_Object *)logger, | |
895 (PKIX_PL_Object **)&dupLogger, | |
896 plContext), | |
897 PKIX_LOGGERDUPLICATEFAILED); | |
898 | |
899 PKIX_CHECK(PKIX_List_AppendItem | |
900 (list, | |
901 (PKIX_PL_Object *) dupLogger, | |
902 plContext), | |
903 PKIX_LISTAPPENDITEMFAILED); | |
904 | |
905 /* Make two lists */ | |
906 | |
907 /* Put in pkixLoggersErrors in any case*/ | |
908 | |
909 if (savedPkixLoggersErrors == NULL) { | |
910 | |
911 PKIX_CHECK(PKIX_List_Create | |
912 (&savedPkixLoggersErrors, | |
913 plContext), | |
914 PKIX_LISTCREATEFAILED); | |
915 } | |
916 | |
917 PKIX_CHECK(PKIX_List_AppendItem | |
918 (savedPkixLoggersErrors, | |
919 (PKIX_PL_Object *) dupLogger, | |
920 plContext), | |
921 PKIX_LISTAPPENDITEMFAILED); | |
922 | |
923 if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) { | |
924 | |
925 /* Put in pkixLoggersDebugTrace */ | |
926 | |
927 if (savedPkixLoggersDebugTrace == NULL) { | |
928 | |
929 PKIX_CHECK(PKIX_List_Create | |
930 (&savedPkixLoggersDebugTrace, | |
931 plContext), | |
932 PKIX_LISTCREATEFAILED); | |
933 } | |
934 | |
935 PKIX_CHECK(PKIX_List_AppendItem | |
936 (savedPkixLoggersDebugTrace, | |
937 (PKIX_PL_Object *) dupLogger, | |
938 plContext), | |
939 PKIX_LISTAPPENDITEMFAILED); | |
940 } | |
941 PKIX_DECREF(logger); | |
942 PKIX_DECREF(dupLogger); | |
943 | |
944 } | |
945 | |
946 pkixLoggers = list; | |
947 } | |
948 | |
949 cleanup: | |
950 | |
951 if (PKIX_ERROR_RECEIVED){ | |
952 PKIX_DECREF(list); | |
953 PKIX_DECREF(savedPkixLoggersErrors); | |
954 PKIX_DECREF(savedPkixLoggersDebugTrace); | |
955 pkixLoggers = NULL; | |
956 } | |
957 | |
958 PKIX_DECREF(logger); | |
959 | |
960 /* Reenable logging capability with new lists */ | |
961 pkixLoggersErrors = savedPkixLoggersErrors; | |
962 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; | |
963 | |
964 if (locked) { | |
965 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), | |
966 PKIX_MONITORLOCKEXITFAILED); | |
967 } | |
968 | |
969 PKIX_RETURN(LOGGER); | |
970 } | |
971 | |
972 /* | |
973 * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h) | |
974 */ | |
975 PKIX_Error * | |
976 PKIX_AddLogger( | |
977 PKIX_Logger *logger, | |
978 void *plContext) | |
979 { | |
980 PKIX_Logger *dupLogger = NULL; | |
981 PKIX_Logger *addLogger = NULL; | |
982 PKIX_List *savedPkixLoggersErrors = NULL; | |
983 PKIX_List *savedPkixLoggersDebugTrace = NULL; | |
984 PKIX_Boolean locked = PKIX_FALSE; | |
985 PKIX_UInt32 i, length; | |
986 | |
987 PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger"); | |
988 PKIX_NULLCHECK_ONE(logger); | |
989 | |
990 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), | |
991 PKIX_MONITORLOCKENTERFAILED); | |
992 locked = PKIX_TRUE; | |
993 | |
994 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; | |
995 pkixLoggersDebugTrace = NULL; | |
996 savedPkixLoggersErrors = pkixLoggersErrors; | |
997 pkixLoggersErrors = NULL; | |
998 | |
999 PKIX_DECREF(savedPkixLoggersErrors); | |
1000 PKIX_DECREF(savedPkixLoggersDebugTrace); | |
1001 | |
1002 if (pkixLoggers == NULL) { | |
1003 | |
1004 PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext), | |
1005 PKIX_LISTCREATEFAILED); | |
1006 } | |
1007 | |
1008 PKIX_CHECK(pkix_Logger_Duplicate | |
1009 ((PKIX_PL_Object *)logger, | |
1010 (PKIX_PL_Object **)&dupLogger, | |
1011 plContext), | |
1012 PKIX_LOGGERDUPLICATEFAILED); | |
1013 | |
1014 PKIX_CHECK(PKIX_List_AppendItem | |
1015 (pkixLoggers, | |
1016 (PKIX_PL_Object *) dupLogger, | |
1017 plContext), | |
1018 PKIX_LISTAPPENDITEMFAILED); | |
1019 | |
1020 PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext), | |
1021 PKIX_LISTGETLENGTHFAILED); | |
1022 | |
1023 /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */ | |
1024 for (i = 0; i < length; i++) { | |
1025 | |
1026 PKIX_CHECK(PKIX_List_GetItem | |
1027 (pkixLoggers, | |
1028 i, | |
1029 (PKIX_PL_Object **) &addLogger, | |
1030 plContext), | |
1031 PKIX_LISTGETITEMFAILED); | |
1032 | |
1033 | |
1034 /* Put in pkixLoggersErrors */ | |
1035 | |
1036 if (savedPkixLoggersErrors == NULL) { | |
1037 | |
1038 PKIX_CHECK(PKIX_List_Create | |
1039 (&savedPkixLoggersErrors, | |
1040 plContext), | |
1041 PKIX_LISTCREATEFAILED); | |
1042 } | |
1043 | |
1044 PKIX_CHECK(PKIX_List_AppendItem | |
1045 (savedPkixLoggersErrors, | |
1046 (PKIX_PL_Object *) addLogger, | |
1047 plContext), | |
1048 PKIX_LISTAPPENDITEMFAILED); | |
1049 | |
1050 if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) { | |
1051 | |
1052 /* Put in pkixLoggersDebugTrace */ | |
1053 | |
1054 if (savedPkixLoggersDebugTrace == NULL) { | |
1055 | |
1056 PKIX_CHECK(PKIX_List_Create | |
1057 (&savedPkixLoggersDebugTrace, | |
1058 plContext), | |
1059 PKIX_LISTCREATEFAILED); | |
1060 } | |
1061 | |
1062 PKIX_CHECK(PKIX_List_AppendItem | |
1063 (savedPkixLoggersDebugTrace, | |
1064 (PKIX_PL_Object *) addLogger, | |
1065 plContext), | |
1066 PKIX_LISTAPPENDITEMFAILED); | |
1067 } | |
1068 | |
1069 PKIX_DECREF(addLogger); | |
1070 | |
1071 } | |
1072 | |
1073 cleanup: | |
1074 | |
1075 PKIX_DECREF(dupLogger); | |
1076 PKIX_DECREF(addLogger); | |
1077 | |
1078 /* Restore logging capability */ | |
1079 pkixLoggersErrors = savedPkixLoggersErrors; | |
1080 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; | |
1081 | |
1082 if (locked) { | |
1083 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), | |
1084 PKIX_MONITORLOCKEXITFAILED); | |
1085 } | |
1086 | |
1087 PKIX_RETURN(LOGGER); | |
1088 } |