Xuyi Wang / wolfcrypt

Dependents:   OS

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-2017 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 <wolfcrypt/settings.h>
00028 
00029 /* submitted by eof */
00030 
00031 #include <wolfcrypt/logging.h>
00032 #include <wolfcrypt/error-crypt.h>
00033 #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
00034 /* avoid adding WANT_READ and WANT_WRITE to error queue */
00035 #include <wolfssl/error-ssl.h>
00036 #endif
00037 
00038 #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
00039 static wolfSSL_Mutex debug_mutex; /* mutex for access to debug structure */
00040 
00041 /* accessing any node from the queue should be wrapped in a lock of
00042  * debug_mutex */
00043 static void* wc_error_heap;
00044 struct wc_error_queue {
00045     void*  heap; /* the heap hint used with nodes creation */
00046     struct wc_error_queue* next;
00047     struct wc_error_queue* prev;
00048     char   error[WOLFSSL_MAX_ERROR_SZ];
00049     char   file[WOLFSSL_MAX_ERROR_SZ];
00050     int    value;
00051     int    line;
00052 };
00053 volatile struct wc_error_queue* wc_errors;
00054 static struct wc_error_queue* wc_current_node;
00055 static struct wc_error_queue* wc_last_node;
00056 /* pointer to last node in queue to make insertion O(1) */
00057 #endif
00058 
00059 #ifdef WOLFSSL_FUNC_TIME
00060 /* WARNING: This code is only to be used for debugging performance.
00061  *          The code is not thread-safe.
00062  *          Do not use WOLFSSL_FUNC_TIME in production code.
00063  */
00064 static double wc_func_start[WC_FUNC_COUNT];
00065 static double wc_func_time[WC_FUNC_COUNT] = { 0, };
00066 static const char* wc_func_name[WC_FUNC_COUNT] = {
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 #endif /* DEBUG_WOLFSSL */
00121 
00122 
00123 /* allow this to be set to NULL, so logs can be redirected to default output */
00124 int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb f)
00125 {
00126 #ifdef DEBUG_WOLFSSL
00127     log_function = f;
00128     return 0;
00129 #else
00130     (void)f;
00131     return NOT_COMPILED_IN;
00132 #endif
00133 }
00134 
00135 
00136 int wolfSSL_Debugging_ON(void)
00137 {
00138 #ifdef DEBUG_WOLFSSL
00139     loggingEnabled = 1;
00140     return 0;
00141 #else
00142     return NOT_COMPILED_IN;
00143 #endif
00144 }
00145 
00146 
00147 void wolfSSL_Debugging_OFF(void)
00148 {
00149 #ifdef DEBUG_WOLFSSL
00150     loggingEnabled = 0;
00151 #endif
00152 }
00153 
00154 #ifdef WOLFSSL_FUNC_TIME
00155 /* WARNING: This code is only to be used for debugging performance.
00156  *          The code is not thread-safe.
00157  *          Do not use WOLFSSL_FUNC_TIME in production code.
00158  */
00159 void WOLFSSL_START(int funcNum)
00160 {
00161     double now = current_time(0) * 1000.0;
00162 #ifdef WOLFSSL_FUNC_TIME_LOG
00163     fprintf(stderr, "%17.3f: START - %s\n", now, wc_func_name[funcNum]);
00164 #endif
00165     wc_func_start[funcNum] = now;
00166 }
00167 
00168 void WOLFSSL_END(int funcNum)
00169 {
00170     double now = current_time(0) * 1000.0;
00171     wc_func_time[funcNum] += now - wc_func_start[funcNum];
00172 #ifdef WOLFSSL_FUNC_TIME_LOG
00173     fprintf(stderr, "%17.3f: END   - %s\n", now, wc_func_name[funcNum]);
00174 #endif
00175 }
00176 
00177 void WOLFSSL_TIME(int count)
00178 {
00179     int i;
00180     double avg, total = 0;
00181 
00182     for (i = 0; i < WC_FUNC_COUNT; i++) {
00183         if (wc_func_time[i] > 0) {
00184             avg = wc_func_time[i] / count;
00185             fprintf(stderr, "%8.3f ms: %s\n", avg, wc_func_name[i]);
00186             total += avg;
00187         }
00188     }
00189     fprintf(stderr, "%8.3f ms\n", total);
00190 }
00191 #endif
00192 
00193 #ifdef DEBUG_WOLFSSL
00194 
00195 #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
00196     #if MQX_USE_IO_OLD
00197         #include <fio.h>
00198     #else
00199         #include <nio.h>
00200     #endif
00201 #elif defined(WOLFSSL_SGX)
00202     /* Declare sprintf for ocall */
00203     int sprintf(char* buf, const char *fmt, ...);
00204 #elif defined(MICRIUM)
00205     #include <bsp_ser.h>
00206 #elif defined(WOLFSSL_USER_LOG)
00207     /* user includes their own headers */
00208 #else
00209     #include <stdio.h>   /* for default printf stuff */
00210 #endif
00211 
00212 #if defined(THREADX) && !defined(THREADX_NO_DC_PRINTF)
00213     int dc_log_printf(char*, ...);
00214 #endif
00215 
00216 static void wolfssl_log(const int logLevel, const char *const logMessage)
00217 {
00218     if (log_function)
00219         log_function(logLevel, logMessage);
00220     else {
00221 #if defined(WOLFSSL_USER_LOG)
00222         WOLFSSL_USER_LOG(logMessage);
00223 #elif defined(WOLFSSL_LOG_PRINTF)
00224         printf("%s\n", logMessage);
00225 
00226 #elif defined(THREADX) && !defined(THREADX_NO_DC_PRINTF)
00227         dc_log_printf("%s\n", logMessage);
00228 #elif defined(MICRIUM)
00229         BSP_Ser_Printf("%s\r\n", logMessage);
00230 #elif defined(WOLFSSL_MDK_ARM)
00231         fflush(stdout) ;
00232         printf("%s\n", logMessage);
00233         fflush(stdout) ;
00234 #elif defined(WOLFSSL_UTASKER)
00235         fnDebugMsg((char*)logMessage);
00236         fnDebugMsg("\r\n");
00237 #elif defined(MQX_USE_IO_OLD)
00238         fprintf(_mqxio_stderr, "%s\n", logMessage);
00239 
00240 #else
00241         fprintf(stderr, "%s\n", logMessage);
00242 #endif
00243     }
00244 }
00245 
00246 #ifndef WOLFSSL_DEBUG_ERRORS_ONLY
00247 void WOLFSSL_MSG(const char* msg)
00248 {
00249     if (loggingEnabled)
00250         wolfssl_log(INFO_LOG , msg);
00251 }
00252 
00253 
00254 void WOLFSSL_BUFFER(const byte* buffer, word32 length)
00255 {
00256     #define LINE_LEN 16
00257 
00258     if (loggingEnabled) {
00259         word32 i;
00260         char line[80];
00261 
00262         if (!buffer) {
00263             wolfssl_log(INFO_LOG, "\tNULL");
00264 
00265             return;
00266         }
00267 
00268         sprintf(line, "\t");
00269 
00270         for (i = 0; i < LINE_LEN; i++) {
00271             if (i < length)
00272                 sprintf(line + 1 + i * 3,"%02x ", buffer[i]);
00273             else
00274                 sprintf(line + 1 + i * 3, "   ");
00275         }
00276 
00277         sprintf(line + 1 + LINE_LEN * 3, "| ");
00278 
00279         for (i = 0; i < LINE_LEN; i++)
00280             if (i < length)
00281                 sprintf(line + 3 + LINE_LEN * 3 + i,
00282                      "%c", 31 < buffer[i] && buffer[i] < 127 ? buffer[i] : '.');
00283 
00284         wolfssl_log(INFO_LOG, line);
00285 
00286         if (length > LINE_LEN)
00287             WOLFSSL_BUFFER(buffer + LINE_LEN, length - LINE_LEN);
00288     }
00289 }
00290 
00291 
00292 void WOLFSSL_ENTER(const char* msg)
00293 {
00294     if (loggingEnabled) {
00295         char buffer[WOLFSSL_MAX_ERROR_SZ];
00296         XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Entering %s", msg);
00297         wolfssl_log(ENTER_LOG , buffer);
00298     }
00299 }
00300 
00301 
00302 void WOLFSSL_LEAVE(const char* msg, int ret)
00303 {
00304     if (loggingEnabled) {
00305         char buffer[WOLFSSL_MAX_ERROR_SZ];
00306         XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Leaving %s, return %d",
00307                 msg, ret);
00308         wolfssl_log(LEAVE_LOG , buffer);
00309     }
00310 }
00311 #endif /* !WOLFSSL_DEBUG_ERRORS_ONLY */
00312 #endif /* DEBUG_WOLFSSL */
00313 
00314 /*
00315  * When using OPENSSL_EXTRA or DEBUG_WOLFSSL_VERBOSE macro then WOLFSSL_ERROR is
00316  * mapped to new funtion WOLFSSL_ERROR_LINE which gets the line # and function
00317  * name where WOLFSSL_ERROR is called at.
00318  */
00319 #if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || \
00320     defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
00321 
00322 #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
00323 void WOLFSSL_ERROR_LINE(int error, const char* func, unsigned int line,
00324         const char* file, void* usrCtx)
00325 #else
00326 void WOLFSSL_ERROR(int error)
00327 #endif
00328 {
00329 #ifdef WOLFSSL_ASYNC_CRYPT
00330     if (error != WC_PENDING_E)
00331 #endif
00332     {
00333         char buffer[WOLFSSL_MAX_ERROR_SZ];
00334 
00335     #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
00336         (void)usrCtx; /* a user ctx for future flexibility */
00337         (void)func;
00338 
00339         if (wc_LockMutex(&debug_mutex) != 0) {
00340             WOLFSSL_MSG("Lock debug mutex failed");
00341             XSNPRINTF(buffer, sizeof(buffer),
00342                     "wolfSSL error occurred, error = %d", error);
00343         }
00344         else {
00345             #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
00346             /* If running in compatibility mode do not add want read and
00347                want right to error queue */
00348             if (error != WANT_READ && error != WANT_WRITE) {
00349             #endif
00350             if (error < 0)
00351                 error = error - (2 * error); /* get absolute value */
00352             XSNPRINTF(buffer, sizeof(buffer),
00353                     "wolfSSL error occurred, error = %d line:%d file:%s",
00354                     error, line, file);
00355             if (wc_AddErrorNode(error, line, buffer, (char*)file) != 0) {
00356                 WOLFSSL_MSG("Error creating logging node");
00357                 /* with void function there is no return here, continue on
00358                  * to unlock mutex and log what buffer was created. */
00359             }
00360             #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY)
00361             }
00362             else {
00363                 XSNPRINTF(buffer, sizeof(buffer),
00364                     "wolfSSL error occurred, error = %d", error);
00365 
00366             }
00367             #endif
00368 
00369             wc_UnLockMutex(&debug_mutex);
00370         }
00371     #else
00372         XSNPRINTF(buffer, sizeof(buffer),
00373                 "wolfSSL error occurred, error = %d", error);
00374     #endif
00375 
00376     #ifdef DEBUG_WOLFSSL
00377         if (loggingEnabled)
00378             wolfssl_log(ERROR_LOG , buffer);
00379     #endif
00380     }
00381 }
00382 
00383 void WOLFSSL_ERROR_MSG(const char* msg)
00384 {
00385 #ifdef DEBUG_WOLFSSL
00386     if (loggingEnabled)
00387         wolfssl_log(ERROR_LOG , msg);
00388 #else
00389     (void)msg;
00390 #endif
00391 }
00392 
00393 #endif  /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
00394 
00395 #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
00396 /* Internal function that is called by wolfCrypt_Init() */
00397 int wc_LoggingInit(void)
00398 {
00399     if (wc_InitMutex(&debug_mutex) != 0) {
00400         WOLFSSL_MSG("Bad Init Mutex");
00401         return BAD_MUTEX_E;
00402     }
00403     wc_errors          = NULL;
00404     wc_current_node    = NULL;
00405     wc_last_node       = NULL;
00406 
00407     return 0;
00408 }
00409 
00410 
00411 /* internal function that is called by wolfCrypt_Cleanup */
00412 int wc_LoggingCleanup(void)
00413 {
00414     /* clear logging entries */
00415     wc_ClearErrorNodes();
00416 
00417     /* free mutex */
00418     if (wc_FreeMutex(&debug_mutex) != 0) {
00419         WOLFSSL_MSG("Bad Mutex free");
00420         return BAD_MUTEX_E;
00421     }
00422     return 0;
00423 }
00424 
00425 
00426 /* peek at an error node
00427  *
00428  * idx : if -1 then the most recent node is looked at, otherwise search
00429  *         through queue for node at the given index
00430  * file  : pointer to internal file string
00431  * reason : pointer to internal error reason
00432  * line  : line number that error happened at
00433  *
00434  * Returns a negative value in error case, on success returns the nodes error
00435  * value which is positve (absolute value)
00436  */
00437 int wc_PeekErrorNode(int idx, const char **file, const char **reason,
00438         int *line)
00439 {
00440     struct wc_error_queue* err;
00441 
00442     if (wc_LockMutex(&debug_mutex) != 0) {
00443         WOLFSSL_MSG("Lock debug mutex failed");
00444         return BAD_MUTEX_E;
00445     }
00446 
00447     if (idx < 0) {
00448         err = wc_last_node;
00449         if (err == NULL) {
00450             WOLFSSL_MSG("No Errors in queue");
00451             wc_UnLockMutex(&debug_mutex);
00452             return BAD_STATE_E;
00453         }
00454     }
00455     else {
00456         int i;
00457 
00458         err = (struct wc_error_queue*)wc_errors;
00459         for (i = 0; i < idx; i++) {
00460             if (err == NULL) {
00461                 WOLFSSL_MSG("Error node not found. Bad index?");
00462                 wc_UnLockMutex(&debug_mutex);
00463                 return BAD_FUNC_ARG;
00464             }
00465             err = err->next;
00466         }
00467     }
00468 
00469     if (file != NULL) {
00470         *file = err->file;
00471     }
00472 
00473     if (reason != NULL) {
00474         *reason = err->error;
00475     }
00476 
00477     if (line != NULL) {
00478         *line = err->line;
00479     }
00480 
00481     wc_UnLockMutex(&debug_mutex);
00482 
00483     return err->value;
00484 }
00485 
00486 
00487 /* Pulls the current node from error queue and increments current state.
00488  * Note: this does not delete nodes because input arguments are pointing to
00489  *       node buffers.
00490  *
00491  * file   pointer to file that error was in. Can be NULL to return no file.
00492  * reason error string giving reason for error. Can be NULL to return no reason.
00493  * line   retrun line number of where error happened.
00494  *
00495  * returns the error value on success and BAD_MUTEX_E or BAD_STATE_E on failure
00496  */
00497 int wc_PullErrorNode(const char **file, const char **reason, int *line)
00498 {
00499     struct wc_error_queue* err;
00500     int value;
00501 
00502     if (wc_LockMutex(&debug_mutex) != 0) {
00503         WOLFSSL_MSG("Lock debug mutex failed");
00504         return BAD_MUTEX_E;
00505     }
00506 
00507     err = wc_current_node;
00508     if (err == NULL) {
00509         WOLFSSL_MSG("No Errors in queue");
00510         wc_UnLockMutex(&debug_mutex);
00511         return BAD_STATE_E;
00512     }
00513 
00514     if (file != NULL) {
00515         *file = err->file;
00516     }
00517 
00518     if (reason != NULL) {
00519         *reason = err->error;
00520     }
00521 
00522     if (line != NULL) {
00523         *line = err->line;
00524     }
00525 
00526     value = err->value;
00527     wc_current_node = err->next;
00528     wc_UnLockMutex(&debug_mutex);
00529 
00530     return value;
00531 }
00532 
00533 
00534 /* create new error node and add it to the queue
00535  * buffers are assumed to be of size WOLFSSL_MAX_ERROR_SZ for this internal
00536  * function. debug_mutex should be locked before a call to this function. */
00537 int wc_AddErrorNode(int error, int line, char* buf, char* file)
00538 {
00539 
00540     struct wc_error_queue* err;
00541 
00542     err = (struct wc_error_queue*)XMALLOC(
00543             sizeof(struct wc_error_queue), wc_error_heap, DYNAMIC_TYPE_LOG);
00544     if (err == NULL) {
00545         WOLFSSL_MSG("Unable to create error node for log");
00546         return MEMORY_E;
00547     }
00548     else {
00549         int sz;
00550 
00551         XMEMSET(err, 0, sizeof(struct wc_error_queue));
00552         err->heap = wc_error_heap;
00553         sz = (int)XSTRLEN(buf);
00554         if (sz > WOLFSSL_MAX_ERROR_SZ - 1) {
00555             sz = WOLFSSL_MAX_ERROR_SZ - 1;
00556         }
00557         if (sz > 0) {
00558             XMEMCPY(err->error, buf, sz);
00559         }
00560 
00561         sz = (int)XSTRLEN(file);
00562         if (sz > WOLFSSL_MAX_ERROR_SZ - 1) {
00563             sz = WOLFSSL_MAX_ERROR_SZ - 1;
00564         }
00565         if (sz > 0) {
00566             XMEMCPY(err->file, file, sz);
00567         }
00568 
00569         err->value = error;
00570         err->line  = line;
00571 
00572         /* make sure is terminated */
00573         err->error[WOLFSSL_MAX_ERROR_SZ - 1] = '\0';
00574         err->file[WOLFSSL_MAX_ERROR_SZ - 1]  = '\0';
00575 
00576 
00577         /* since is queue place new node at last of the list */
00578         if (wc_last_node == NULL) {
00579             /* case of first node added to queue */
00580             if (wc_errors != NULL) {
00581                 /* check for unexpected case before over writing wc_errors */
00582                 WOLFSSL_MSG("ERROR in adding new node to logging queue!!\n");
00583             }
00584             else {
00585                 wc_errors    = err;
00586                 wc_last_node = err;
00587                 wc_current_node = err;
00588             }
00589         }
00590         else {
00591             wc_last_node->next = err;
00592             err->prev = wc_last_node;
00593             wc_last_node = err;
00594 
00595             /* check the case where have read to the end of the queue and the
00596              * current node to read needs updated */
00597             if (wc_current_node == NULL) {
00598                 wc_current_node = err;
00599             }
00600         }
00601     }
00602 
00603     return 0;
00604 }
00605 
00606 /* Removes the error node at the specified index.
00607  * idx : if -1 then the most recent node is looked at, otherwise search
00608  *         through queue for node at the given index
00609  */
00610 void wc_RemoveErrorNode(int idx)
00611 {
00612     struct wc_error_queue* current;
00613 
00614     if (wc_LockMutex(&debug_mutex) != 0) {
00615         WOLFSSL_MSG("Lock debug mutex failed");
00616         return;
00617     }
00618 
00619     if (idx == -1)
00620         current = wc_last_node;
00621     else {
00622         current = (struct wc_error_queue*)wc_errors;
00623         for (; current != NULL && idx > 0; idx--)
00624              current = current->next;
00625     }
00626     if (current != NULL) {
00627         if (current->prev != NULL)
00628             current->prev->next = current->next;
00629         if (wc_last_node == current)
00630             wc_last_node = current->prev;
00631         if (wc_errors == current)
00632             wc_errors = current->next;
00633         XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
00634     }
00635 
00636     wc_UnLockMutex(&debug_mutex);
00637 }
00638 
00639 
00640 /* Clears out the list of error nodes.
00641  */
00642 void wc_ClearErrorNodes(void)
00643 {
00644 #if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX)
00645     if (wc_LockMutex(&debug_mutex) != 0) {
00646         WOLFSSL_MSG("Lock debug mutex failed");
00647         return;
00648     }
00649 
00650     /* free all nodes from error queue */
00651     {
00652         struct wc_error_queue* current;
00653         struct wc_error_queue* next;
00654 
00655         current = (struct wc_error_queue*)wc_errors;
00656         while (current != NULL) {
00657             next = current->next;
00658             XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
00659             current = next;
00660         }
00661     }
00662 
00663     wc_errors    = NULL;
00664     wc_last_node = NULL;
00665     wc_UnLockMutex(&debug_mutex);
00666 #endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX */
00667 }
00668 
00669 int wc_SetLoggingHeap(void* h)
00670 {
00671     if (wc_LockMutex(&debug_mutex) != 0) {
00672         WOLFSSL_MSG("Lock debug mutex failed");
00673         return BAD_MUTEX_E;
00674     }
00675     wc_error_heap = h;
00676     wc_UnLockMutex(&debug_mutex);
00677     return 0;
00678 }
00679 
00680 
00681 /* frees all nodes in the queue
00682  *
00683  * id  this is the thread id
00684  */
00685 int wc_ERR_remove_state(void)
00686 {
00687     struct wc_error_queue* current;
00688     struct wc_error_queue* next;
00689 
00690     if (wc_LockMutex(&debug_mutex) != 0) {
00691         WOLFSSL_MSG("Lock debug mutex failed");
00692         return BAD_MUTEX_E;
00693     }
00694 
00695     /* free all nodes from error queue */
00696     current = (struct wc_error_queue*)wc_errors;
00697     while (current != NULL) {
00698         next = current->next;
00699         XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
00700         current = next;
00701     }
00702 
00703     wc_errors          = NULL;
00704     wc_last_node       = NULL;
00705 
00706     wc_UnLockMutex(&debug_mutex);
00707 
00708     return 0;
00709 }
00710 
00711 
00712 #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
00713 /* empties out the error queue into the file */
00714 void wc_ERR_print_errors_fp(XFILE fp)
00715 {
00716     WOLFSSL_ENTER("wc_ERR_print_errors_fp");
00717 
00718     if (wc_LockMutex(&debug_mutex) != 0) {
00719         WOLFSSL_MSG("Lock debug mutex failed");
00720     }
00721     else {
00722         /* free all nodes from error queue and print them to file */
00723         {
00724             struct wc_error_queue* current;
00725             struct wc_error_queue* next;
00726 
00727             current = (struct wc_error_queue*)wc_errors;
00728             while (current != NULL) {
00729                 next = current->next;
00730                 fprintf(fp, "%s\n", current->error);
00731                 XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
00732                 current = next;
00733             }
00734 
00735             /* set global pointers to match having been freed */
00736             wc_errors    = NULL;
00737             wc_last_node = NULL;
00738         }
00739 
00740         wc_UnLockMutex(&debug_mutex);
00741     }
00742 }
00743 #endif /* !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) */
00744 
00745 #endif /* defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) */
00746 
00747