2 This file is part of GNUnet.
3 Copyright (C) 2006-2013 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file util/common_logging.c
23 * @brief error handling API
24 * @author Christian Grothoff
27 #include "gnunet_crypto_lib.h"
28 #include "gnunet_disk_lib.h"
29 #include "gnunet_strings_lib.h"
34 * After how many milliseconds do we always print
35 * that "message X was repeated N times"? Use 12h.
37 #define BULK_DELAY_THRESHOLD (12 * 60 * 60 * 1000LL * 1000LL)
40 * After how many repetitions do we always print
41 * that "message X was repeated N times"? (even if
42 * we have not yet reached the delay threshold)
44 #define BULK_REPEAT_THRESHOLD 1000
47 * How many characters do we use for matching of
50 #define BULK_TRACK_SIZE 256
53 * How many characters do we use for matching of
56 #define COMP_TRACK_SIZE 32
59 * How many characters can a date/time string
62 #define DATE_STR_SIZE 64
65 * How many log files to keep?
67 #define ROTATION_KEEP 3
71 * Assumed maximum path length (for the log file name).
78 * Linked list of active loggers.
82 * This is a linked list.
84 struct CustomLogger *next;
99 * Asynchronous scope of the current thread, or NULL if we have not
100 * entered an async scope yet.
102 static __thread struct GNUNET_AsyncScopeSave current_async_scope;
105 * The last "bulk" error message that we have been logging.
106 * Note that this message maybe truncated to the first BULK_TRACK_SIZE
107 * characters, in which case it is NOT 0-terminated!
109 static GNUNET_THREAD_LOCAL char last_bulk[BULK_TRACK_SIZE] __nonstring;
112 * Type of the last bulk message.
114 static GNUNET_THREAD_LOCAL enum GNUNET_ErrorType last_bulk_kind;
117 * Time of the last bulk error message (0 for none)
119 static GNUNET_THREAD_LOCAL struct GNUNET_TIME_Absolute last_bulk_time;
122 * Number of times that bulk message has been repeated since.
124 static GNUNET_THREAD_LOCAL unsigned int last_bulk_repeat;
127 * Component when the last bulk was logged. Will be 0-terminated.
129 static GNUNET_THREAD_LOCAL char last_bulk_comp[COMP_TRACK_SIZE + 1];
134 static char *component;
137 * Running component (without pid).
139 static char *component_nopid;
142 * Format string describing the name of the log file.
144 static char *log_file_name;
149 static enum GNUNET_ErrorType min_level;
152 * Linked list of our custom loggres.
154 static struct CustomLogger *loggers;
157 * Number of log calls to ignore.
159 static GNUNET_THREAD_LOCAL int skip_log = 0;
162 * File descriptor to use for "stderr", or NULL for none.
164 static FILE *GNUNET_stderr;
167 * Represents a single logging definition
171 * Component name regex
173 regex_t component_regex;
181 * Function name regex
183 regex_t function_regex;
186 * Lowest line at which this definition matches.
187 * Defaults to 0. Must be <= to_line.
192 * Highest line at which this definition matches.
193 * Defaults to INT_MAX. Must be >= from_line.
198 * Maximal log level allowed for calls that match this definition.
199 * Calls with higher log level will be disabled.
205 * 1 if this definition comes from GNUNET_FORCE_LOG, which means that it
206 * overrides any configuration options. 0 otherwise.
212 #if !defined(GNUNET_CULL_LOGGING)
214 * Dynamic array of logging definitions
216 static struct LogDef *logdefs;
219 * Allocated size of logdefs array (in units)
221 static int logdefs_size;
224 * The number of units used in logdefs array.
226 static int logdefs_len;
229 * #GNUNET_YES if GNUNET_LOG environment variable is already parsed.
231 static int gnunet_log_parsed;
234 * #GNUNET_YES if GNUNET_FORCE_LOG environment variable is already parsed.
236 static int gnunet_force_log_parsed;
239 * #GNUNET_YES if at least one definition with forced == 1 is available.
241 static int gnunet_force_log_present;
246 * Contains the number of performance counts per second.
248 static LARGE_INTEGER performance_frequency;
253 * Convert a textual description of a loglevel
254 * to the respective GNUNET_GE_KIND.
256 * @param log loglevel to parse
257 * @return GNUNET_GE_INVALID if log does not parse
259 static enum GNUNET_ErrorType
260 get_type(const char *log)
263 return GNUNET_ERROR_TYPE_UNSPECIFIED;
264 if (0 == strcasecmp(log, _("DEBUG")))
265 return GNUNET_ERROR_TYPE_DEBUG;
266 if (0 == strcasecmp(log, _("INFO")))
267 return GNUNET_ERROR_TYPE_INFO;
268 if (0 == strcasecmp(log, _("MESSAGE")))
269 return GNUNET_ERROR_TYPE_MESSAGE;
270 if (0 == strcasecmp(log, _("WARNING")))
271 return GNUNET_ERROR_TYPE_WARNING;
272 if (0 == strcasecmp(log, _("ERROR")))
273 return GNUNET_ERROR_TYPE_ERROR;
274 if (0 == strcasecmp(log, _("NONE")))
275 return GNUNET_ERROR_TYPE_NONE;
276 return GNUNET_ERROR_TYPE_INVALID;
281 * Abort the process, generate a core dump if possible.
293 #if !defined(GNUNET_CULL_LOGGING)
295 * Utility function - reallocates logdefs array to be twice as large.
300 logdefs_size = (logdefs_size + 1) * 2;
301 logdefs = GNUNET_realloc(logdefs, logdefs_size * sizeof(struct LogDef));
305 #if !TALER_WALLET_ONLY
307 * Rotate logs, deleting the oldest log.
309 * @param new_name new name to add to the rotation
312 log_rotate(const char *new_name)
314 static char *rotation[ROTATION_KEEP];
315 static unsigned int rotation_off;
318 if ('\0' == *new_name)
319 return; /* not a real log file name */
320 discard = rotation[rotation_off % ROTATION_KEEP];
323 /* Note: can't log errors during logging (recursion!), so this
324 operation MUST silently fail... */
325 (void)unlink(discard);
326 GNUNET_free(discard);
328 rotation[rotation_off % ROTATION_KEEP] = GNUNET_strdup(new_name);
334 * Setup the log file.
336 * @param tm timestamp for which we should setup logging
337 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
340 setup_log_file(const struct tm *tm)
342 static char last_fn[PATH_MAX + 1];
343 char fn[PATH_MAX + 1];
349 if (NULL == log_file_name)
350 return GNUNET_SYSERR;
351 if (0 == strftime(fn, sizeof(fn), log_file_name, tm))
352 return GNUNET_SYSERR;
353 leftsquare = strrchr(fn, '[');
354 if ((NULL != leftsquare) && (']' == leftsquare[1]))
356 char *logfile_copy = GNUNET_strdup(fn);
358 logfile_copy[leftsquare - fn] = '\0';
359 logfile_copy[leftsquare - fn + 1] = '\0';
365 &logfile_copy[leftsquare - fn + 2]);
366 GNUNET_free(logfile_copy);
368 if (0 == strcmp(fn, last_fn))
369 return GNUNET_OK; /* no change */
372 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file(fn))
375 "Failed to create directory for `%s': %s\n",
378 return GNUNET_SYSERR;
382 open(fn, O_APPEND | O_BINARY | O_WRONLY | O_CREAT, _S_IREAD | _S_IWRITE);
385 O_APPEND | O_WRONLY | O_CREAT,
386 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
390 if (NULL != GNUNET_stderr)
391 fclose(GNUNET_stderr);
392 dup_return = dup2(altlog_fd, 2);
393 (void)close(altlog_fd);
394 if (-1 != dup_return)
396 altlog = fdopen(2, "ab");
410 GNUNET_log_strerror_file(GNUNET_ERROR_TYPE_ERROR, "open", fn);
411 return GNUNET_SYSERR;
413 GNUNET_stderr = altlog;
420 * Utility function - adds a parsed definition to logdefs array.
422 * @param component see struct LogDef, can't be NULL
423 * @param file see struct LogDef, can't be NULL
424 * @param function see struct LogDef, can't be NULL
425 * @param from_line see struct LogDef
426 * @param to_line see struct LogDef
427 * @param level see struct LogDef, must be >= 0
428 * @param force see struct LogDef
429 * @return 0 on success, regex-specific error otherwise
432 add_definition(const char *component,
434 const char *function,
443 if (logdefs_size == logdefs_len)
445 memset(&n, 0, sizeof(n));
446 if (0 == strlen(component))
447 component = (char *)".*";
448 r = regcomp(&n.component_regex, (const char *)component, REG_NOSUB);
453 if (0 == strlen(file))
455 r = regcomp(&n.file_regex, (const char *)file, REG_NOSUB);
458 regfree(&n.component_regex);
461 if ((NULL == function) || (0 == strlen(function)))
462 function = (char *)".*";
463 r = regcomp(&n.function_regex, (const char *)function, REG_NOSUB);
466 regfree(&n.component_regex);
467 regfree(&n.file_regex);
470 n.from_line = from_line;
474 logdefs[logdefs_len++] = n;
480 * Decides whether a particular logging call should or should not be allowed
481 * to be made. Used internally by GNUNET_log*()
483 * @param caller_level loglevel the caller wants to use
484 * @param comp component name the caller uses (NULL means that global
485 * component name is used)
486 * @param file file name containing the logging call, usually __FILE__
487 * @param function function which tries to make a logging call,
488 * usually __FUNCTION__
489 * @param line line at which the call is made, usually __LINE__
490 * @return 0 to disallow the call, 1 to allow it
493 GNUNET_get_log_call_status(int caller_level,
496 const char *function,
504 /* Use default component */
505 comp = component_nopid;
507 /* We have no definitions to override globally configured log level,
508 * so just use it right away.
510 if ((min_level >= 0) && (GNUNET_NO == gnunet_force_log_present))
511 return caller_level <= min_level;
513 /* Only look for forced definitions? */
514 force_only = min_level >= 0;
515 for (i = 0; i < logdefs_len; i++)
518 if (((!force_only) || ld->force) &&
519 (line >= ld->from_line && line <= ld->to_line) &&
520 (0 == regexec(&ld->component_regex, comp, 0, NULL, 0)) &&
521 (0 == regexec(&ld->file_regex, file, 0, NULL, 0)) &&
522 (0 == regexec(&ld->function_regex, function, 0, NULL, 0)))
525 return caller_level <= ld->level;
528 /* No matches - use global level, if defined */
530 return caller_level <= min_level;
531 /* All programs/services previously defaulted to WARNING.
532 * Now *we* default to WARNING, and THEY default to NULL.
533 * Or rather we default to MESSAGE, since things aren't always bad.
535 return caller_level <= GNUNET_ERROR_TYPE_MESSAGE;
540 * Utility function - parses a definition
543 * component;file;function;from_line-to_line;level[/component...]
544 * All entries are mandatory, but may be empty.
545 * Empty entries for component, file and function are treated as
546 * "matches anything".
547 * Empty line entry is treated as "from 0 to INT_MAX"
548 * Line entry with only one line is treated as "this line only"
549 * Entry for level MUST NOT be empty.
550 * Entries for component, file and function that consist of a
551 * single character "*" are treated (at the moment) the same way
552 * empty entries are treated (wildcard matching is not implemented (yet?)).
553 * file entry is matched to the end of __FILE__. That is, it might be
554 * a base name, or a base name with leading directory names (some compilers
555 * define __FILE__ to absolute file path).
557 * @param constname name of the environment variable from which to get the
558 * string to be parsed
559 * @param force 1 if definitions found in constname are to be forced
560 * @return number of added definitions
563 parse_definitions(const char *constname, int force)
569 char *function = NULL;
575 int from_line, to_line;
577 int keep_looking = 1;
579 tmp = getenv(constname);
582 def = GNUNET_strdup(tmp);
585 for (p = def, state = 0, start = def; keep_looking; p++)
589 case ';': /* found a field separator */
593 case 0: /* within a component name */
597 case 1: /* within a file name */
601 case 2: /* within a function name */
602 /* after a file name there must be a function name */
606 case 3: /* within a from-to line range */
607 if (strlen(start) > 0)
610 from_line = strtol(start, &t, 10);
611 if ((0 != errno) || (from_line < 0))
616 if ((t < p) && ('-' == t[0]))
620 to_line = strtol(start, &t, 10);
621 if ((0 != errno) || (to_line < 0) || (t != p))
627 else /* one number means "match this line only" */
630 else /* default to 0-max */
640 _("ERROR: Unable to parse log definition: Syntax error at `%s'.\n"),
648 case '\0': /* found EOL */
651 /* fall through to '/' */
652 case '/': /* found a definition separator */
655 case 4: /* within a log level */
658 level = get_type((const char *)start);
659 if ((GNUNET_ERROR_TYPE_INVALID == level) ||
660 (GNUNET_ERROR_TYPE_UNSPECIFIED == level) ||
661 (0 != add_definition(comp,
679 _("ERROR: Unable to parse log definition: Syntax error at `%s'.\n"),
694 * Utility function - parses GNUNET_LOG and GNUNET_FORCE_LOG.
697 parse_all_definitions()
699 if (GNUNET_NO == gnunet_force_log_parsed)
700 gnunet_force_log_present =
701 parse_definitions("GNUNET_FORCE_LOG", 1) > 0 ? GNUNET_YES : GNUNET_NO;
702 gnunet_force_log_parsed = GNUNET_YES;
704 if (GNUNET_NO == gnunet_log_parsed)
705 parse_definitions("GNUNET_LOG", 0);
706 gnunet_log_parsed = GNUNET_YES;
714 * @param comp default component to use
715 * @param loglevel what types of messages should be logged
716 * @param logfile which file to write log messages to (can be NULL)
717 * @return #GNUNET_OK on success
720 GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
722 const char *env_logfile;
724 min_level = get_type(loglevel);
725 #if !defined(GNUNET_CULL_LOGGING)
726 parse_all_definitions();
729 QueryPerformanceFrequency(&performance_frequency);
731 GNUNET_free_non_null(component);
732 GNUNET_asprintf(&component, "%s-%d", comp, getpid());
733 GNUNET_free_non_null(component_nopid);
734 component_nopid = GNUNET_strdup(comp);
736 env_logfile = getenv("GNUNET_FORCE_LOGFILE");
737 if ((NULL != env_logfile) && (strlen(env_logfile) > 0))
738 logfile = env_logfile;
741 GNUNET_free_non_null(log_file_name);
742 log_file_name = GNUNET_STRINGS_filename_expand(logfile);
743 if (NULL == log_file_name)
744 return GNUNET_SYSERR;
745 #if TALER_WALLET_ONLY || defined(GNUNET_CULL_LOGGING)
746 /* log file option not allowed for wallet logic */
747 GNUNET_assert(NULL == logfile);
756 return setup_log_file(tm);
763 * Add a custom logger. Note that installing any custom logger
764 * will disable the standard logger. When multiple custom loggers
765 * are installed, all will be called. The standard logger will
766 * only be used if no custom loggers are present.
768 * @param logger log function
769 * @param logger_cls closure for @a logger
772 GNUNET_logger_add(GNUNET_Logger logger, void *logger_cls)
774 struct CustomLogger *entry;
776 entry = GNUNET_new(struct CustomLogger);
777 entry->logger = logger;
778 entry->logger_cls = logger_cls;
779 entry->next = loggers;
785 * Remove a custom logger.
787 * @param logger log function
788 * @param logger_cls closure for @a logger
791 GNUNET_logger_remove(GNUNET_Logger logger, void *logger_cls)
793 struct CustomLogger *pos;
794 struct CustomLogger *prev;
798 while ((NULL != pos) &&
799 ((pos->logger != logger) || (pos->logger_cls != logger_cls)))
804 GNUNET_assert(NULL != pos);
808 prev->next = pos->next;
813 CRITICAL_SECTION output_message_cs;
818 * Actually output the log message.
820 * @param kind how severe was the issue
821 * @param comp component responsible
822 * @param datestr current date/time
823 * @param msg the actual message
826 output_message(enum GNUNET_ErrorType kind,
831 struct CustomLogger *pos;
834 EnterCriticalSection(&output_message_cs);
836 /* only use the standard logger if no custom loggers are present */
837 if ((NULL != GNUNET_stderr) && (NULL == loggers))
839 if (kind == GNUNET_ERROR_TYPE_MESSAGE)
841 /* The idea here is to produce "normal" output messages
842 * for end users while still having the power of the
843 * logging engine for developer needs. So ideally this
844 * is what it should look like when CLI tools are used
845 * interactively, yet the same message shouldn't look
846 * this way if the output is going to logfiles or robots
849 fprintf(GNUNET_stderr, "* %s", msg);
851 else if (GNUNET_YES == current_async_scope.have_scope)
853 static GNUNET_THREAD_LOCAL char id_buf[27];
856 /* We're logging, so skip_log must be currently 0. */
858 end = GNUNET_STRINGS_data_to_string(¤t_async_scope.scope_id,
859 sizeof(struct GNUNET_AsyncScopeId),
862 GNUNET_assert(NULL != end);
865 fprintf(GNUNET_stderr,
870 GNUNET_error_type_to_string(kind),
875 fprintf(GNUNET_stderr,
879 GNUNET_error_type_to_string(kind),
882 fflush(GNUNET_stderr);
887 pos->logger(pos->logger_cls, kind, comp, datestr, msg);
891 LeaveCriticalSection(&output_message_cs);
897 * Flush an existing bulk report to the output.
899 * @param datestr our current timestamp
902 flush_bulk(const char *datestr)
904 char msg[DATE_STR_SIZE + BULK_TRACK_SIZE + 256];
909 if ((0 == last_bulk_time.abs_value_us) || (0 == last_bulk_repeat))
912 last = memchr(last_bulk, '\0', BULK_TRACK_SIZE);
914 last = &last_bulk[BULK_TRACK_SIZE - 1];
915 else if (last != last_bulk)
923 GNUNET_STRINGS_relative_time_to_string(GNUNET_TIME_absolute_get_duration(
928 _("Message `%.*s' repeated %u times in the last %s\n"),
935 output_message(last_bulk_kind, last_bulk_comp, datestr, msg);
936 last_bulk_time = GNUNET_TIME_absolute_get();
937 last_bulk_repeat = 0;
942 * Ignore the next n calls to the log function.
944 * @param n number of log calls to ignore (could be negative)
945 * @param check_reset #GNUNET_YES to assert that the log skip counter is currently zero
948 GNUNET_log_skip(int n, int check_reset)
954 ok = (0 == skip_log);
967 * Get the number of log calls that are going to be skipped
969 * @return number of log calls to be ignored
972 GNUNET_get_log_skip()
979 * Output a log message using the default mechanism.
981 * @param kind how severe was the issue
982 * @param comp component responsible
983 * @param message the actual message
984 * @param va arguments to the format string "message"
987 mylog(enum GNUNET_ErrorType kind,
992 char date[DATE_STR_SIZE];
993 char date2[DATE_STR_SIZE];
999 size = vsnprintf(NULL, 0, message, vacp) + 1;
1000 GNUNET_assert(0 != size);
1002 memset(date, 0, DATE_STR_SIZE);
1010 offset = GNUNET_TIME_get_offset();
1012 timetmp += offset / 1000;
1013 tmptr = localtime(&timetmp);
1015 QueryPerformanceCounter(&pc);
1018 strcpy(date, "localtime error");
1023 strftime(date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%020llu", tmptr))
1025 if (0 > snprintf(date,
1028 (long long)(pc.QuadPart /
1029 (performance_frequency.QuadPart / 1000))))
1033 struct timeval timeofday;
1035 gettimeofday(&timeofday, NULL);
1036 offset = GNUNET_TIME_get_offset();
1039 timeofday.tv_sec += offset / 1000LL;
1040 timeofday.tv_usec += (offset % 1000LL) * 1000LL;
1041 if (timeofday.tv_usec > 1000000LL)
1043 timeofday.tv_usec -= 1000000LL;
1049 timeofday.tv_sec += offset / 1000LL;
1050 if (timeofday.tv_usec > -(offset % 1000LL) * 1000LL)
1052 timeofday.tv_usec += (offset % 1000LL) * 1000LL;
1056 timeofday.tv_usec += 1000000LL + (offset % 1000LL) * 1000LL;
1060 tmptr = localtime(&timeofday.tv_sec);
1063 strcpy(date, "localtime error");
1067 if (0 == strftime(date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%06u", tmptr))
1069 if (0 > snprintf(date, sizeof(date), date2, timeofday.tv_usec))
1073 vsnprintf(buf, size, message, va);
1074 #if !(defined(GNUNET_CULL_LOGGING) || TALER_WALLET_ONLY)
1076 (void)setup_log_file(tmptr);
1078 if ((0 != (kind & GNUNET_ERROR_TYPE_BULK)) &&
1079 (0 != last_bulk_time.abs_value_us) &&
1080 (0 == strncmp(buf, last_bulk, sizeof(last_bulk))))
1083 if ((GNUNET_TIME_absolute_get_duration(last_bulk_time).rel_value_us >
1084 BULK_DELAY_THRESHOLD) ||
1085 (last_bulk_repeat > BULK_REPEAT_THRESHOLD))
1090 GNUNET_strlcpy(last_bulk, buf, sizeof(last_bulk));
1091 last_bulk_repeat = 0;
1092 last_bulk_kind = kind;
1093 last_bulk_time = GNUNET_TIME_absolute_get();
1094 GNUNET_strlcpy(last_bulk_comp, comp, sizeof(last_bulk_comp));
1095 output_message(kind, comp, date, buf);
1101 * Main log function.
1103 * @param kind how serious is the error?
1104 * @param message what is the message (format string)
1105 * @param ... arguments for format string
1108 GNUNET_log_nocheck(enum GNUNET_ErrorType kind, const char *message, ...)
1112 va_start(va, message);
1113 mylog(kind, component, message, va);
1119 * Log function that specifies an alternative component.
1120 * This function should be used by plugins.
1122 * @param kind how serious is the error?
1123 * @param comp component responsible for generating the message
1124 * @param message what is the message (format string)
1125 * @param ... arguments for format string
1128 GNUNET_log_from_nocheck(enum GNUNET_ErrorType kind,
1130 const char *message,
1134 char comp_w_pid[128];
1137 comp = component_nopid;
1139 va_start(va, message);
1140 GNUNET_snprintf(comp_w_pid, sizeof(comp_w_pid), "%s-%d", comp, getpid());
1141 mylog(kind, comp_w_pid, message, va);
1147 * Convert error type to string.
1149 * @param kind type to convert
1150 * @return string corresponding to the type
1153 GNUNET_error_type_to_string(enum GNUNET_ErrorType kind)
1155 if ((kind & GNUNET_ERROR_TYPE_ERROR) > 0)
1157 if ((kind & GNUNET_ERROR_TYPE_WARNING) > 0)
1158 return _("WARNING");
1159 if ((kind & GNUNET_ERROR_TYPE_MESSAGE) > 0)
1160 return _("MESSAGE");
1161 if ((kind & GNUNET_ERROR_TYPE_INFO) > 0)
1163 if ((kind & GNUNET_ERROR_TYPE_DEBUG) > 0)
1165 if ((kind & ~GNUNET_ERROR_TYPE_BULK) == 0)
1167 return _("INVALID");
1172 * Convert a hash to a string (for printing debug messages).
1174 * @param hc the hash code
1175 * @return string form; will be overwritten by next call to GNUNET_h2s.
1178 GNUNET_h2s(const struct GNUNET_HashCode *hc)
1180 static GNUNET_THREAD_LOCAL struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1182 GNUNET_CRYPTO_hash_to_enc(hc, &ret);
1183 ret.encoding[8] = '\0';
1184 return (const char *)ret.encoding;
1189 * Convert a hash to a string (for printing debug messages).
1190 * This is one of the very few calls in the entire API that is
1191 * NOT reentrant! Identical to #GNUNET_h2s(), except that another
1192 * buffer is used so both #GNUNET_h2s() and #GNUNET_h2s2() can be
1193 * used within the same log statement.
1195 * @param hc the hash code
1196 * @return string form; will be overwritten by next call to GNUNET_h2s.
1199 GNUNET_h2s2(const struct GNUNET_HashCode *hc)
1201 static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1203 GNUNET_CRYPTO_hash_to_enc(hc, &ret);
1204 ret.encoding[8] = '\0';
1205 return (const char *)ret.encoding;
1211 * Convert a public key value to a string (for printing debug messages).
1212 * This is one of the very few calls in the entire API that is
1215 * @param hc the hash code
1219 GNUNET_p2s(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
1221 static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1222 struct GNUNET_HashCode hc;
1224 GNUNET_CRYPTO_hash(p, sizeof(*p), &hc);
1225 GNUNET_CRYPTO_hash_to_enc(&hc, &ret);
1226 ret.encoding[6] = '\0';
1227 return (const char *)ret.encoding;
1233 * Convert a public key value to a string (for printing debug messages).
1234 * This is one of the very few calls in the entire API that is
1237 * @param hc the hash code
1241 GNUNET_p2s2(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
1243 static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1244 struct GNUNET_HashCode hc;
1246 GNUNET_CRYPTO_hash(p, sizeof(*p), &hc);
1247 GNUNET_CRYPTO_hash_to_enc(&hc, &ret);
1248 ret.encoding[6] = '\0';
1249 return (const char *)ret.encoding;
1255 * Convert a public key value to a string (for printing debug messages).
1256 * This is one of the very few calls in the entire API that is
1259 * @param hc the hash code
1263 GNUNET_e2s(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
1265 static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1266 struct GNUNET_HashCode hc;
1268 GNUNET_CRYPTO_hash(p, sizeof(*p), &hc);
1269 GNUNET_CRYPTO_hash_to_enc(&hc, &ret);
1270 ret.encoding[6] = '\0';
1271 return (const char *)ret.encoding;
1277 * Convert a public key value to a string (for printing debug messages).
1278 * This is one of the very few calls in the entire API that is
1281 * @param hc the hash code
1285 GNUNET_e2s2(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
1287 static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1288 struct GNUNET_HashCode hc;
1290 GNUNET_CRYPTO_hash(p, sizeof(*p), &hc);
1291 GNUNET_CRYPTO_hash_to_enc(&hc, &ret);
1292 ret.encoding[6] = '\0';
1293 return (const char *)ret.encoding;
1299 * Convert a short hash value to a string (for printing debug messages).
1300 * This is one of the very few calls in the entire API that is
1303 * @param shc the hash code
1307 GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
1309 static char buf[64];
1311 GNUNET_STRINGS_data_to_string(shc, sizeof(*shc), buf, sizeof(buf));
1313 return (const char *)buf;
1319 * Convert a UUID to a string (for printing debug messages).
1320 * This is one of the very few calls in the entire API that is
1323 * @param uuid the UUID
1327 GNUNET_uuid2s(const struct GNUNET_Uuid *uuid)
1329 static char buf[32];
1331 GNUNET_STRINGS_data_to_string(uuid, sizeof(*uuid), buf, sizeof(buf));
1333 return (const char *)buf;
1338 * Convert a hash to a string (for printing debug messages).
1339 * This is one of the very few calls in the entire API that is
1342 * @param hc the hash code
1343 * @return string form; will be overwritten by next call to GNUNET_h2s_full.
1346 GNUNET_h2s_full(const struct GNUNET_HashCode *hc)
1348 static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1350 GNUNET_CRYPTO_hash_to_enc(hc, &ret);
1351 ret.encoding[sizeof(ret) - 1] = '\0';
1352 return (const char *)ret.encoding;
1357 * Convert a peer identity to a string (for printing debug messages).
1359 * @param pid the peer identity
1360 * @return string form of the pid; will be overwritten by next
1361 * call to #GNUNET_i2s.
1364 GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
1366 static GNUNET_THREAD_LOCAL char buf[5];
1371 ret = GNUNET_CRYPTO_eddsa_public_key_to_string(&pid->public_key);
1372 GNUNET_strlcpy(buf, ret, sizeof(buf));
1379 * Convert a peer identity to a string (for printing debug messages).
1380 * Identical to #GNUNET_i2s(), except that another
1381 * buffer is used so both #GNUNET_i2s() and #GNUNET_i2s2() can be
1382 * used within the same log statement.
1384 * @param pid the peer identity
1385 * @return string form of the pid; will be overwritten by next
1386 * call to #GNUNET_i2s.
1389 GNUNET_i2s2(const struct GNUNET_PeerIdentity *pid)
1391 static GNUNET_THREAD_LOCAL char buf[5];
1396 ret = GNUNET_CRYPTO_eddsa_public_key_to_string(&pid->public_key);
1397 GNUNET_strlcpy(buf, ret, sizeof(buf));
1404 * Convert a peer identity to a string (for printing debug messages).
1406 * @param pid the peer identity
1407 * @return string form of the pid; will be overwritten by next
1408 * call to #GNUNET_i2s_full.
1411 GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
1413 static GNUNET_THREAD_LOCAL char buf[256];
1416 ret = GNUNET_CRYPTO_eddsa_public_key_to_string(&pid->public_key);
1424 * Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string
1425 * (for printing debug messages). This is one of the very few calls
1426 * in the entire API that is NOT reentrant!
1428 * @param addr the address
1429 * @param addrlen the length of the address in @a addr
1430 * @return nicely formatted string for the address
1431 * will be overwritten by next call to #GNUNET_a2s.
1434 GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
1438 GNUNET_MAX((INET6_ADDRSTRLEN + 8), \
1439 (1 + sizeof(struct sockaddr_un) - sizeof(sa_family_t)))
1441 #define LEN (INET6_ADDRSTRLEN + 8)
1443 static char buf[LEN];
1446 const struct sockaddr_in *v4;
1447 const struct sockaddr_un *un;
1448 const struct sockaddr_in6 *v6;
1452 return _("unknown address");
1453 switch (addr->sa_family)
1456 if (addrlen != sizeof(struct sockaddr_in))
1457 return "<invalid v4 address>";
1458 v4 = (const struct sockaddr_in *)addr;
1459 inet_ntop(AF_INET, &v4->sin_addr, buf, INET_ADDRSTRLEN);
1460 if (0 == ntohs(v4->sin_port))
1463 GNUNET_snprintf(b2, sizeof(b2), "%u", ntohs(v4->sin_port));
1468 if (addrlen != sizeof(struct sockaddr_in6))
1469 return "<invalid v4 address>";
1470 v6 = (const struct sockaddr_in6 *)addr;
1472 inet_ntop(AF_INET6, &v6->sin6_addr, &buf[1], INET6_ADDRSTRLEN);
1473 if (0 == ntohs(v6->sin6_port))
1476 GNUNET_snprintf(b2, sizeof(b2), "%u", ntohs(v6->sin6_port));
1481 if (addrlen <= sizeof(sa_family_t))
1482 return "<unbound UNIX client>";
1483 un = (const struct sockaddr_un *)addr;
1485 if ('\0' == un->sun_path[0])
1487 memset(buf, 0, sizeof(buf));
1488 GNUNET_snprintf(buf,
1491 (1 == off) ? "@" : "",
1492 (int)(addrlen - sizeof(sa_family_t) - off),
1493 &un->sun_path[off]);
1497 return _("invalid address");
1503 * Log error message about missing configuration option.
1505 * @param kind log level
1506 * @param section section with missing option
1507 * @param option name of missing option
1510 GNUNET_log_config_missing(enum GNUNET_ErrorType kind,
1511 const char *section,
1516 "Configuration fails to specify option `%s' in section `%s'!\n"),
1523 * Log error message about invalid configuration option value.
1525 * @param kind log level
1526 * @param section section with invalid option
1527 * @param option name of invalid option
1528 * @param required what is required that is invalid about the option
1531 GNUNET_log_config_invalid(enum GNUNET_ErrorType kind,
1532 const char *section,
1534 const char *required)
1539 "Configuration specifies invalid value for option `%s' in section `%s': %s\n"),
1547 * Set the async scope for the current thread.
1549 * @param aid the async scope identifier
1550 * @param old_scope[out] location to save the old scope
1553 GNUNET_async_scope_enter(const struct GNUNET_AsyncScopeId *aid,
1554 struct GNUNET_AsyncScopeSave *old_scope)
1556 *old_scope = current_async_scope;
1557 current_async_scope.have_scope = GNUNET_YES;
1558 current_async_scope.scope_id = *aid;
1563 * Clear the current thread's async scope.
1565 * @param old_scope scope to restore
1568 GNUNET_async_scope_restore(struct GNUNET_AsyncScopeSave *old_scope)
1570 current_async_scope = *old_scope;
1575 * Generate a fresh async scope identifier.
1577 * @param[out] aid_ret pointer to where the result is stored
1580 GNUNET_async_scope_fresh(struct GNUNET_AsyncScopeId *aid_ret)
1582 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK,
1584 sizeof(struct GNUNET_AsyncScopeId));
1589 * Get the current async scope.
1591 * @param[out] scope_ret pointer to where the result is stored
1594 GNUNET_async_scope_get(struct GNUNET_AsyncScopeSave *scope_ret)
1596 *scope_ret = current_async_scope;
1603 void __attribute__ ((constructor)) GNUNET_util_cl_init()
1605 GNUNET_stderr = stderr;
1610 if (!InitializeCriticalSectionAndSpinCount(&output_message_cs, 0x00000400))
1619 void __attribute__ ((destructor)) GNUNET_util_cl_fini()
1622 DeleteCriticalSection(&output_message_cs);
1629 /* end of common_logging.c */