commit ee95430d397d2382227cdeac8c678c7345df594d Author: George Kadianakis desnacked@gmail.com Date: Wed Dec 1 03:32:42 2010 +0200
Implement more heartbeat message stuff.
(This squashes multiple commits:
* Adds uptime monitoring support. * Adds circuit counting code. * Trivially tweaks the documentation. * Trivial run_scheduled_events() code tweaking. * Adds a status.h to export functions. * Added bandwidth monitoring code. * Added consensus presense detection code. * Restricts the precision of the bandwidth output. * Various fixes. * Fixed style and spacing problems. * Tidied up src/or/Makefile.am * Couple of minor fixes on status.c functions. * 'Implemented' client heartbeat support ) --- doc/tor.1.txt | 3 +- src/or/Makefile.am | 7 ++-- src/or/config.c | 3 +- src/or/main.c | 32 +++++++++++++---- src/or/main.h | 3 ++ src/or/or.h | 2 +- src/or/status.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++----- src/or/status.h | 10 +++++ 8 files changed, 140 insertions(+), 23 deletions(-)
diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 9020a80..7ba5302 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -931,7 +931,8 @@ is non-zero): **HeartbeatPeriod** __N__ **minutes**|**hours**|**days**|**weeks**:: Log a heartbeat message every **HeartbeatPeriod** seconds. This is a log level __info__ message, designed to let you know your Tor - instance is still alive and doing useful things. (Default: 6 hours) + server is still alive and doing useful things. Settings this + to 0 will disable the heartbeat. (Default: 6 hours)
**AccountingMax** __N__ **bytes**|**KB**|**MB**|**GB**|**TB**:: Never send more than the specified number of bytes in a given accounting diff --git a/src/or/Makefile.am b/src/or/Makefile.am index a49a86a..f0d5a0f 100644 --- a/src/or/Makefile.am +++ b/src/or/Makefile.am @@ -50,10 +50,10 @@ libtor_a_SOURCES = \ router.c \ routerlist.c \ routerparse.c \ + status.c \ $(evdns_source) \ $(tor_platform_source) \ - config_codedigest.c \ - status.c + config_codedigest.c
#libtor_a_LIBADD = ../common/libor.a ../common/libor-crypto.a \ # ../common/libor-event.a @@ -120,7 +120,8 @@ noinst_HEADERS = \ router.h \ routerlist.h \ routerparse.h \ - micro-revision.i + status.h \ + micro-revision.i
config_codedigest.o: or_sha1.i
diff --git a/src/or/config.c b/src/or/config.c index e2b2b5c..8bf4842 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -3381,7 +3381,7 @@ options_validate(or_options_t *old_options, or_options_t *options, "raising to %d seconds.", MIN_CIRCUIT_STREAM_TIMEOUT); options->CircuitStreamTimeout = MIN_CIRCUIT_STREAM_TIMEOUT; } - + if (options->HeartbeatPeriod && options->HeartbeatPeriod < MIN_HEARTBEAT_PERIOD) { log_warn(LD_CONFIG, "HeartbeatPeriod option is too short; " @@ -3389,7 +3389,6 @@ options_validate(or_options_t *old_options, or_options_t *options, options->HeartbeatPeriod = MIN_HEARTBEAT_PERIOD; }
- if (options->KeepalivePeriod < 1) REJECT("KeepalivePeriod option must be positive.");
diff --git a/src/or/main.c b/src/or/main.c index 6e3cb2b..c1335ff 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -45,6 +45,7 @@ #include "router.h" #include "routerlist.h" #include "routerparse.h" +#include "status.h" #ifdef USE_DMALLOC #include <dmalloc.h> #include <openssl/crypto.h> @@ -1050,7 +1051,7 @@ run_scheduled_events(time_t now) static time_t time_to_check_port_forwarding = 0; static int should_init_bridge_stats = 1; static time_t time_to_retry_dns_init = 0; - static time_t time_last_written_heartbeat = 0; + static time_t time_to_next_heartbeat = 0; or_options_t *options = get_options(); int is_server = server_mode(options); int i; @@ -1265,7 +1266,7 @@ run_scheduled_events(time_t now) /* If we're a server and initializing dns failed, retry periodically. */ if (time_to_retry_dns_init < now) { time_to_retry_dns_init = now + RETRY_DNS_INTERVAL; - if (server_mode(options) && has_dns_init_failed()) + if (is_server && has_dns_init_failed()) dns_init(); }
@@ -1296,7 +1297,7 @@ run_scheduled_events(time_t now) consider_publishable_server(0); /* also, check religiously for reachability, if it's within the first * 20 minutes of our uptime. */ - if (server_mode(options) && + if (is_server && (can_complete_circuit || !any_predicted_circuits(now)) && !we_are_hibernating()) { if (stats_n_seconds_working < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) { @@ -1433,7 +1434,7 @@ run_scheduled_events(time_t now)
if (time_to_check_port_forwarding < now && options->PortForwarding && - server_mode(options)) { + is_server) { #define PORT_FORWARDING_CHECK_INTERVAL 5 tor_check_port_forwarding(options->PortForwardingHelper, options->DirPort, @@ -1441,12 +1442,13 @@ run_scheduled_events(time_t now) now); time_to_check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL; } - + /** 11. write the heartbeat message */ if (options->HeartbeatPeriod && - time_last_written_heartbeat + options->HeartbeatPeriod < now) + time_to_next_heartbeat < now) { log_heartbeat(now); - time_last_written_heartbeat = now; + time_to_next_heartbeat = now+options->HeartbeatPeriod; + } }
/** Timer: used to invoke second_elapsed_callback() once per second. */ @@ -1911,6 +1913,22 @@ signal_callback(int fd, short events, void *arg) } }
+/** Returns Tor's uptime. */ +long +get_uptime(void) +{ + return stats_n_seconds_working; +} + +/** Fills <b>n_read_in</b> with total bytes read and <b>n_written_out</b> + with total bytes written */ +void +get_traffic_stats(uint64_t *n_read_in, uint64_t *n_written_out) +{ + *n_read_in = stats_n_bytes_read; + *n_written_out = stats_n_bytes_written; +} + extern uint64_t rephist_total_alloc; extern uint32_t rephist_total_num;
diff --git a/src/or/main.h b/src/or/main.h index 4e15d4d..49ed5fe 100644 --- a/src/or/main.h +++ b/src/or/main.h @@ -49,6 +49,9 @@ void directory_info_has_arrived(time_t now, int from_cache); void ip_address_changed(int at_interface); void dns_servers_relaunch_checks(void);
+long get_uptime(void); +void get_traffic_stats(uint64_t *in, uint64_t *out); + void control_signal_act(int the_signal); void handle_signals(int is_parent);
diff --git a/src/or/or.h b/src/or/or.h index 4f3fef0..90f01e1 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2718,7 +2718,7 @@ typedef struct { config_line_t *HidServAuth; /**< List of configuration lines for client-side * authorizations for hidden services */ char *ContactInfo; /**< Contact info to be published in the directory. */ - + int HeartbeatPeriod; /**< Log heartbeat messages after this many seconds * have passed. */
diff --git a/src/or/status.c b/src/or/status.c index 0cd9a07..c6a007b 100644 --- a/src/or/status.c +++ b/src/or/status.c @@ -7,21 +7,106 @@ **/
#include "or.h" +#include "config.h" +#include "status.h" +#include "nodelist.h" +#include "router.h" +#include "circuitlist.h" +#include "main.h"
+/** Returns the number of open circuits. */ +static int +count_circuits(void) +{ + circuit_t *circ; + int nr=0;
-/****************************************************************************/ + for (circ = _circuit_get_global_list(); circ; circ = circ->next) + nr++;
+ return nr; +} + +/* Takes seconds <b>secs</b> and returns a human-readable uptime string */ +static char * +secs_to_uptime(long secs) +{ + long int days = secs / 86400; + int hours = (secs - (days * 86400)) / 3600; + int minutes = (secs - (days * 86400) - (hours * 3600)) / 60; + char *uptime_string = NULL; + + switch (days) { + case 0: + tor_asprintf(&uptime_string, "%d:%02d", hours, minutes); + break; + case 1: + tor_asprintf(&uptime_string, "%ld day %d:%02d", days, hours, minutes); + break; + default: + tor_asprintf(&uptime_string, "%ld days %d:%02d", days, hours, minutes); + break; + } + + return uptime_string; +} + +/* Takes <b>bytes</b> and returns a human-readable bandwidth string. */ +static char * +bytes_to_bandwidth(uint64_t bytes) +{ + char *bw_string = NULL;
+ if (bytes < (1<<20)) /* Less than a megabyte. */ + tor_asprintf(&bw_string, U64_FORMAT" kB", U64_PRINTF_ARG(bytes>>10)); + else if (bytes < (1<<30)) { /* Megabytes. Let's add some precision. */ + double bw = U64_TO_DBL(bytes); + tor_asprintf(&bw_string, "%.2f MB", bw/(1<<20)); + } else { /* Gigabytes. */ + double bw = U64_TO_DBL(bytes); + tor_asprintf(&bw_string, "%.2f GB", bw/(1<<30)); + }
-#define BEAT(x) log_fn(LOG_NOTICE, LD_HEARTBEAT, (x) ) + return bw_string; +} + +/* This function provides the heartbeat log message */ +int +log_heartbeat(time_t now) +{ + uint64_t in,out; + char *bw_sent = NULL; + char *bw_rcvd = NULL; + char *uptime = NULL; + const routerinfo_t *me; + const node_t *myself; + + or_options_t *options = get_options(); + int is_server = server_mode(options);
-void -log_heartbeat(time_t now) { - or_options_t *opt = get_options(); + if (is_server) { + /* Let's check if we are in the current cached consensus. */ + if (!(me = router_get_my_routerinfo())) + return -1; /* Something stinks, we won't even attempt this. */ + else + if (!(myself = node_get_by_id(me->cache_info.identity_digest))) + log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: It seems like we are not " + "in the cached consensus."); + }
- (void) now; - log_fn(LOG_NOTICE, LD_HEARTBEAT, "This is the Tor heartbeat message."); - if (!server_mode(opt)) - BEAT("you are a client, hahaha"); + get_traffic_stats(&in, &out); + uptime = secs_to_uptime(get_uptime()); + bw_sent = bytes_to_bandwidth(out); + bw_rcvd = bytes_to_bandwidth(in);
+ log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: Tor's uptime is %s, with %d " + "circuits open, I've pushed %s and received %s.", + uptime, count_circuits(),bw_sent,bw_rcvd); + + tor_free(uptime); + tor_free(bw_sent); + tor_free(bw_rcvd); + + return 0; } + diff --git a/src/or/status.h b/src/or/status.h new file mode 100644 index 0000000..ac726a1 --- /dev/null +++ b/src/or/status.h @@ -0,0 +1,10 @@ +/* Copyright (c) 2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef _TOR_STATUS_H +#define _TOR_STATUS_H + +int log_heartbeat(time_t now); + +#endif +