[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [obfsproxy/master] Logging subsystem code.
commit 792954eb8ebc389f44c1e651c67e1dee738ba4ae
Author: George Kadianakis <desnacked@xxxxxxxxx>
Date: Thu Jun 9 23:23:57 2011 +0200
Logging subsystem code.
---
src/util.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/util.h | 66 ++++++++++++--
2 files changed, 342 insertions(+), 12 deletions(-)
diff --git a/src/util.c b/src/util.c
index baebe10..6ff337f 100644
--- a/src/util.c
+++ b/src/util.c
@@ -9,9 +9,27 @@
#include <stdio.h>
#include <stdlib.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "util.h"
+
#include <event2/util.h>
#include <event2/dns.h>
+static const char *sev_to_string(int severity);
+static int sev_is_valid(int severity);
+static int write_logfile_prologue(int fd);
+static int compose_logfile_prologue(char *buf, size_t buflen);
+static int string_to_sev(char *string);
+static int open_and_set_obfsproxy_logfile(char *filename);
+
+
+/************************ Obfsproxy Network Routines *************************/
+
int
resolve_address_port(const char *address,
int nodns, int passive,
@@ -33,7 +51,7 @@ resolve_address_port(const char *address,
} else if (default_port) {
portstr = default_port;
} else {
- fprintf(stderr, "Error in address %s: port required.\n", address);
+ log_debug("Error in address %s: port required.", address);
goto done;
}
@@ -47,16 +65,16 @@ resolve_address_port(const char *address,
ai_hints.ai_flags |= EVUTIL_AI_NUMERICHOST;
if ((ai_res = evutil_getaddrinfo(a, portstr, &ai_hints, &ai))) {
- fprintf(stderr, "Error resolving %s (%s) (%s): %s\n",
- address, a, portstr, evutil_gai_strerror(ai_res));
+ log_warn("Error resolving %s (%s) (%s): %s",
+ address, a, portstr, evutil_gai_strerror(ai_res));
goto done;
}
if (ai == NULL) {
- fprintf(stderr, "No result for address %s\n", address);
+ log_warn("No result for address %s", address);
goto done;
}
if (ai->ai_addrlen > sizeof(struct sockaddr_storage)) {
- fprintf(stderr, "Result for address %s too long\n", address);
+ log_warn("Result for address %s too long", address);
goto done;
}
@@ -85,3 +103,263 @@ init_evdns_base(struct event_base *base)
the_evdns_base = evdns_base_new(base, 1);
return the_evdns_base == NULL ? -1 : 0;
}
+
+/************************ String Functions *************************/
+/** The functions in this section were carbon copied off tor. Thank you tor! */
+
+/** Replacement for snprintf. Differs from platform snprintf in two
+ * ways: First, always NUL-terminates its output. Second, always
+ * returns -1 if the result is truncated. (Note that this return
+ * behavior does <i>not</i> conform to C99; it just happens to be
+ * easier to emulate "return -1" with conformant implementations than
+ * it is to emulate "return number that would be written" with
+ * non-conformant implementations.) */
+int
+obfs_snprintf(char *str, size_t size, const char *format, ...)
+{
+ va_list ap;
+ int r;
+ va_start(ap,format);
+ r = obfs_vsnprintf(str,size,format,ap);
+ va_end(ap);
+ return r;
+}
+
+/** Replacement for vsnprintf; behavior differs as obfs_snprintf differs from
+ * snprintf.
+ */
+int
+obfs_vsnprintf(char *str, size_t size, const char *format, va_list args)
+{
+ int r;
+ if (size == 0)
+ return -1; /* no place for the NUL */
+ if (size > SIZE_T_CEILING)
+ return -1;
+#ifdef MS_WINDOWS
+ r = _vsnprintf(str, size, format, args);
+#else
+ r = vsnprintf(str, size, format, args);
+#endif
+ str[size-1] = '\0';
+ if (r < 0 || r >= (ssize_t)size)
+ return -1;
+ return r;
+}
+
+/************************ Logging Subsystem *************************/
+/** The code of this section was to a great extend shamelessly copied
+ off tor. It's basicaly a stripped down version of tor's logging
+ system. Thank you tor. */
+
+/* Size of maximum log entry, including newline and NULL byte. */
+#define MAX_LOG_ENTRY 1024
+/* String to append when a log entry doesn't fit in MAX_LOG_ENTRY. */
+#define TRUNCATED_STR "[...truncated]"
+/* strlen(TRUNCATED_STR) */
+#define TRUNCATED_STR_LEN 14
+
+/* logging method */
+static int logging_method=LOG_METHOD_STDOUT;
+/* minimum logging severity */
+static int logging_min_sev=LOG_SEV_INFO;
+/* logfile fd */
+static int logging_logfile=-1;
+
+/** Helper: map a log severity to descriptive string. */
+static const char *
+sev_to_string(int severity)
+{
+ switch (severity) {
+ case LOG_SEV_WARN: return "warn";
+ case LOG_SEV_INFO: return "info";
+ case LOG_SEV_DEBUG: return "debug";
+ default:
+ assert(0); return "UNKNOWN";
+ }
+}
+
+/** If 'string' is a valid log severity, return the corresponding
+ * numeric value. Otherwise, return -1. */
+static int
+string_to_sev(char *string)
+{
+ if (!strcasecmp(string, "warn"))
+ return LOG_SEV_WARN;
+ else if (!strcasecmp(string, "info"))
+ return LOG_SEV_INFO;
+ else if (!strcasecmp(string, "debug"))
+ return LOG_SEV_DEBUG;
+ else
+ return -1;
+}
+
+/**
+ Returns True if 'severity' is a valid obfsproxy logging severity.
+ Otherwise, it returns False.
+*/
+static int
+sev_is_valid(int severity)
+{
+ return (severity == LOG_SEV_WARN ||
+ severity == LOG_SEV_INFO ||
+ severity == LOG_SEV_DEBUG);
+}
+
+/**
+ Sets the global logging 'method' and also sets and open the logfile
+ 'filename' in case we want to log into a file.
+ It returns 1 on success and -1 on fail.
+*/
+int
+log_set_method(int method, char *filename)
+{
+
+ logging_method = method;
+ if (method == LOG_METHOD_FILE) {
+ if (open_and_set_obfsproxy_logfile(filename) < 0)
+ return -1;
+ if (write_logfile_prologue(logging_logfile) < 0)
+ return -1;
+ }
+ return 1;
+}
+
+/**
+ Helper: Opens 'filename' and sets it as the obfsproxy logfile.
+ On success it returns 1, on fail it returns -1.
+*/
+static int
+open_and_set_obfsproxy_logfile(char *filename)
+{
+ if (!filename)
+ return -1;
+ logging_logfile = open(filename,
+ O_WRONLY|O_CREAT|O_APPEND,
+ 0644);
+ if (logging_logfile < 0)
+ return -1;
+ return 1;
+}
+
+/**
+ Closes the obfsproxy logfile if it exists.
+ Returns 0 on success or if we weren't using a logfile (that's
+ close()'s success return value) and -1 on failure.
+*/
+int
+close_obfsproxy_logfile(void)
+{
+ if (logging_logfile < 0) /* no logfile. */
+ return 0;
+ else
+ return close(logging_logfile);
+}
+
+/**
+ Writes a small prologue in the logfile 'fd' that mentions the
+ obfsproxy version and helps separate log instances.
+*/
+static int
+write_logfile_prologue(int logfile) {
+ char buf[256];
+ if (compose_logfile_prologue(buf, sizeof(buf)) < 0)
+ return -1;
+ if (write(logfile, buf, strlen(buf)) < 0)
+ return -1;
+ return 1;
+}
+
+#define TEMP_PROLOGUE "\nBrand new obfsproxy log:\n"
+/**
+ Helper: Composes the logfile prologue.
+*/
+static int
+compose_logfile_prologue(char *buf, size_t buflen)
+{
+ if (obfs_snprintf(buf, buflen, TEMP_PROLOGUE) < 0) {
+ log_warn("Logfile prologue couldn't be written.");
+ return -1;
+ }
+ return 1;
+}
+#undef TEMP_PROLOGUE
+
+/**
+ Sets the minimum logging severity of obfsproxy to the severity
+ described by 'sev_string', then it returns 1. If 'sev_string' is
+ not a valid severity, it returns -1.
+*/
+int
+log_set_min_severity(char* sev_string) {
+ int severity = string_to_sev(sev_string);
+ if (!sev_is_valid(severity)) {
+ log_warn("Severity '%s' makes no sense.", sev_string);
+ return -1;
+ }
+ logging_min_sev = severity;
+ return 1;
+}
+
+/**
+ Logging function of obfsproxy.
+ Don't call this directly; use the log_* macros defined in util.h
+ instead.
+
+ It accepts a logging 'severity' and a 'format' string and logs the
+ message in 'format' according to the configured obfsproxy minimum
+ logging severity and logging method.
+*/
+void
+log_fn(int severity, const char *format, ...)
+{
+ assert(sev_is_valid(severity));
+
+ if (logging_method == LOG_METHOD_NULL)
+ return;
+
+ /* See if the user is interested in this log message. */
+ if (severity < logging_min_sev)
+ return;
+
+ size_t n=0;
+ int r=0;
+ char buf[MAX_LOG_ENTRY];
+
+ size_t buflen = MAX_LOG_ENTRY-2;
+
+ va_list ap;
+ va_start(ap,format);
+
+ r = obfs_snprintf(buf, buflen, "[%s] ", sev_to_string(severity));
+ if (r < 0)
+ n = strlen(buf);
+ else
+ n=r;
+
+ r = obfs_vsnprintf(buf+n, buflen-n, format, ap);
+ if (r < 0) {
+ if (buflen >= TRUNCATED_STR_LEN) {
+ size_t offset = buflen-TRUNCATED_STR_LEN;
+ r = obfs_snprintf(buf+offset, TRUNCATED_STR_LEN+1,
+ "%s", TRUNCATED_STR);
+ if (r < 0) assert(0);
+ }
+ n = buflen;
+ } else
+ n+=r;
+
+ buf[n]='\n';
+ buf[n+1]='\0';
+
+ va_end(ap);
+
+ if (logging_method == LOG_METHOD_STDOUT)
+ fprintf(stdout, "%s", buf);
+ else if (logging_method == LOG_METHOD_FILE) {
+ assert(logging_logfile);
+ if (write(logging_logfile, buf, strlen(buf)) < 0)
+ printf("%s(): Terrible write() error!!!\n", __func__);
+ } else
+ assert(0);
+}
diff --git a/src/util.h b/src/util.h
index 69bd768..a48f7d8 100644
--- a/src/util.h
+++ b/src/util.h
@@ -5,10 +5,17 @@
in all redistributed copies and derived works. There is no warranty.
*/
+/* va_list definition */
+#include <stdarg.h>
+
#ifndef UTIL_H
#define UTIL_H
struct sockaddr_storage;
+struct event_base;
+struct evdns_base;
+
+/***** Network functions stuff. *****/
int resolve_address_port(const char *address,
int nodns, int passive,
@@ -16,16 +23,61 @@ int resolve_address_port(const char *address,
int *addrlen_out,
const char *default_port);
-#ifdef DEBUG
-#define dbg(x) printf x
+struct evdns_base *get_evdns_base(void);
+int init_evdns_base(struct event_base *base);
+
+/***** String functions stuff. *****/
+
+/* The sizeof a size_t, as computed by sizeof. */
+#ifndef SIZEOF_SIZE_T
+#define SIZEOF_SIZE_T 4
+#endif
+#ifndef SSIZE_T_MAX
+#if (SIZEOF_SIZE_T == 4)
+#define SSIZE_T_MAX INT32_MAX
+#elif (SIZEOF_SIZE_T == 8)
+#define SSIZE_T_MAX INT64_MAX
#else
-#define dbg(x) ((void)0)
+#error "Can't define SSIZE_T_MAX"
+#endif
#endif
+/** Any size_t larger than this amount is likely to be an underflow. */
+#define SIZE_T_CEILING ((size_t)(SSIZE_T_MAX-16))
-struct event_base;
-struct evdns_base;
-struct evdns_base *get_evdns_base(void);
-int init_evdns_base(struct event_base *base);
+int obfs_vsnprintf(char *str, size_t size,
+ const char *format, va_list args);
+int obfs_snprintf(char *str, size_t size,
+ const char *format, ...);
+
+/***** Logging subsystem stuff. *****/
+
+void log_fn(int severity, const char *format, ...);
+int log_set_method(int method, char *filename);
+int log_set_min_severity(char* sev_string);
+int close_obfsproxy_logfile(void);
+
+#define log_info(args...) log_fn(LOG_SEV_INFO, args)
+#define log_warn(args...) log_fn(LOG_SEV_WARN, args)
+#define log_debug(args...) log_fn(LOG_SEV_DEBUG, args)
+
+/** Logging methods */
+
+/** Spit log messages on stdout. */
+#define LOG_METHOD_STDOUT 1
+/** Place log messages in a file. */
+#define LOG_METHOD_FILE 2
+/** We don't want no logs. */
+#define LOG_METHOD_NULL 3
+
+/** Logging severities */
+/** Warn-level severity: for messages that only appear when something has gone wrong. */
+#define LOG_SEV_WARN 3
+/** Info-level severity: for messages that should be sent to the user
+ during normal operation. */
+#define LOG_SEV_INFO 2
+/** Debug-level severity: for hyper-verbose messages of no interest to
+ anybody but developers. */
+#define LOG_SEV_DEBUG 1
#endif
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits