wolfSSL SSL/TLS library, support up to TLS1.3

Dependents:   CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers logging.c Source File

logging.c

00001 /* logging.c
00002  *
00003  * Copyright (C) 2006-2020 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfssl/wolfcrypt/settings.h>
00028 
00029 #include <wolfssl/wolfcrypt/logging.h >
00030 #include <wolfssl/wolfcrypt/error-crypt.h >
00031 #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
00032 /* avoid adding WANT_READ and WANT_WRITE to error queue */
00033 #include <wolfssl/error-ssl.h>
00034 #endif
00035 
00036 #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
00037 static wolfSSL_Mutex debug_mutex; /* mutex for access to debug structure */
00038 
00039 /* accessing any node from the queue should be wrapped in a lock of
00040  * debug_mutex */
00041 static void* wc_error_heap;
00042 struct wc_error_queue {
00043     void*  heap; /* the heap hint used with nodes creation */
00044     struct wc_error_queue* next;
00045     struct wc_error_queue* prev;
00046     char   error[WOLFSSL_MAX_ERROR_SZ];
00047     char   file[WOLFSSL_MAX_ERROR_SZ];
00048     int    value;
00049     int    line;
00050 };
00051 volatile struct wc_error_queue* wc_errors;
00052 static struct wc_error_queue* wc_current_node;
00053 static struct wc_error_queue* wc_last_node;
00054 /* pointer to last node in queue to make insertion O(1) */
00055 #endif
00056 
00057 #ifdef WOLFSSL_FUNC_TIME
00058 /* WARNING: This code is only to be used for debugging performance.
00059  *          The code is not thread-safe.
00060  *          Do not use WOLFSSL_FUNC_TIME in production code.
00061  */
00062 static double wc_func_start[WC_FUNC_COUNT];
00063 static double wc_func_time[WC_FUNC_COUNT] = { 0, };
00064 static const char* wc_func_name[WC_FUNC_COUNT] = {
00065     "SendHelloRequest",
00066     "DoHelloRequest",
00067     "SendClientHello",
00068     "DoClientHello",
00069     "SendServerHello",
00070     "DoServerHello",
00071     "SendEncryptedExtensions",
00072     "DoEncryptedExtensions",
00073     "SendCertificateRequest",
00074     "DoCertificateRequest",
00075     "SendCertificate",
00076     "DoCertificate",
00077     "SendCertificateVerify",
00078     "DoCertificateVerify",
00079     "SendFinished",
00080     "DoFinished",
00081     "SendKeyUpdate",
00082     "DoKeyUpdate",
00083     "SendEarlyData",
00084     "DoEarlyData",
00085     "SendNewSessionTicket",
00086     "DoNewSessionTicket",
00087     "SendServerHelloDone",
00088     "DoServerHelloDone",
00089     "SendTicket",
00090     "DoTicket",
00091     "SendClientKeyExchange",
00092     "DoClientKeyExchange",
00093     "SendCertificateStatus",
00094     "DoCertificateStatus",
00095     "SendServerKeyExchange",
00096     "DoServerKeyExchange",
00097     "SendEarlyData",
00098     "DoEarlyData",
00099 };
00100 
00101 #include <sys/time.h>
00102 
00103 /* WARNING: This function is not portable. */
00104 static WC_INLINE double current_time(int reset)
00105 {
00106     struct timeval tv;
00107     gettimeofday(&tv, 0);
00108     (void)reset;
00109 
00110     return (double)tv.tv_sec + (double)tv.tv_usec / 1000000;
00111 }
00112 #endif /* WOLFSSL_FUNC_TIME */
00113 
00114 #ifdef DEBUG_WOLFSSL
00115 
00116 /* Set these to default values initially. */
00117 static wolfSSL_Logging_cb log_function = NULL;
00118 static int loggingEnabled = 0;
00119 
00120 #if defined(WOLFSSL_APACHE_MYNEWT)
00121 #include "log/log.h"
00122 static struct log mynewt_log;
00123 #endif /* WOLFSSL_APACHE_MYNEWT */
00124 
00125 #endif /* DEBUG_WOLFSSL */
00126 
00127 
00128 /* allow this to be set to NULL, so logs can be redirected to default output */
00129 int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb f)
00130 {
00131 #ifdef DEBUG_WOLFSSL
00132     log_function = f;
00133     return 0;
00134 #else
00135     (void)f;
00136     return NOT_COMPILED_IN;
00137 #endif
00138 }
00139 
00140 /* allow this to be set to NULL, so logs can be redirected to default output */
00141 wolfSSL_Logging_cb wolfSSL_GetLoggingCb(void)
00142 {
00143 #ifdef DEBUG_WOLFSSL
00144     return log_function;
00145 #else
00146     return NULL;
00147 #endif
00148 }
00149 
00150 
00151 int wolfSSL_Debugging_ON(void)
00152 {
00153 #ifdef DEBUG_WOLFSSL
00154     loggingEnabled = 1;
00155 #if defined(WOLFSSL_APACHE_MYNEWT)
00156     log_register("wolfcrypt", &mynewt_log, &log_console_handler, NULL, LOG_SYSLEVEL);
00157 #endif /* WOLFSSL_APACHE_MYNEWT */
00158     return 0;
00159 #else
00160     return NOT_COMPILED_IN;
00161 #endif
00162 }
00163 
00164 
00165 void wolfSSL_Debugging_OFF(void)
00166 {
00167 #ifdef DEBUG_WOLFSSL
00168     loggingEnabled = 0;
00169 #endif
00170 }
00171 
00172 #ifdef WOLFSSL_FUNC_TIME
00173 /* WARNING: This code is only to be used for debugging performance.
00174  *          The code is not thread-safe.
00175  *          Do not use WOLFSSL_FUNC_TIME in production code.
00176  */
00177 void WOLFSSL_START(int funcNum)
00178 {
00179     double now = current_time(0) * 1000.0;
00180 #ifdef WOLFSSL_FUNC_TIME_LOG
00181     fprintf(stderr, "%17.3f: START - %s\n", now, wc_func_name[funcNum]);
00182 #endif
00183     wc_func_start[funcNum] = now;
00184 }
00185 
00186 void WOLFSSL_END(int funcNum)
00187 {
00188     double now = current_time(0) * 1000.0;
00189     wc_func_time[funcNum] += now - wc_func_start[funcNum];
00190 #ifdef WOLFSSL_FUNC_TIME_LOG
00191     fprintf(stderr, "%17.3f: END   - %s\n", now, wc_func_name[funcNum]);
00192 #endif
00193 }
00194 
00195 void WOLFSSL_TIME(int count)
00196 {
00197     int i;
00198     double avg, total = 0;
00199 
00200     for (i = 0; i < WC_FUNC_COUNT; i++) {
00201         if (wc_func_time[i] > 0) {
00202             avg = wc_func_time[i] / count;
00203             fprintf(stderr, "%8.3f ms: %s\n", avg, wc_func_name[i]);
00204             total += avg;
00205         }
00206     }
00207     fprintf(stderr, "%8.3f ms\n", total);
00208 }
00209 #endif
00210 
00211 #ifdef DEBUG_WOLFSSL
00212 
00213 #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
00214     /* see wc_port.h for fio.h and nio.h includes */
00215 #elif defined(WOLFSSL_SGX)
00216     /* Declare sprintf for ocall */
00217     int sprintf(char* buf, const char *fmt, ...);
00218 #elif defined(WOLFSSL_DEOS)
00219 #elif defined(MICRIUM)
00220     #if (BSP_SER_COMM_EN  == DEF_ENABLED)
00221         #include <bsp_ser.h>
00222     #endif
00223 #elif defined(WOLFSSL_USER_LOG)
00224     /* user includes their own headers */
00225 #elif defined(WOLFSSL_ESPIDF)
00226     #include "esp_types.h"
00227     #include "esp_log.h"
00228 #elif defined(WOLFSSL_TELIT_M2MB)
00229     #include <stdio.h>
00230     #include "m2m_log.h"
00231 #elif defined(WOLFSSL_ANDROID_DEBUG)
00232     #include <android/log.h>
00233 #else
00234     #include <stdio.h>   /* for default printf stuff */
00235 #endif
00236 
00237 #if defined(THREADX) && !defined(THREADX_NO_DC_PRINTF)
00238     int dc_log_printf(char*, ...);
00239 #endif
00240 
00241 static void wolfssl_log(const int logLevel, const char *const logMessage)
00242 {
00243     if (log_function)
00244         log_function(logLevel, logMessage);
00245     else {
00246 #if defined(WOLFSSL_USER_LOG)
00247         WOLFSSL_USER_LOG(logMessage);
00248 #elif defined(WOLFSSL_LOG_PRINTF)
00249         printf("%s\n", logMessage);
00250 
00251 #elif defined(THREADX) && !defined(THREADX_NO_DC_PRINTF)
00252         dc_log_printf("%s\n", logMessage);
00253 #elif defined(WOLFSSL_DEOS)
00254         printf("%s\r\n", logMessage);
00255 #elif defined(MICRIUM)
00256         BSP_Ser_Printf("%s\r\n", logMessage);
00257 #elif defined(WOLFSSL_MDK_ARM)
00258         fflush(stdout) ;
00259         printf("%s\n", logMessage);
00260         fflush(stdout) ;
00261 #elif defined(WOLFSSL_UTASKER)
00262         fnDebugMsg((char*)logMessage);
00263         fnDebugMsg("\r\n");
00264 #elif defined(MQX_USE_IO_OLD)
00265         fprintf(_mqxio_stderr, "%s\n", logMessage);
00266 
00267 #elif defined(WOLFSSL_APACHE_MYNEWT)
00268         LOG_DEBUG(&mynewt_log, LOG_MODULE_DEFAULT, "%s\n", logMessage);
00269 #elif defined(WOLFSSL_ESPIDF)
00270         ESP_LOGI("wolfssl", "%s", logMessage);
00271 #elif defined(WOLFSSL_ZEPHYR)
00272         printk("%s\n", logMessage);
00273 #elif defined(WOLFSSL_TELIT_M2MB)
00274         M2M_LOG_INFO("%s\n", logMessage);
00275 #elif defined(WOLFSSL_ANDROID_DEBUG)
00276         __android_log_print(ANDROID_LOG_VERBOSE, "[wolfSSL]", "%s", logMessage);
00277 #else
00278         fprintf(stderr, "%s\n", logMessage);
00279 #endif
00280     }
00281 }
00282 
00283 #ifndef WOLFSSL_DEBUG_ERRORS_ONLY
00284 void WOLFSSL_MSG(const char* msg)
00285 {
00286     if (loggingEnabled)
00287         wolfssl_log(INFO_LOG , msg);
00288 }
00289 
00290 #ifndef LINE_LEN
00291 #define LINE_LEN 16
00292 #endif
00293 void WOLFSSL_BUFFER(const byte* buffer, word32 length)
00294 {
00295     int i, buflen = (int)length, bufidx;
00296     char line[(LINE_LEN * 4) + 3]; /* \t00..0F | chars...chars\0 */
00297 
00298     if (!loggingEnabled) {
00299         return;
00300     }
00301 
00302     if (!buffer) {
00303         wolfssl_log(INFO_LOG, "\tNULL");
00304         return;
00305     }
00306 
00307     while (buflen > 0) {
00308         bufidx = 0;
00309         XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "\t");
00310         bufidx++;
00311 
00312         for (i = 0; i < LINE_LEN; i++) {
00313             if (i < buflen) {
00314                 XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "%02x ", buffer[i]);
00315             }
00316             else {
00317                 XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "   ");
00318             }
00319             bufidx += 3;
00320         }
00321 
00322         XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "| ");
00323         bufidx++;
00324 
00325         for (i = 0; i < LINE_LEN; i++) {
00326             if (i < buflen) {
00327                 XSNPRINTF(&line[bufidx], sizeof(line)-bufidx,
00328                      "%c", 31 < buffer[i] && buffer[i] < 127 ? buffer[i] : '.');
00329                 bufidx++;
00330             }
00331         }
00332 
00333         wolfssl_log(INFO_LOG, line);
00334         buffer += LINE_LEN;
00335         buflen -= LINE_LEN;
00336     }
00337 }
00338 
00339 
00340 void WOLFSSL_ENTER(const char* msg)
00341 {
00342     if (loggingEnabled) {
00343         char buffer[WOLFSSL_MAX_ERROR_SZ];
00344         XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Entering %s", msg);
00345         wolfssl_log(ENTER_LOG , buffer);
00346     }
00347 }
00348 
00349 
00350 void WOLFSSL_LEAVE(const char* msg, int ret)
00351 {
00352     if (loggingEnabled) {
00353         char buffer[WOLFSSL_MAX_ERROR_SZ];
00354         XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Leaving %s, return %d",
00355                 msg, ret);
00356         wolfssl_log(LEAVE_LOG , buffer);
00357     }
00358 }
00359 
00360 WOLFSSL_API int WOLFSSL_IS_DEBUG_ON(void)
00361 {
00362     return loggingEnabled;
00363 }
00364 #endif /* !WOLFSSL_DEBUG_ERRORS_ONLY */
00365 #endif /* DEBUG_WOLFSSL */
00366 
00367 /*
00368  * When using OPENSSL_EXTRA or DEBUG_WOLFSSL_VERBOSE macro then WOLFSSL_ERROR is
00369  * mapped to new function WOLFSSL_ERROR_LINE which gets the line # and function
00370  * name where WOLFSSL_ERROR is called at.
00371  */
00372 #if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || \
00373     defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
00374     defined(OPENSSL_EXTRA)
00375 
00376 #if (defined(OPENSSL_EXTRA) && !defined(_WIN32) && !defined(NO_ERROR_QUEUE)) \
00377     || defined(DEBUG_WOLFSSL_VERBOSE)
00378 void WOLFSSL_ERROR_LINE(int error, const char* func, unsigned int line,
00379         const char* file, void* usrCtx)
00380 #else
00381 void WOLFSSL_ERROR(int error)
00382 #endif
00383 {
00384 #ifdef WOLFSSL_ASYNC_CRYPT
00385     if (error != WC_PENDING_E)
00386 #endif
00387     {
00388         char buffer[WOLFSSL_MAX_ERROR_SZ];
00389 
00390     #if (defined(OPENSSL_EXTRA) && !defined(_WIN32) && \
00391             !defined(NO_ERROR_QUEUE)) || defined(DEBUG_WOLFSSL_VERBOSE)
00392         (void)usrCtx; /* a user ctx for future flexibility */
00393         (void)func;
00394 
00395         if (wc_LockMutex(&debug_mutex) != 0) {
00396             WOLFSSL_MSG("Lock debug mutex failed");
00397             XSNPRINTF(buffer, sizeof(buffer),
00398                     "wolfSSL error occurred, error = %d", error);
00399         }
00400         else {
00401             #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
00402             /* If running in compatibility mode do not add want read and
00403                want right to error queue */
00404             if (error != WANT_READ && error != WANT_WRITE) {
00405             #endif
00406             if (error < 0)
00407                 error = error - (2 * error); /* get absolute value */
00408             XSNPRINTF(buffer, sizeof(buffer),
00409                     "wolfSSL error occurred, error = %d line:%d file:%s",
00410                     error, line, file);
00411             if (wc_AddErrorNode(error, line, buffer, (char*)file) != 0) {
00412                 WOLFSSL_MSG("Error creating logging node");
00413                 /* with void function there is no return here, continue on
00414                  * to unlock mutex and log what buffer was created. */
00415             }
00416             #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
00417             }
00418             else {
00419                 XSNPRINTF(buffer, sizeof(buffer),
00420                     "wolfSSL error occurred, error = %d", error);
00421 
00422             }
00423             #endif
00424 
00425             wc_UnLockMutex(&debug_mutex);
00426         }
00427     #else
00428         XSNPRINTF(buffer, sizeof(buffer),
00429                 "wolfSSL error occurred, error = %d", error);
00430     #endif
00431 
00432     #ifdef DEBUG_WOLFSSL
00433         if (loggingEnabled)
00434             wolfssl_log(ERROR_LOG , buffer);
00435     #endif
00436     }
00437 }
00438 
00439 void WOLFSSL_ERROR_MSG(const char* msg)
00440 {
00441 #ifdef DEBUG_WOLFSSL
00442     if (loggingEnabled)
00443         wolfssl_log(ERROR_LOG , msg);
00444 #else
00445     (void)msg;
00446 #endif
00447 }
00448 
00449 #endif  /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
00450 
00451 #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
00452 /* Internal function that is called by wolfCrypt_Init() */
00453 int wc_LoggingInit(void)
00454 {
00455     if (wc_InitMutex(&debug_mutex) != 0) {
00456         WOLFSSL_MSG("Bad Init Mutex");
00457         return BAD_MUTEX_E;
00458     }
00459     wc_errors          = NULL;
00460     wc_current_node    = NULL;
00461     wc_last_node       = NULL;
00462 
00463     return 0;
00464 }
00465 
00466 
00467 /* internal function that is called by wolfCrypt_Cleanup */
00468 int wc_LoggingCleanup(void)
00469 {
00470     /* clear logging entries */
00471     wc_ClearErrorNodes();
00472 
00473     /* free mutex */
00474     if (wc_FreeMutex(&debug_mutex) != 0) {
00475         WOLFSSL_MSG("Bad Mutex free");
00476         return BAD_MUTEX_E;
00477     }
00478     return 0;
00479 }
00480 
00481 
00482 /* peek at an error node
00483  *
00484  * idx : if -1 then the most recent node is looked at, otherwise search
00485  *         through queue for node at the given index
00486  * file  : pointer to internal file string
00487  * reason : pointer to internal error reason
00488  * line  : line number that error happened at
00489  *
00490  * Returns a negative value in error case, on success returns the nodes error
00491  * value which is positive (absolute value)
00492  */
00493 int wc_PeekErrorNode(int idx, const char **file, const char **reason,
00494         int *line)
00495 {
00496     struct wc_error_queue* err;
00497 
00498     if (wc_LockMutex(&debug_mutex) != 0) {
00499         WOLFSSL_MSG("Lock debug mutex failed");
00500         return BAD_MUTEX_E;
00501     }
00502 
00503     if (idx < 0) {
00504         err = wc_last_node;
00505     }
00506     else {
00507         int i;
00508 
00509         err = (struct wc_error_queue*)wc_errors;
00510         for (i = 0; i < idx; i++) {
00511             if (err == NULL) {
00512                 WOLFSSL_MSG("Error node not found. Bad index?");
00513                 wc_UnLockMutex(&debug_mutex);
00514                 return BAD_FUNC_ARG;
00515             }
00516             err = err->next;
00517         }
00518     }
00519 
00520     if (err == NULL) {
00521         WOLFSSL_MSG("No Errors in queue");
00522         wc_UnLockMutex(&debug_mutex);
00523         return BAD_STATE_E;
00524     }
00525 
00526     if (file != NULL) {
00527         *file = err->file;
00528     }
00529 
00530     if (reason != NULL) {
00531         *reason = err->error;
00532     }
00533 
00534     if (line != NULL) {
00535         *line = err->line;
00536     }
00537 
00538     wc_UnLockMutex(&debug_mutex);
00539 
00540     return err->value;
00541 }
00542 
00543 
00544 /* Pulls the current node from error queue and increments current state.
00545  * Note: this does not delete nodes because input arguments are pointing to
00546  *       node buffers.
00547  *
00548  * file   pointer to file that error was in. Can be NULL to return no file.
00549  * reason error string giving reason for error. Can be NULL to return no reason.
00550  * line   return line number of where error happened.
00551  *
00552  * returns the error value on success and BAD_MUTEX_E or BAD_STATE_E on failure
00553  */
00554 int wc_PullErrorNode(const char **file, const char **reason, int *line)
00555 {
00556     struct wc_error_queue* err;
00557     int value;
00558 
00559     if (wc_LockMutex(&debug_mutex) != 0) {
00560         WOLFSSL_MSG("Lock debug mutex failed");
00561         return BAD_MUTEX_E;
00562     }
00563 
00564     err = wc_current_node;
00565     if (err == NULL) {
00566         WOLFSSL_MSG("No Errors in queue");
00567         wc_UnLockMutex(&debug_mutex);
00568         return BAD_STATE_E;
00569     }
00570 
00571     if (file != NULL) {
00572         *file = err->file;
00573     }
00574 
00575     if (reason != NULL) {
00576         *reason = err->error;
00577     }
00578 
00579     if (line != NULL) {
00580         *line = err->line;
00581     }
00582 
00583     value = err->value;
00584     wc_current_node = err->next;
00585     wc_UnLockMutex(&debug_mutex);
00586 
00587     return value;
00588 }
00589 
00590 
00591 /* create new error node and add it to the queue
00592  * buffers are assumed to be of size WOLFSSL_MAX_ERROR_SZ for this internal
00593  * function. debug_mutex should be locked before a call to this function. */
00594 int wc_AddErrorNode(int error, int line, char* buf, char* file)
00595 {
00596 #if defined(NO_ERROR_QUEUE)
00597     (void)error;
00598     (void)line;
00599     (void)buf;
00600     (void)file;
00601     WOLFSSL_MSG("Error queue turned off, can not add nodes");
00602 #else
00603     struct wc_error_queue* err;
00604     err = (struct wc_error_queue*)XMALLOC(
00605             sizeof(struct wc_error_queue), wc_error_heap, DYNAMIC_TYPE_LOG);
00606     if (err == NULL) {
00607         WOLFSSL_MSG("Unable to create error node for log");
00608         return MEMORY_E;
00609     }
00610     else {
00611         int sz;
00612 
00613         XMEMSET(err, 0, sizeof(struct wc_error_queue));
00614         err->heap = wc_error_heap;
00615         sz = (int)XSTRLEN(buf);
00616         if (sz > WOLFSSL_MAX_ERROR_SZ - 1) {
00617             sz = WOLFSSL_MAX_ERROR_SZ - 1;
00618         }
00619         if (sz > 0) {
00620             XMEMCPY(err->error, buf, sz);
00621         }
00622 
00623         sz = (int)XSTRLEN(file);
00624         if (sz > WOLFSSL_MAX_ERROR_SZ - 1) {
00625             sz = WOLFSSL_MAX_ERROR_SZ - 1;
00626         }
00627         if (sz > 0) {
00628             XMEMCPY(err->file, file, sz);
00629         }
00630 
00631         err->value = error;
00632         err->line  = line;
00633 
00634         /* make sure is terminated */
00635         err->error[WOLFSSL_MAX_ERROR_SZ - 1] = '\0';
00636         err->file[WOLFSSL_MAX_ERROR_SZ - 1]  = '\0';
00637 
00638 
00639         /* since is queue place new node at last of the list */
00640         if (wc_last_node == NULL) {
00641             /* case of first node added to queue */
00642             if (wc_errors != NULL) {
00643                 /* check for unexpected case before over writing wc_errors */
00644                 WOLFSSL_MSG("ERROR in adding new node to logging queue!!\n");
00645                 /* In the event both wc_last_node and wc_errors are NULL, err
00646                  * goes unassigned to external wc_errors, wc_last_node. Free
00647                  * err in this instance since wc_ClearErrorNodes will not
00648                  */
00649                 XFREE(err, wc_error_heap, DYNAMIC_TYPE_LOG);
00650             }
00651             else {
00652                 wc_errors    = err;
00653                 wc_last_node = err;
00654                 wc_current_node = err;
00655             }
00656         }
00657         else {
00658             wc_last_node->next = err;
00659             err->prev = wc_last_node;
00660             wc_last_node = err;
00661 
00662             /* check the case where have read to the end of the queue and the
00663              * current node to read needs updated */
00664             if (wc_current_node == NULL) {
00665                 wc_current_node = err;
00666             }
00667         }
00668     }
00669 #endif
00670     return 0;
00671 }
00672 
00673 /* Removes the error node at the specified index.
00674  * idx : if -1 then the most recent node is looked at, otherwise search
00675  *         through queue for node at the given index
00676  */
00677 void wc_RemoveErrorNode(int idx)
00678 {
00679     struct wc_error_queue* current;
00680 
00681     if (wc_LockMutex(&debug_mutex) != 0) {
00682         WOLFSSL_MSG("Lock debug mutex failed");
00683         return;
00684     }
00685 
00686     if (idx == -1)
00687         current = wc_last_node;
00688     else {
00689         current = (struct wc_error_queue*)wc_errors;
00690         for (; current != NULL && idx > 0; idx--)
00691              current = current->next;
00692     }
00693     if (current != NULL) {
00694         if (current->prev != NULL)
00695             current->prev->next = current->next;
00696         if (current->next != NULL)
00697             current->next->prev = current->prev;
00698         if (wc_last_node == current)
00699             wc_last_node = current->prev;
00700         if (wc_errors == current)
00701             wc_errors = current->next;
00702         if (wc_current_node == current)
00703             wc_current_node = current->next;
00704         XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
00705     }
00706 
00707     wc_UnLockMutex(&debug_mutex);
00708 }
00709 
00710 
00711 /* Clears out the list of error nodes.
00712  */
00713 void wc_ClearErrorNodes(void)
00714 {
00715 #if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX) || \
00716     defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
00717 
00718     if (wc_LockMutex(&debug_mutex) != 0) {
00719         WOLFSSL_MSG("Lock debug mutex failed");
00720         return;
00721     }
00722 
00723     /* free all nodes from error queue */
00724     {
00725         struct wc_error_queue* current;
00726         struct wc_error_queue* next;
00727 
00728         current = (struct wc_error_queue*)wc_errors;
00729         while (current != NULL) {
00730             next = current->next;
00731             XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
00732             current = next;
00733         }
00734     }
00735 
00736     wc_errors       = NULL;
00737     wc_last_node    = NULL;
00738     wc_current_node = NULL;
00739     wc_UnLockMutex(&debug_mutex);
00740 #endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX */
00741 }
00742 
00743 int wc_SetLoggingHeap(void* h)
00744 {
00745     if (wc_LockMutex(&debug_mutex) != 0) {
00746         WOLFSSL_MSG("Lock debug mutex failed");
00747         return BAD_MUTEX_E;
00748     }
00749     wc_error_heap = h;
00750     wc_UnLockMutex(&debug_mutex);
00751     return 0;
00752 }
00753 
00754 
00755 /* frees all nodes in the queue
00756  *
00757  * id  this is the thread id
00758  */
00759 int wc_ERR_remove_state(void)
00760 {
00761     struct wc_error_queue* current;
00762     struct wc_error_queue* next;
00763 
00764     if (wc_LockMutex(&debug_mutex) != 0) {
00765         WOLFSSL_MSG("Lock debug mutex failed");
00766         return BAD_MUTEX_E;
00767     }
00768 
00769     /* free all nodes from error queue */
00770     current = (struct wc_error_queue*)wc_errors;
00771     while (current != NULL) {
00772         next = current->next;
00773         XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
00774         current = next;
00775     }
00776 
00777     wc_errors          = NULL;
00778     wc_last_node       = NULL;
00779 
00780     wc_UnLockMutex(&debug_mutex);
00781 
00782     return 0;
00783 }
00784 
00785 #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
00786 /* empties out the error queue into the file */
00787 static int wc_ERR_dump_to_file (const char *str, size_t len, void *u)
00788 {
00789     XFILE fp = (XFILE ) u;
00790     fprintf(fp, "%-*.*s\n", (int)len, (int)len, str);
00791     return 0;
00792 }
00793 
00794 /* This callback allows the application to provide a custom error printing
00795  * function. */
00796 void wc_ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u),
00797                             void *u)
00798 {
00799     WOLFSSL_ENTER("wc_ERR_print_errors_cb");
00800 
00801     if (cb == NULL) {
00802         /* Invalid param */
00803         return;
00804     }
00805 
00806     if (wc_LockMutex(&debug_mutex) != 0)
00807     {
00808         WOLFSSL_MSG("Lock debug mutex failed");
00809     }
00810     else
00811     {
00812         /* free all nodes from error queue and print them to file */
00813         struct wc_error_queue *current;
00814         struct wc_error_queue *next;
00815 
00816         current = (struct wc_error_queue *)wc_errors;
00817         while (current != NULL)
00818         {
00819             next = current->next;
00820             cb(current->error, strlen(current->error), u);
00821             XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
00822             current = next;
00823         }
00824 
00825         /* set global pointers to match having been freed */
00826         wc_errors = NULL;
00827         wc_last_node = NULL;
00828 
00829         wc_UnLockMutex(&debug_mutex);
00830     }
00831 }
00832 
00833 void wc_ERR_print_errors_fp(XFILE fp)
00834 {
00835     WOLFSSL_ENTER("wc_ERR_print_errors_fp");
00836 
00837     /* Send all errors to the wc_ERR_dump_to_file function */
00838     wc_ERR_print_errors_cb(wc_ERR_dump_to_file, fp);
00839 }
00840 
00841 #endif /* !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) */
00842 
00843 #endif /* defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) */
00844