mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-13 11:10:13 +01:00
44b7f056d9
bug1001332, 56b691c003ad, bug1086145, bug1054069, bug1155922, bug991783, bug1125025, bug1162521, bug1162644, bug1132941, bug1164364, bug1166205, bug1166163, bug1166515, bug1138554, bug1167046, bug1167043, bug1169451, bug1172128, bug1170322, bug102794, bug1128184, bug557830, bug1174648, bug1180244, bug1177784, bug1173413, bug1169174, bug1084669, bug951455, bug1183395, bug1177430, bug1183827, bug1160139, bug1154106, bug1142209, bug1185033, bug1193467, bug1182667(with sha512 changes backed out, which breaks VC6 compilation), bug1158489, bug337796
1089 lines
33 KiB
C
1089 lines
33 KiB
C
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
/*
|
|
* pkix_logger.c
|
|
*
|
|
* Logger Object Functions
|
|
*
|
|
*/
|
|
|
|
#include "pkix_logger.h"
|
|
#ifndef PKIX_ERROR_DESCRIPTION
|
|
#include "prprf.h"
|
|
#endif
|
|
|
|
/* Global variable to keep PKIX_Logger List */
|
|
PKIX_List *pkixLoggers = NULL;
|
|
|
|
/*
|
|
* Once the Logger has been set, for any logging related operations, we have
|
|
* to go through the List to find a match, and if found, issue the
|
|
* corresponding callback. The overhead to check for DEBUG and TRACE in each
|
|
* PKIX function entering and exiting is very expensive (400X), and redundant
|
|
* if they are not the interest of the Logger. Therefore, the PKIX_Logger List
|
|
* pkixLoggers is separated into two lists based on its Loggers' trace level.
|
|
*
|
|
* Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or
|
|
* PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors
|
|
* and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and
|
|
* WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to
|
|
* pkixLoggersDebugTrace.
|
|
*
|
|
* Currently we provide five logging levels and the default setting are by:
|
|
*
|
|
* PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level
|
|
* PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level
|
|
* WARNING is not invoked as default
|
|
* PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs
|
|
* compilation -DPKIX_<component>DEBUG flag to turn on
|
|
* PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE
|
|
* level. TRACE provides duplicate information of DEBUG, but needs no
|
|
* recompilation and cannot choose component. To allow application
|
|
* to use DEBUG level, TRACE is put as last.
|
|
*
|
|
*/
|
|
PKIX_List *pkixLoggersErrors = NULL;
|
|
PKIX_List *pkixLoggersDebugTrace = NULL;
|
|
|
|
/* To ensure atomic update on pkixLoggers lists */
|
|
PKIX_PL_MonitorLock *pkixLoggerLock = NULL;
|
|
|
|
/* --Private-Functions-------------------------------------------- */
|
|
|
|
/*
|
|
* FUNCTION: pkix_Logger_CheckErrors
|
|
* DESCRIPTION:
|
|
*
|
|
* This function goes through each PKIX_Logger at "pkixLoggersList" and
|
|
* checks if "maxLevel" and "logComponent" satisfies what is specified in the
|
|
* PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and
|
|
* passes a PKIX_PL_String that is the concatenation of "message" and
|
|
* "message2" to the application for processing.
|
|
* Since this call is inserted into a handful of PKIX macros, no macros are
|
|
* applied in this function, to avoid infinite recursion.
|
|
* If an error occurs, this call is aborted.
|
|
*
|
|
* PARAMETERS:
|
|
* "pkixLoggersList"
|
|
* A list of PKIX_Loggers to be examined for invoking callback. Must be
|
|
* non-NULL.
|
|
* "message"
|
|
* Address of "message" to be logged. Must be non-NULL.
|
|
* "message2"
|
|
* Address of "message2" to be concatenated and logged. May be NULL.
|
|
* "logComponent"
|
|
* A PKIX_UInt32 that indicates the component the message is from.
|
|
* "maxLevel"
|
|
* A PKIX_UInt32 that represents the level of severity of the message.
|
|
* "plContext"
|
|
* Platform-specific context pointer.
|
|
* THREAD SAFETY:
|
|
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
|
* RETURNS:
|
|
* Returns NULL if the function succeeds
|
|
* Returns a Fatal Error if the function fails in an unrecoverable way
|
|
*/
|
|
PKIX_Error *
|
|
pkix_Logger_Check(
|
|
PKIX_List *pkixLoggersList,
|
|
const char *message,
|
|
const char *message2,
|
|
PKIX_ERRORCLASS logComponent,
|
|
PKIX_UInt32 currentLevel,
|
|
void *plContext)
|
|
{
|
|
PKIX_Logger *logger = NULL;
|
|
PKIX_List *savedPkixLoggersErrors = NULL;
|
|
PKIX_List *savedPkixLoggersDebugTrace = NULL;
|
|
PKIX_PL_String *formatString = NULL;
|
|
PKIX_PL_String *messageString = NULL;
|
|
PKIX_PL_String *message2String = NULL;
|
|
PKIX_PL_String *msgString = NULL;
|
|
PKIX_Error *error = NULL;
|
|
PKIX_Boolean needLogging = PKIX_FALSE;
|
|
PKIX_UInt32 i, length;
|
|
|
|
/*
|
|
* We cannot use any the PKIX_ macros here, since this function is
|
|
* called from some of these macros. It can create infinite recursion.
|
|
*/
|
|
|
|
if ((pkixLoggersList == NULL) || (message == NULL)) {
|
|
return(NULL);
|
|
}
|
|
|
|
/*
|
|
* Disable all subsequent loggings to avoid recursion. The result is
|
|
* if other thread is calling this function at the same time, there
|
|
* won't be any logging because the pkixLoggersErrors and
|
|
* pkixLoggersDebugTrace are set to null.
|
|
* It would be nice if we provide control per thread (e.g. make
|
|
* plContext threadable) then we can avoid the recursion by setting
|
|
* flag at plContext. Then other thread's logging won't be affected.
|
|
*
|
|
* Also we need to use a reentrant Lock. Although we avoid recursion
|
|
* for TRACE. When there is an ERROR occurs in subsequent call, this
|
|
* function will be called.
|
|
*/
|
|
|
|
error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext);
|
|
if (error) { return(NULL); }
|
|
|
|
savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
|
|
pkixLoggersDebugTrace = NULL;
|
|
savedPkixLoggersErrors = pkixLoggersErrors;
|
|
pkixLoggersErrors = NULL;
|
|
|
|
/* Convert message and message2 to String */
|
|
error = PKIX_PL_String_Create
|
|
(PKIX_ESCASCII, message, 0, &messageString, plContext);
|
|
if (error) { goto cleanup; }
|
|
|
|
if (message2) {
|
|
error = PKIX_PL_String_Create
|
|
(PKIX_ESCASCII, message2, 0, &message2String, plContext);
|
|
if (error) { goto cleanup; }
|
|
error = PKIX_PL_String_Create
|
|
(PKIX_ESCASCII, "%s %s", 0, &formatString, plContext);
|
|
if (error) { goto cleanup; }
|
|
|
|
} else {
|
|
error = PKIX_PL_String_Create
|
|
(PKIX_ESCASCII, "%s", 0, &formatString, plContext);
|
|
if (error) { goto cleanup; }
|
|
|
|
}
|
|
|
|
error = PKIX_PL_Sprintf
|
|
(&msgString,
|
|
plContext,
|
|
formatString,
|
|
messageString,
|
|
message2String);
|
|
if (error) { goto cleanup; }
|
|
|
|
/* Go through the Logger list */
|
|
|
|
error = PKIX_List_GetLength(pkixLoggersList, &length, plContext);
|
|
if (error) { goto cleanup; }
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
error = PKIX_List_GetItem
|
|
(pkixLoggersList,
|
|
i,
|
|
(PKIX_PL_Object **) &logger,
|
|
plContext);
|
|
if (error) { goto cleanup; }
|
|
|
|
/* Intended logging level less or equal than the max */
|
|
needLogging = (currentLevel <= logger->maxLevel);
|
|
|
|
if (needLogging && (logger->callback)) {
|
|
|
|
/*
|
|
* We separate Logger into two lists based on log level
|
|
* but log level is not modified. We need to check here to
|
|
* avoid logging the higher log level (lower value) twice.
|
|
*/
|
|
if (pkixLoggersList == pkixLoggersErrors) {
|
|
needLogging = needLogging &&
|
|
(currentLevel <= PKIX_LOGGER_LEVEL_WARNING);
|
|
} else if (pkixLoggersList == pkixLoggersDebugTrace) {
|
|
needLogging = needLogging &&
|
|
(currentLevel > PKIX_LOGGER_LEVEL_WARNING);
|
|
}
|
|
|
|
if (needLogging) {
|
|
if (logComponent == logger->logComponent) {
|
|
needLogging = PKIX_TRUE;
|
|
} else {
|
|
needLogging = PKIX_FALSE;
|
|
}
|
|
}
|
|
|
|
if (needLogging) {
|
|
error = logger->callback
|
|
(logger,
|
|
msgString,
|
|
currentLevel,
|
|
logComponent,
|
|
plContext);
|
|
if (error) { goto cleanup; }
|
|
}
|
|
}
|
|
|
|
error = PKIX_PL_Object_DecRef
|
|
((PKIX_PL_Object *)logger, plContext);
|
|
logger = NULL;
|
|
if (error) { goto cleanup; }
|
|
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if (formatString) {
|
|
error = PKIX_PL_Object_DecRef
|
|
((PKIX_PL_Object *)formatString, plContext);
|
|
}
|
|
|
|
if (messageString) {
|
|
error = PKIX_PL_Object_DecRef
|
|
((PKIX_PL_Object *)messageString, plContext);
|
|
}
|
|
|
|
if (message2String) {
|
|
error = PKIX_PL_Object_DecRef
|
|
((PKIX_PL_Object *)message2String, plContext);
|
|
}
|
|
|
|
if (msgString) {
|
|
error = PKIX_PL_Object_DecRef
|
|
((PKIX_PL_Object *)msgString, plContext);
|
|
}
|
|
|
|
if (logger) {
|
|
error = PKIX_PL_Object_DecRef
|
|
((PKIX_PL_Object *)logger, plContext);
|
|
}
|
|
|
|
if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) {
|
|
pkixLoggersErrors = savedPkixLoggersErrors;
|
|
}
|
|
|
|
if (pkixLoggersDebugTrace == NULL &&
|
|
savedPkixLoggersDebugTrace != NULL) {
|
|
pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
|
|
}
|
|
|
|
error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext);
|
|
if (error) { return(NULL); }
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
PKIX_Error *
|
|
pkix_Logger_CheckWithCode(
|
|
PKIX_List *pkixLoggersList,
|
|
PKIX_UInt32 errorCode,
|
|
const char *message2,
|
|
PKIX_ERRORCLASS logComponent,
|
|
PKIX_UInt32 currentLevel,
|
|
void *plContext)
|
|
{
|
|
char error[32];
|
|
char *errorString = NULL;
|
|
|
|
PKIX_ENTER(LOGGER, "pkix_Logger_CheckWithCode");
|
|
#if defined PKIX_ERROR_DESCRIPTION
|
|
errorString = PKIX_ErrorText[errorCode];
|
|
#else
|
|
PR_snprintf(error, 32, "Error code: %d", errorCode);
|
|
errorString = error;
|
|
#endif /* PKIX_ERROR_DESCRIPTION */
|
|
|
|
pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString,
|
|
message2, logComponent,
|
|
currentLevel, plContext);
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: pkix_Logger_Destroy
|
|
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
|
|
*/
|
|
static PKIX_Error *
|
|
pkix_Logger_Destroy(
|
|
PKIX_PL_Object *object,
|
|
void *plContext)
|
|
{
|
|
PKIX_Logger *logger = NULL;
|
|
|
|
PKIX_ENTER(LOGGER, "pkix_Logger_Destroy");
|
|
PKIX_NULLCHECK_ONE(object);
|
|
|
|
/* Check that this object is a logger */
|
|
PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
|
|
PKIX_OBJECTNOTLOGGER);
|
|
|
|
logger = (PKIX_Logger *)object;
|
|
|
|
/* We have a valid logger. DecRef its item and recurse on next */
|
|
|
|
logger->callback = NULL;
|
|
PKIX_DECREF(logger->context);
|
|
logger->logComponent = (PKIX_ERRORCLASS)NULL;
|
|
|
|
cleanup:
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: pkix_Logger_ToString
|
|
* (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
|
|
*/
|
|
static PKIX_Error *
|
|
pkix_Logger_ToString(
|
|
PKIX_PL_Object *object,
|
|
PKIX_PL_String **pString,
|
|
void *plContext)
|
|
{
|
|
PKIX_Logger *logger = NULL;
|
|
char *asciiFormat = NULL;
|
|
PKIX_PL_String *formatString = NULL;
|
|
PKIX_PL_String *contextString = NULL;
|
|
PKIX_PL_String *componentString = NULL;
|
|
PKIX_PL_String *loggerString = NULL;
|
|
|
|
PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper");
|
|
PKIX_NULLCHECK_TWO(object, pString);
|
|
|
|
/* Check that this object is a logger */
|
|
PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
|
|
PKIX_OBJECTNOTLOGGER);
|
|
|
|
logger = (PKIX_Logger *)object;
|
|
|
|
asciiFormat =
|
|
"[\n"
|
|
"\tLogger: \n"
|
|
"\tContext: %s\n"
|
|
"\tMaximum Level: %d\n"
|
|
"\tComponent Name: %s\n"
|
|
"]\n";
|
|
|
|
PKIX_CHECK(PKIX_PL_String_Create
|
|
(PKIX_ESCASCII,
|
|
asciiFormat,
|
|
0,
|
|
&formatString,
|
|
plContext),
|
|
PKIX_STRINGCREATEFAILED);
|
|
|
|
PKIX_TOSTRING(logger->context, &contextString, plContext,
|
|
PKIX_OBJECTTOSTRINGFAILED);
|
|
|
|
PKIX_CHECK(PKIX_PL_String_Create
|
|
(PKIX_ESCASCII,
|
|
(void *)PKIX_ERRORCLASSNAMES[logger->logComponent],
|
|
0,
|
|
&componentString,
|
|
plContext),
|
|
PKIX_STRINGCREATEFAILED);
|
|
|
|
PKIX_CHECK(PKIX_PL_Sprintf
|
|
(&loggerString,
|
|
plContext,
|
|
formatString,
|
|
contextString,
|
|
logger->maxLevel,
|
|
componentString),
|
|
PKIX_SPRINTFFAILED);
|
|
|
|
*pString = loggerString;
|
|
|
|
cleanup:
|
|
|
|
PKIX_DECREF(formatString);
|
|
PKIX_DECREF(contextString);
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: pkix_Logger_Equals
|
|
* (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
|
|
*/
|
|
static PKIX_Error *
|
|
pkix_Logger_Equals(
|
|
PKIX_PL_Object *first,
|
|
PKIX_PL_Object *second,
|
|
PKIX_Boolean *pResult,
|
|
void *plContext)
|
|
{
|
|
PKIX_UInt32 secondType;
|
|
PKIX_Boolean cmpResult;
|
|
PKIX_Logger *firstLogger = NULL;
|
|
PKIX_Logger *secondLogger = NULL;
|
|
|
|
PKIX_ENTER(LOGGER, "pkix_Logger_Equals");
|
|
PKIX_NULLCHECK_THREE(first, second, pResult);
|
|
|
|
/* test that first is a Logger */
|
|
PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext),
|
|
PKIX_FIRSTOBJECTNOTLOGGER);
|
|
|
|
/*
|
|
* Since we know first is a Logger, if both references are
|
|
* identical, they must be equal
|
|
*/
|
|
if (first == second){
|
|
*pResult = PKIX_TRUE;
|
|
goto cleanup;
|
|
}
|
|
|
|
/*
|
|
* If second isn't a Logger, we don't throw an error.
|
|
* We simply return a Boolean result of FALSE
|
|
*/
|
|
*pResult = PKIX_FALSE;
|
|
PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
|
|
PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
|
|
if (secondType != PKIX_LOGGER_TYPE) goto cleanup;
|
|
|
|
firstLogger = (PKIX_Logger *)first;
|
|
secondLogger = (PKIX_Logger *)second;
|
|
|
|
cmpResult = PKIX_FALSE;
|
|
|
|
if (firstLogger->callback != secondLogger->callback) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (firstLogger->logComponent != secondLogger->logComponent) {
|
|
goto cleanup;
|
|
}
|
|
|
|
PKIX_EQUALS
|
|
(firstLogger->context,
|
|
secondLogger->context,
|
|
&cmpResult,
|
|
plContext,
|
|
PKIX_OBJECTEQUALSFAILED);
|
|
|
|
if (cmpResult == PKIX_FALSE) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (firstLogger->maxLevel != secondLogger->maxLevel) {
|
|
goto cleanup;
|
|
}
|
|
|
|
*pResult = cmpResult;
|
|
|
|
cleanup:
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: pkix_Logger_Hashcode
|
|
* (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
|
|
*/
|
|
static PKIX_Error *
|
|
pkix_Logger_Hashcode(
|
|
PKIX_PL_Object *object,
|
|
PKIX_UInt32 *pHashcode,
|
|
void *plContext)
|
|
{
|
|
PKIX_Logger *logger = NULL;
|
|
PKIX_UInt32 hash = 0;
|
|
PKIX_UInt32 tempHash = 0;
|
|
|
|
PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode");
|
|
PKIX_NULLCHECK_TWO(object, pHashcode);
|
|
|
|
PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
|
|
PKIX_OBJECTNOTLOGGER);
|
|
|
|
logger = (PKIX_Logger *)object;
|
|
|
|
PKIX_HASHCODE(logger->context, &tempHash, plContext,
|
|
PKIX_OBJECTHASHCODEFAILED);
|
|
|
|
hash = (((((PKIX_UInt32)((char *)logger->callback - (char *)NULL) + tempHash) << 7) +
|
|
logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent;
|
|
|
|
*pHashcode = hash;
|
|
|
|
cleanup:
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
|
|
/*
|
|
* FUNCTION: pkix_Logger_Duplicate
|
|
* (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
|
|
*/
|
|
static PKIX_Error *
|
|
pkix_Logger_Duplicate(
|
|
PKIX_PL_Object *object,
|
|
PKIX_PL_Object **pNewObject,
|
|
void *plContext)
|
|
{
|
|
PKIX_Logger *logger = NULL;
|
|
PKIX_Logger *dupLogger = NULL;
|
|
|
|
PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate");
|
|
PKIX_NULLCHECK_TWO(object, pNewObject);
|
|
|
|
PKIX_CHECK(pkix_CheckType
|
|
((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext),
|
|
PKIX_OBJECTNOTLOGGER);
|
|
|
|
logger = (PKIX_Logger *) object;
|
|
|
|
PKIX_CHECK(PKIX_PL_Object_Alloc
|
|
(PKIX_LOGGER_TYPE,
|
|
sizeof (PKIX_Logger),
|
|
(PKIX_PL_Object **)&dupLogger,
|
|
plContext),
|
|
PKIX_COULDNOTCREATELOGGEROBJECT);
|
|
|
|
dupLogger->callback = logger->callback;
|
|
dupLogger->maxLevel = logger->maxLevel;
|
|
|
|
PKIX_DUPLICATE
|
|
(logger->context,
|
|
&dupLogger->context,
|
|
plContext,
|
|
PKIX_OBJECTDUPLICATEFAILED);
|
|
|
|
dupLogger->logComponent = logger->logComponent;
|
|
|
|
*pNewObject = (PKIX_PL_Object *) dupLogger;
|
|
|
|
cleanup:
|
|
|
|
if (PKIX_ERROR_RECEIVED){
|
|
PKIX_DECREF(dupLogger);
|
|
}
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: pkix_Logger_RegisterSelf
|
|
* DESCRIPTION:
|
|
* Registers PKIX_LOGGER_TYPE and its related functions with systemClasses[]
|
|
* THREAD SAFETY:
|
|
* Not Thread Safe - for performance and complexity reasons
|
|
*
|
|
* Since this function is only called by PKIX_PL_Initialize, which should
|
|
* only be called once, it is acceptable that this function is not
|
|
* thread-safe.
|
|
*/
|
|
PKIX_Error *
|
|
pkix_Logger_RegisterSelf(void *plContext)
|
|
{
|
|
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
|
|
pkix_ClassTable_Entry entry;
|
|
|
|
PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf");
|
|
|
|
entry.description = "Logger";
|
|
entry.objCounter = 0;
|
|
entry.typeObjectSize = sizeof(PKIX_Logger);
|
|
entry.destructor = pkix_Logger_Destroy;
|
|
entry.equalsFunction = pkix_Logger_Equals;
|
|
entry.hashcodeFunction = pkix_Logger_Hashcode;
|
|
entry.toStringFunction = pkix_Logger_ToString;
|
|
entry.comparator = NULL;
|
|
entry.duplicateFunction = pkix_Logger_Duplicate;
|
|
|
|
systemClasses[PKIX_LOGGER_TYPE] = entry;
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/* --Public-Logger-Functions--------------------------------------------- */
|
|
|
|
/*
|
|
* FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h)
|
|
*/
|
|
PKIX_Error *
|
|
PKIX_Logger_Create(
|
|
PKIX_Logger_LogCallback callback,
|
|
PKIX_PL_Object *loggerContext,
|
|
PKIX_Logger **pLogger,
|
|
void *plContext)
|
|
{
|
|
PKIX_Logger *logger = NULL;
|
|
|
|
PKIX_ENTER(LOGGER, "PKIX_Logger_Create");
|
|
PKIX_NULLCHECK_ONE(pLogger);
|
|
|
|
PKIX_CHECK(PKIX_PL_Object_Alloc
|
|
(PKIX_LOGGER_TYPE,
|
|
sizeof (PKIX_Logger),
|
|
(PKIX_PL_Object **)&logger,
|
|
plContext),
|
|
PKIX_COULDNOTCREATELOGGEROBJECT);
|
|
|
|
logger->callback = callback;
|
|
logger->maxLevel = 0;
|
|
logger->logComponent = (PKIX_ERRORCLASS)NULL;
|
|
|
|
PKIX_INCREF(loggerContext);
|
|
logger->context = loggerContext;
|
|
|
|
*pLogger = logger;
|
|
logger = NULL;
|
|
|
|
cleanup:
|
|
|
|
PKIX_DECREF(logger);
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h)
|
|
*/
|
|
PKIX_Error *
|
|
PKIX_Logger_GetLogCallback(
|
|
PKIX_Logger *logger,
|
|
PKIX_Logger_LogCallback *pCallback,
|
|
void *plContext)
|
|
{
|
|
PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback");
|
|
PKIX_NULLCHECK_TWO(logger, pCallback);
|
|
|
|
*pCallback = logger->callback;
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h)
|
|
*/
|
|
PKIX_Error *
|
|
PKIX_Logger_GetLoggerContext(
|
|
PKIX_Logger *logger,
|
|
PKIX_PL_Object **pLoggerContext,
|
|
void *plContext)
|
|
{
|
|
PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex");
|
|
PKIX_NULLCHECK_TWO(logger, pLoggerContext);
|
|
|
|
PKIX_INCREF(logger->context);
|
|
*pLoggerContext = logger->context;
|
|
|
|
cleanup:
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h)
|
|
*/
|
|
PKIX_Error *
|
|
PKIX_Logger_GetMaxLoggingLevel(
|
|
PKIX_Logger *logger,
|
|
PKIX_UInt32 *pLevel,
|
|
void *plContext)
|
|
{
|
|
PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel");
|
|
PKIX_NULLCHECK_TWO(logger, pLevel);
|
|
|
|
*pLevel = logger->maxLevel;
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h)
|
|
*/
|
|
PKIX_Error *
|
|
PKIX_Logger_SetMaxLoggingLevel(
|
|
PKIX_Logger *logger,
|
|
PKIX_UInt32 level,
|
|
void *plContext)
|
|
{
|
|
PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel");
|
|
PKIX_NULLCHECK_ONE(logger);
|
|
|
|
if (level > PKIX_LOGGER_LEVEL_MAX) {
|
|
PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM);
|
|
} else {
|
|
logger->maxLevel = level;
|
|
}
|
|
|
|
cleanup:
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h)
|
|
*/
|
|
PKIX_Error *
|
|
PKIX_Logger_GetLoggingComponent(
|
|
PKIX_Logger *logger,
|
|
PKIX_ERRORCLASS *pComponent,
|
|
void *plContext)
|
|
{
|
|
PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent");
|
|
PKIX_NULLCHECK_TWO(logger, pComponent);
|
|
|
|
*pComponent = logger->logComponent;
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h)
|
|
*/
|
|
PKIX_Error *
|
|
PKIX_Logger_SetLoggingComponent(
|
|
PKIX_Logger *logger,
|
|
PKIX_ERRORCLASS component,
|
|
void *plContext)
|
|
{
|
|
PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent");
|
|
PKIX_NULLCHECK_ONE(logger);
|
|
|
|
logger->logComponent = component;
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
|
|
/*
|
|
* Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are
|
|
* documented as not thread-safe. However they are thread-safe now. We need
|
|
* the lock when accessing the logger lists.
|
|
*/
|
|
|
|
/*
|
|
* FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h)
|
|
*/
|
|
PKIX_Error *
|
|
PKIX_GetLoggers(
|
|
PKIX_List **pLoggers, /* list of PKIX_Logger */
|
|
void *plContext)
|
|
{
|
|
PKIX_List *list = NULL;
|
|
PKIX_List *savedPkixLoggersDebugTrace = NULL;
|
|
PKIX_List *savedPkixLoggersErrors = NULL;
|
|
PKIX_Logger *logger = NULL;
|
|
PKIX_Logger *dupLogger = NULL;
|
|
PKIX_UInt32 i, length;
|
|
PKIX_Boolean locked = PKIX_FALSE;
|
|
|
|
PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers");
|
|
PKIX_NULLCHECK_ONE(pLoggers);
|
|
|
|
PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
|
|
PKIX_MONITORLOCKENTERFAILED);
|
|
locked = PKIX_TRUE;
|
|
|
|
/*
|
|
* Temporarily disable DEBUG/TRACE Logging to avoid possible
|
|
* deadlock:
|
|
* When the Logger List is being accessed, e.g. by PKIX_ENTER or
|
|
* PKIX_DECREF, pkix_Logger_Check may check whether logging
|
|
* is requested, creating a deadlock situation.
|
|
*/
|
|
savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
|
|
pkixLoggersDebugTrace = NULL;
|
|
savedPkixLoggersErrors = pkixLoggersErrors;
|
|
pkixLoggersErrors = NULL;
|
|
|
|
if (pkixLoggers == NULL) {
|
|
length = 0;
|
|
} else {
|
|
PKIX_CHECK(PKIX_List_GetLength
|
|
(pkixLoggers, &length, plContext),
|
|
PKIX_LISTGETLENGTHFAILED);
|
|
}
|
|
|
|
/* Create a list and copy the pkixLoggers item to the list */
|
|
PKIX_CHECK(PKIX_List_Create(&list, plContext),
|
|
PKIX_LISTCREATEFAILED);
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
PKIX_CHECK(PKIX_List_GetItem
|
|
(pkixLoggers,
|
|
i,
|
|
(PKIX_PL_Object **) &logger,
|
|
plContext),
|
|
PKIX_LISTGETITEMFAILED);
|
|
|
|
PKIX_CHECK(pkix_Logger_Duplicate
|
|
((PKIX_PL_Object *)logger,
|
|
(PKIX_PL_Object **)&dupLogger,
|
|
plContext),
|
|
PKIX_LOGGERDUPLICATEFAILED);
|
|
|
|
PKIX_CHECK(PKIX_List_AppendItem
|
|
(list,
|
|
(PKIX_PL_Object *) dupLogger,
|
|
plContext),
|
|
PKIX_LISTAPPENDITEMFAILED);
|
|
|
|
PKIX_DECREF(logger);
|
|
PKIX_DECREF(dupLogger);
|
|
}
|
|
|
|
/* Set the list to be immutable */
|
|
PKIX_CHECK(PKIX_List_SetImmutable(list, plContext),
|
|
PKIX_LISTSETIMMUTABLEFAILED);
|
|
|
|
*pLoggers = list;
|
|
|
|
cleanup:
|
|
|
|
PKIX_DECREF(logger);
|
|
|
|
/* Restore logging capability */
|
|
pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
|
|
pkixLoggersErrors = savedPkixLoggersErrors;
|
|
|
|
if (locked) {
|
|
PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
|
|
PKIX_MONITORLOCKEXITFAILED);
|
|
}
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h)
|
|
*/
|
|
PKIX_Error *
|
|
PKIX_SetLoggers(
|
|
PKIX_List *loggers, /* list of PKIX_Logger */
|
|
void *plContext)
|
|
{
|
|
PKIX_List *list = NULL;
|
|
PKIX_List *savedPkixLoggersErrors = NULL;
|
|
PKIX_List *savedPkixLoggersDebugTrace = NULL;
|
|
PKIX_Logger *logger = NULL;
|
|
PKIX_Logger *dupLogger = NULL;
|
|
PKIX_Boolean locked = PKIX_FALSE;
|
|
PKIX_UInt32 i, length;
|
|
|
|
PKIX_ENTER(LOGGER, "PKIX_SetLoggers");
|
|
|
|
PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
|
|
PKIX_MONITORLOCKENTERFAILED);
|
|
locked = PKIX_TRUE;
|
|
|
|
/* Disable tracing, etc. to avoid recursion and deadlock */
|
|
savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
|
|
pkixLoggersDebugTrace = NULL;
|
|
savedPkixLoggersErrors = pkixLoggersErrors;
|
|
pkixLoggersErrors = NULL;
|
|
|
|
/* discard any prior loggers */
|
|
PKIX_DECREF(pkixLoggers);
|
|
PKIX_DECREF(savedPkixLoggersErrors);
|
|
PKIX_DECREF(savedPkixLoggersDebugTrace);
|
|
|
|
if (loggers != NULL) {
|
|
|
|
PKIX_CHECK(PKIX_List_Create(&list, plContext),
|
|
PKIX_LISTCREATEFAILED);
|
|
|
|
PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext),
|
|
PKIX_LISTGETLENGTHFAILED);
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
PKIX_CHECK(PKIX_List_GetItem
|
|
(loggers,
|
|
i,
|
|
(PKIX_PL_Object **) &logger,
|
|
plContext),
|
|
PKIX_LISTGETITEMFAILED);
|
|
|
|
PKIX_CHECK(pkix_Logger_Duplicate
|
|
((PKIX_PL_Object *)logger,
|
|
(PKIX_PL_Object **)&dupLogger,
|
|
plContext),
|
|
PKIX_LOGGERDUPLICATEFAILED);
|
|
|
|
PKIX_CHECK(PKIX_List_AppendItem
|
|
(list,
|
|
(PKIX_PL_Object *) dupLogger,
|
|
plContext),
|
|
PKIX_LISTAPPENDITEMFAILED);
|
|
|
|
/* Make two lists */
|
|
|
|
/* Put in pkixLoggersErrors in any case*/
|
|
|
|
if (savedPkixLoggersErrors == NULL) {
|
|
|
|
PKIX_CHECK(PKIX_List_Create
|
|
(&savedPkixLoggersErrors,
|
|
plContext),
|
|
PKIX_LISTCREATEFAILED);
|
|
}
|
|
|
|
PKIX_CHECK(PKIX_List_AppendItem
|
|
(savedPkixLoggersErrors,
|
|
(PKIX_PL_Object *) dupLogger,
|
|
plContext),
|
|
PKIX_LISTAPPENDITEMFAILED);
|
|
|
|
if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
|
|
|
|
/* Put in pkixLoggersDebugTrace */
|
|
|
|
if (savedPkixLoggersDebugTrace == NULL) {
|
|
|
|
PKIX_CHECK(PKIX_List_Create
|
|
(&savedPkixLoggersDebugTrace,
|
|
plContext),
|
|
PKIX_LISTCREATEFAILED);
|
|
}
|
|
|
|
PKIX_CHECK(PKIX_List_AppendItem
|
|
(savedPkixLoggersDebugTrace,
|
|
(PKIX_PL_Object *) dupLogger,
|
|
plContext),
|
|
PKIX_LISTAPPENDITEMFAILED);
|
|
}
|
|
PKIX_DECREF(logger);
|
|
PKIX_DECREF(dupLogger);
|
|
|
|
}
|
|
|
|
pkixLoggers = list;
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if (PKIX_ERROR_RECEIVED){
|
|
PKIX_DECREF(list);
|
|
PKIX_DECREF(savedPkixLoggersErrors);
|
|
PKIX_DECREF(savedPkixLoggersDebugTrace);
|
|
pkixLoggers = NULL;
|
|
}
|
|
|
|
PKIX_DECREF(logger);
|
|
|
|
/* Reenable logging capability with new lists */
|
|
pkixLoggersErrors = savedPkixLoggersErrors;
|
|
pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
|
|
|
|
if (locked) {
|
|
PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
|
|
PKIX_MONITORLOCKEXITFAILED);
|
|
}
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h)
|
|
*/
|
|
PKIX_Error *
|
|
PKIX_AddLogger(
|
|
PKIX_Logger *logger,
|
|
void *plContext)
|
|
{
|
|
PKIX_Logger *dupLogger = NULL;
|
|
PKIX_Logger *addLogger = NULL;
|
|
PKIX_List *savedPkixLoggersErrors = NULL;
|
|
PKIX_List *savedPkixLoggersDebugTrace = NULL;
|
|
PKIX_Boolean locked = PKIX_FALSE;
|
|
PKIX_UInt32 i, length;
|
|
|
|
PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger");
|
|
PKIX_NULLCHECK_ONE(logger);
|
|
|
|
PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
|
|
PKIX_MONITORLOCKENTERFAILED);
|
|
locked = PKIX_TRUE;
|
|
|
|
savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
|
|
pkixLoggersDebugTrace = NULL;
|
|
savedPkixLoggersErrors = pkixLoggersErrors;
|
|
pkixLoggersErrors = NULL;
|
|
|
|
PKIX_DECREF(savedPkixLoggersErrors);
|
|
PKIX_DECREF(savedPkixLoggersDebugTrace);
|
|
|
|
if (pkixLoggers == NULL) {
|
|
|
|
PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext),
|
|
PKIX_LISTCREATEFAILED);
|
|
}
|
|
|
|
PKIX_CHECK(pkix_Logger_Duplicate
|
|
((PKIX_PL_Object *)logger,
|
|
(PKIX_PL_Object **)&dupLogger,
|
|
plContext),
|
|
PKIX_LOGGERDUPLICATEFAILED);
|
|
|
|
PKIX_CHECK(PKIX_List_AppendItem
|
|
(pkixLoggers,
|
|
(PKIX_PL_Object *) dupLogger,
|
|
plContext),
|
|
PKIX_LISTAPPENDITEMFAILED);
|
|
|
|
PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext),
|
|
PKIX_LISTGETLENGTHFAILED);
|
|
|
|
/* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */
|
|
for (i = 0; i < length; i++) {
|
|
|
|
PKIX_CHECK(PKIX_List_GetItem
|
|
(pkixLoggers,
|
|
i,
|
|
(PKIX_PL_Object **) &addLogger,
|
|
plContext),
|
|
PKIX_LISTGETITEMFAILED);
|
|
|
|
|
|
/* Put in pkixLoggersErrors */
|
|
|
|
if (savedPkixLoggersErrors == NULL) {
|
|
|
|
PKIX_CHECK(PKIX_List_Create
|
|
(&savedPkixLoggersErrors,
|
|
plContext),
|
|
PKIX_LISTCREATEFAILED);
|
|
}
|
|
|
|
PKIX_CHECK(PKIX_List_AppendItem
|
|
(savedPkixLoggersErrors,
|
|
(PKIX_PL_Object *) addLogger,
|
|
plContext),
|
|
PKIX_LISTAPPENDITEMFAILED);
|
|
|
|
if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
|
|
|
|
/* Put in pkixLoggersDebugTrace */
|
|
|
|
if (savedPkixLoggersDebugTrace == NULL) {
|
|
|
|
PKIX_CHECK(PKIX_List_Create
|
|
(&savedPkixLoggersDebugTrace,
|
|
plContext),
|
|
PKIX_LISTCREATEFAILED);
|
|
}
|
|
|
|
PKIX_CHECK(PKIX_List_AppendItem
|
|
(savedPkixLoggersDebugTrace,
|
|
(PKIX_PL_Object *) addLogger,
|
|
plContext),
|
|
PKIX_LISTAPPENDITEMFAILED);
|
|
}
|
|
|
|
PKIX_DECREF(addLogger);
|
|
|
|
}
|
|
|
|
cleanup:
|
|
|
|
PKIX_DECREF(dupLogger);
|
|
PKIX_DECREF(addLogger);
|
|
|
|
/* Restore logging capability */
|
|
pkixLoggersErrors = savedPkixLoggersErrors;
|
|
pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
|
|
|
|
if (locked) {
|
|
PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
|
|
PKIX_MONITORLOCKEXITFAILED);
|
|
}
|
|
|
|
PKIX_RETURN(LOGGER);
|
|
}
|