commit 3e61d45c607f2e420c28d94b2a42e082441b3bbd Author: Karsten Loesing karsten.loesing@gmx.net Date: Sat Feb 11 13:17:04 2012 +0100
Add heartbeat message with total connections and unique IP counters. --- Makefile.am | 2 + src/main.c | 24 +++++++++++ src/network.c | 3 + src/status.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/status.h | 13 ++++++ 5 files changed, 161 insertions(+), 0 deletions(-)
diff --git a/Makefile.am b/Makefile.am index 963c725..533629b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,6 +18,7 @@ libobfsproxy_a_SOURCES = \ src/network.c \ src/protocol.c \ src/socks.c \ + src/status.c \ src/util.c \ src/protocols/dummy.c \ src/protocols/obfs2.c @@ -48,6 +49,7 @@ noinst_HEADERS = \ src/protocol.h \ src/sha256.h \ src/socks.h \ + src/status.h \ src/util.h \ src/protocols/dummy.h \ src/protocols/obfs2.h \ diff --git a/src/main.c b/src/main.c index 1d7132d..607a153 100644 --- a/src/main.c +++ b/src/main.c @@ -22,6 +22,8 @@ #include "managed.h" #include "external.h"
+#include "status.h" + #include <errno.h> #include <signal.h> #include <stdio.h> @@ -32,6 +34,7 @@ static struct event_base *the_event_base; static struct event *sig_int; static struct event *sig_term; +static struct event *heartbeat;
/* Pluggable transport proxy mode. ('External' or 'Managed') */ static int is_external_proxy=1; @@ -193,6 +196,16 @@ handle_obfsproxy_args(const char *const *argv) return i; }
+/** Libevent callback: Log heartbeat message once every hour. */ +static void +heartbeat_cb(evutil_socket_t fd, short what, void *arg) +{ + (void) fd; + (void) what; + (void) arg; + status_log_heartbeat(); +} + /** Initialize basic components of obfsproxy. */ @@ -233,6 +246,16 @@ obfsproxy_init() if (event_add(sig_int,NULL) || event_add(sig_term,NULL)) { log_error("Failed to initialize signal handling."); } + + /* Initialize hourly heartbeat messages. */ + struct timeval one_hour; + one_hour.tv_sec = 3600; + one_hour.tv_usec = 0; + status_init(); + heartbeat = event_new(the_event_base, -1, EV_PERSIST, heartbeat_cb, NULL); + if (event_add(heartbeat, &one_hour)) { + log_error("Failed to initialize heartbeat logs."); + } }
/** @@ -251,6 +274,7 @@ obfsproxy_cleanup() event_base_free(get_event_base());
cleanup_crypto(); + status_cleanup(); close_obfsproxy_logfile(); }
diff --git a/src/network.c b/src/network.c index a7c1fa6..0a6852e 100644 --- a/src/network.c +++ b/src/network.c @@ -75,6 +75,8 @@ #include "socks.h" #include "protocol.h"
+#include "status.h" + #include <errno.h>
#include <event2/buffer.h> @@ -549,6 +551,7 @@ open_outbound(conn_t *conn, bufferevent_data_cb readcb) success: log_info("%s (%s): Successful outbound connection to '%s'.", safe_str(conn->peername), conn->cfg->vtable->name, safe_str(peername)); + status_note_connection(conn->peername); bufferevent_enable(buf, EV_READ|EV_WRITE); newconn->peername = peername; obfs_assert(connections); diff --git a/src/status.c b/src/status.c new file mode 100644 index 0000000..40cd968 --- /dev/null +++ b/src/status.c @@ -0,0 +1,119 @@ +/* Copyright 2012 The Tor Project + See LICENSE for other credits and copying information +*/ + +/** + * \file status.c + * \headerfile status.h + * \brief Keeps status information and logs heartbeat messages. + **/ + +#include "util.h" + +#include "container.h" + +#include <string.h> +#include <stdio.h> +#include <time.h> + +#include <event2/event.h> +#include <event2/listener.h> + +/** Count total connections. */ +static int connections = 0; + +/** Count connections from unique addresses. */ +static strmap_t *addresses = NULL; + +/** Initialize counting connections from unique addresses. */ +static void +connections_init(void) +{ + if (!addresses) + addresses = strmap_new(); +} + +/** Clear connection counters. */ +static void +connections_clear(int reinit) +{ + connections = 0; + if (!addresses) + return; + strmap_free(addresses, NULL); /* NULL, because no need to free values. */ + addresses = NULL; + if (reinit) + addresses = strmap_new(); +} + +/** Note that we saw a new connection. */ +void +status_note_connection(const char *addrport) +{ + char *addr = xstrdup(addrport), *p; + + if ((p = strrchr(addr, ':'))) { + *p = '\0'; + } else { + log_debug("Error in address %s: port expected.", addrport); + free(addr); + return; + } + + if (!addresses) + addresses = strmap_new(); + strmap_set_lc(addresses, addr, (void*)(1)); + free(addr); + connections++; +} + +/** Time when we started. */ +static time_t started = 0; + +/** Time when we last reset connection and address counters. */ +static time_t last_reset_counters = 0; + +/** Reset status information this often. */ +#define RESET_COUNTERS 86400 + +/** Initialize status information to print out heartbeat messages. */ +void +status_init(void) +{ + time_t now = time(NULL); + started = now; + last_reset_counters = now; + connections_init(); +} + +/** Free all memory used by printing heartbeat logs. */ +void +status_cleanup(void) +{ + started = 0; + last_reset_counters = 0; + connections_clear(0); +} + +/** Log information about our uptime and the number of connections we saw. + */ +void +status_log_heartbeat(void) +{ + time_t now = time(NULL); + long secs = now - started; + long days = secs / 86400; + int hours = (int)((secs - (days * 86400)) / 3600); + int last_reset_hours = (int) (now - last_reset_counters) / 3600; + int minutes = (int)((secs - (days * 86400) - (hours * 3600)) / 60); + log_info("Heartbeat: obfsproxy's uptime is %ld days, %d hours, and " + "%d minutes. During the last %d hours we saw %d connections " + "from %d unique addresses.", + days, hours, minutes, last_reset_hours, + connections, strmap_size(addresses)); + if (now - last_reset_counters >= RESET_COUNTERS) { + log_info("Resetting connection counters."); + connections_clear(1); + last_reset_counters += RESET_COUNTERS; + } +} diff --git a/src/status.h b/src/status.h new file mode 100644 index 0000000..54dfb9c --- /dev/null +++ b/src/status.h @@ -0,0 +1,13 @@ +/* Copyright 2012 The Tor Project + See LICENSE for other credits and copying information +*/ + +/** + * \file status.h + * \brief Headers for status.c. + **/ + +void status_init(void); +void status_cleanup(void); +void status_note_connection(const char *addrport); +void status_log_heartbeat(void);