aboutsummaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/buffers.c19
-rw-r--r--src/or/buffers.h1
-rw-r--r--src/or/circuitbuild.c40
-rw-r--r--src/or/circuitbuild.h4
-rw-r--r--src/or/command.c9
-rw-r--r--src/or/config.c39
-rw-r--r--src/or/connection.c40
-rw-r--r--src/or/connection_edge.c4
-rw-r--r--src/or/connection_edge.h1
-rw-r--r--src/or/connection_or.c59
-rw-r--r--src/or/connection_or.h6
-rw-r--r--src/or/control.c2
-rw-r--r--src/or/cpuworker.c2
-rw-r--r--src/or/directory.c2
-rw-r--r--src/or/dirserv.h1
-rw-r--r--src/or/dirvote.c8
-rw-r--r--src/or/eventdns.c34
-rw-r--r--src/or/geoip.c2
-rw-r--r--src/or/hibernate.h1
-rw-r--r--src/or/main.c13
-rw-r--r--src/or/microdesc.c2
-rw-r--r--src/or/networkstatus.c39
-rw-r--r--src/or/networkstatus.h1
-rw-r--r--src/or/ntmain.c114
-rw-r--r--src/or/onion.c11
-rw-r--r--src/or/or.h11
-rw-r--r--src/or/policies.c4
-rw-r--r--src/or/reasons.c12
-rw-r--r--src/or/relay.c75
-rw-r--r--src/or/relay.h3
-rw-r--r--src/or/rendclient.c2
-rw-r--r--src/or/rendservice.h1
-rw-r--r--src/or/rephist.c419
-rw-r--r--src/or/rephist.h25
-rw-r--r--src/or/routerparse.h5
35 files changed, 630 insertions, 381 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 3ba2760bf..e8422637c 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -270,14 +270,25 @@ buf_shrink_freelists(int free_all)
(freelists[i].lowest_length - slack);
int n_to_skip = freelists[i].cur_length - n_to_free;
int orig_n_to_free = n_to_free, n_freed=0;
+ int orig_n_to_skip = n_to_skip;
int new_length = n_to_skip;
chunk_t **chp = &freelists[i].head;
chunk_t *chunk;
- log_info(LD_MM, "Cleaning freelist for %d-byte chunks: keeping %d, "
- "dropping %d.",
- (int)freelists[i].alloc_size, n_to_skip, n_to_free);
+ log_info(LD_MM, "Cleaning freelist for %d-byte chunks: length %d, "
+ "keeping %d, dropping %d.",
+ (int)freelists[i].alloc_size, freelists[i].cur_length,
+ n_to_skip, n_to_free);
+ tor_assert(n_to_skip + n_to_free == freelists[i].cur_length);
while (n_to_skip) {
- tor_assert((*chp)->next);
+ if (! (*chp)->next) {
+ log_warn(LD_BUG, "I wanted to skip %d chunks in the freelist for "
+ "%d-byte chunks, but only found %d. (Length %d)",
+ orig_n_to_skip, (int)freelists[i].alloc_size,
+ orig_n_to_skip-n_to_skip, freelists[i].cur_length);
+ assert_freelist_ok(&freelists[i]);
+ return;
+ }
+ // tor_assert((*chp)->next);
chp = &(*chp)->next;
--n_to_skip;
}
diff --git a/src/or/buffers.h b/src/or/buffers.h
index 42d92dd89..8fd403d95 100644
--- a/src/or/buffers.h
+++ b/src/or/buffers.h
@@ -23,7 +23,6 @@ void buf_dump_freelist_sizes(int severity);
size_t buf_datalen(const buf_t *buf);
size_t buf_allocation(const buf_t *buf);
size_t buf_slack(const buf_t *buf);
-const char *_buf_peek_raw_buffer(const buf_t *buf);
int read_to_buf(int s, size_t at_most, buf_t *buf, int *reached_eof,
int *socket_error);
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 5bb9d70d5..5567b246a 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -605,19 +605,19 @@ circuit_build_times_filter_timeouts(circuit_build_times_t *cbt)
* after we do so. Use this result to estimate parameters and
* calculate the timeout.
*
- * Returns -1 and sets msg on error. Msg must be freed by the caller.
+ * Return -1 on error.
*/
int
circuit_build_times_parse_state(circuit_build_times_t *cbt,
- or_state_t *state, char **msg)
+ or_state_t *state)
{
int tot_values = 0;
uint32_t loaded_cnt = 0, N = 0;
config_line_t *line;
unsigned int i;
build_time_t *loaded_times;
+ int err = 0;
circuit_build_times_init(cbt);
- *msg = NULL;
if (circuit_build_times_disabled()) {
return 0;
@@ -631,8 +631,9 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
smartlist_split_string(args, line->value, " ",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
if (smartlist_len(args) < 2) {
- *msg = tor_strdup("Unable to parse circuit build times: "
- "Too few arguments to CircuitBuildTime");
+ log_warn(LD_GENERAL, "Unable to parse circuit build times: "
+ "Too few arguments to CircuitBuildTime");
+ err = 1;
SMARTLIST_FOREACH(args, char*, cp, tor_free(cp));
smartlist_free(args);
break;
@@ -645,8 +646,9 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
ms = (build_time_t)tor_parse_ulong(ms_str, 0, 0,
CBT_BUILD_TIME_MAX, &ok, NULL);
if (!ok) {
- *msg = tor_strdup("Unable to parse circuit build times: "
- "Unparsable bin number");
+ log_warn(LD_GENERAL, "Unable to parse circuit build times: "
+ "Unparsable bin number");
+ err = 1;
SMARTLIST_FOREACH(args, char*, cp, tor_free(cp));
smartlist_free(args);
break;
@@ -654,8 +656,9 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
count = (uint32_t)tor_parse_ulong(count_str, 0, 0,
UINT32_MAX, &ok, NULL);
if (!ok) {
- *msg = tor_strdup("Unable to parse circuit build times: "
- "Unparsable bin count");
+ log_warn(LD_GENERAL, "Unable to parse circuit build times: "
+ "Unparsable bin count");
+ err = 1;
SMARTLIST_FOREACH(args, char*, cp, tor_free(cp));
smartlist_free(args);
break;
@@ -692,10 +695,9 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
"Corrupt state file? Build times count mismatch. "
"Read %d times, but file says %d", loaded_cnt,
state->TotalBuildTimes);
- *msg = tor_strdup("Build times count mismatch.");
+ err = 1;
circuit_build_times_reset(cbt);
- tor_free(loaded_times);
- return -1;
+ goto done;
}
circuit_build_times_shuffle_and_store_array(cbt, loaded_times, loaded_cnt);
@@ -716,10 +718,9 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
"Corrupt state file? Shuffled build times mismatch. "
"Read %d times, but file says %d", tot_values,
state->TotalBuildTimes);
- *msg = tor_strdup("Build times count mismatch.");
+ err = 1;
circuit_build_times_reset(cbt);
- tor_free(loaded_times);
- return -1;
+ goto done;
}
circuit_build_times_set_timeout(cbt);
@@ -728,8 +729,9 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
circuit_build_times_filter_timeouts(cbt);
}
+ done:
tor_free(loaded_times);
- return *msg ? -1 : 0;
+ return err ? -1 : 0;
}
/**
@@ -1512,7 +1514,7 @@ static int
onion_populate_cpath(origin_circuit_t *circ)
{
int r;
-again:
+ again:
r = onion_extend_cpath(circ);
if (r < 0) {
log_info(LD_CIRC,"Generating cpath hop failed.");
@@ -1750,7 +1752,7 @@ circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
cell.circ_id = circ->n_circ_id;
memcpy(cell.payload, payload, ONIONSKIN_CHALLENGE_LEN);
- append_cell_to_circuit_queue(circ, circ->n_conn, &cell, CELL_DIRECTION_OUT);
+ append_cell_to_circuit_queue(circ, circ->n_conn, &cell, CELL_DIRECTION_OUT, 0);
if (CIRCUIT_IS_ORIGIN(circ)) {
/* mark it so it gets better rate limiting treatment. */
@@ -2327,7 +2329,7 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
circ->is_first_hop = (cell_type == CELL_CREATED_FAST);
append_cell_to_circuit_queue(TO_CIRCUIT(circ),
- circ->p_conn, &cell, CELL_DIRECTION_IN);
+ circ->p_conn, &cell, CELL_DIRECTION_IN, 0);
log_debug(LD_CIRC,"Finished sending 'created' cell.");
if (!is_local_addr(&circ->p_conn->_base.addr) &&
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 3a02f0420..f4cc2a904 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -81,7 +81,7 @@ extern circuit_build_times_t circ_times;
void circuit_build_times_update_state(circuit_build_times_t *cbt,
or_state_t *state);
int circuit_build_times_parse_state(circuit_build_times_t *cbt,
- or_state_t *state, char **msg);
+ or_state_t *state);
void circuit_build_times_count_timeout(circuit_build_times_t *cbt,
int did_onehop);
int circuit_build_times_count_close(circuit_build_times_t *cbt,
@@ -107,8 +107,6 @@ void circuit_build_times_initial_alpha(circuit_build_times_t *cbt,
double quantile, double time_ms);
int circuit_build_times_update_alpha(circuit_build_times_t *cbt);
double circuit_build_times_cdf(circuit_build_times_t *cbt, double x);
-void circuit_build_times_add_timeout_worker(circuit_build_times_t *cbt,
- double quantile_cutoff);
void circuitbuild_running_unit_tests(void);
void circuit_build_times_reset(circuit_build_times_t *cbt);
diff --git a/src/or/command.c b/src/or/command.c
index 0460e25c2..ea0bbea1e 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -288,7 +288,14 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
/* hand it off to the cpuworkers, and then return. */
if (assign_onionskin_to_cpuworker(NULL, circ, onionskin) < 0) {
- log_warn(LD_GENERAL,"Failed to hand off onionskin. Closing.");
+#define WARN_HANDOFF_FAILURE_INTERVAL (6*60*60)
+ static ratelim_t handoff_warning =
+ RATELIM_INIT(WARN_HANDOFF_FAILURE_INTERVAL);
+ char *m;
+ if ((m = rate_limit_log(&handoff_warning, approx_time()))) {
+ log_warn(LD_GENERAL,"Failed to hand off onionskin. Closing.%s",m);
+ tor_free(m);
+ }
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return;
}
diff --git a/src/or/config.c b/src/or/config.c
index 58cf2ff2d..6b3bcf6da 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -17,6 +17,7 @@
#include "config.h"
#include "connection.h"
#include "connection_edge.h"
+#include "connection_or.h"
#include "control.h"
#include "cpuworker.h"
#include "dirserv.h"
@@ -440,6 +441,12 @@ static config_var_t _state_vars[] = {
V(BWHistoryWriteEnds, ISOTIME, NULL),
V(BWHistoryWriteInterval, UINT, "900"),
V(BWHistoryWriteValues, CSV, ""),
+ V(BWHistoryDirReadEnds, ISOTIME, NULL),
+ V(BWHistoryDirReadInterval, UINT, "900"),
+ V(BWHistoryDirReadValues, CSV, ""),
+ V(BWHistoryDirWriteEnds, ISOTIME, NULL),
+ V(BWHistoryDirWriteInterval, UINT, "900"),
+ V(BWHistoryDirWriteValues, CSV, ""),
V(TorVersion, STRING, NULL),
@@ -1248,8 +1255,9 @@ options_act(or_options_t *old_options)
/* How long should we delay counting bridge stats after becoming a bridge?
* We use this so we don't count people who used our bridge thinking it is
* a relay. If you change this, don't forget to change the log message
- * below. */
-#define RELAY_BRIDGE_STATS_DELAY (2 * 60 * 60)
+ * below. It's 4 hours (the time it takes to stop being used by clients)
+ * plus some extra time for clock skew. */
+#define RELAY_BRIDGE_STATS_DELAY (6 * 60 * 60)
if (! bool_eq(options->BridgeRelay, old_options->BridgeRelay)) {
int was_relay = 0;
@@ -1261,7 +1269,7 @@ options_act(or_options_t *old_options)
}
geoip_bridge_stats_init(int_start);
log_info(LD_CONFIG, "We are acting as a bridge now. Starting new "
- "GeoIP stats interval%s.", was_relay ? " in 2 "
+ "GeoIP stats interval%s.", was_relay ? " in 6 "
"hours from now" : "");
} else {
geoip_bridge_stats_term();
@@ -1292,6 +1300,10 @@ options_act(or_options_t *old_options)
if (options->V3AuthoritativeDir && !old_options->V3AuthoritativeDir)
init_keys();
+
+ if (options->PerConnBWRate != old_options->PerConnBWRate ||
+ options->PerConnBWBurst != old_options->PerConnBWBurst)
+ connection_or_update_token_buckets(get_connection_array(), options);
}
/* Maybe load geoip file */
@@ -3489,6 +3501,13 @@ options_validate(or_options_t *old_options, or_options_t *options,
"upgrade your Tor controller as soon as possible.");
}
+ if (options->CookieAuthFileGroupReadable && !options->CookieAuthFile) {
+ log_warn(LD_CONFIG, "You set the CookieAuthFileGroupReadable but did "
+ "not configure a the path for the cookie file via "
+ "CookieAuthFile. This means your cookie will not be group "
+ "readable.");
+ }
+
if (options->UseEntryGuards && ! options->NumEntryGuards)
REJECT("Cannot enable UseEntryGuards with NumEntryGuards set to 0");
@@ -3813,7 +3832,7 @@ get_windows_conf_root(void)
{
static int is_set = 0;
static char path[MAX_PATH+1];
- WCHAR wpath[MAX_PATH] = {0};
+ TCHAR tpath[MAX_PATH] = {0};
LPITEMIDLIST idl;
IMalloc *m;
@@ -3840,8 +3859,12 @@ get_windows_conf_root(void)
return path;
}
/* Convert the path from an "ID List" (whatever that is!) to a path. */
- result = SHGetPathFromIDListW(idl, wpath);
- wcstombs(path,wpath,MAX_PATH);
+ result = SHGetPathFromIDList(idl, tpath);
+#ifdef UNICODE
+ wcstombs(path,tpath,MAX_PATH);
+#else
+ strlcpy(path,tpath,sizeof(path));
+#endif
/* Now we need to free the memory that the path-idl was stored in. In
* typical Windows fashion, we can't just call 'free()' on it. */
@@ -4966,9 +4989,7 @@ or_state_set(or_state_t *new_state)
tor_free(err);
ret = -1;
}
- if (circuit_build_times_parse_state(&circ_times, global_state, &err) < 0) {
- log_warn(LD_GENERAL,"%s",err);
- tor_free(err);
+ if (circuit_build_times_parse_state(&circ_times, global_state) < 0) {
ret = -1;
}
return ret;
diff --git a/src/or/connection.c b/src/or/connection.c
index 55d2fa814..91ce74b5b 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -839,13 +839,13 @@ static void
warn_too_many_conns(void)
{
#define WARN_TOO_MANY_CONNS_INTERVAL (6*60*60)
- static time_t last_warned = 0;
- time_t now = time(NULL);
- int n_conns = get_n_open_sockets();
- if (last_warned + WARN_TOO_MANY_CONNS_INTERVAL < now) {
+ static ratelim_t last_warned = RATELIM_INIT(WARN_TOO_MANY_CONNS_INTERVAL);
+ char *m;
+ if ((m = rate_limit_log(&last_warned, approx_time()))) {
+ int n_conns = get_n_open_sockets();
log_warn(LD_NET,"Failing because we have %d connections already. Please "
- "raise your ulimit -n.", n_conns);
- last_warned = now;
+ "raise your ulimit -n.%s", n_conns, m);
+ tor_free(m);
control_event_general_status(LOG_WARN, "TOO_MANY_CONNECTIONS CURRENT=%d",
n_conns);
}
@@ -2082,8 +2082,6 @@ static void
connection_buckets_decrement(connection_t *conn, time_t now,
size_t num_read, size_t num_written)
{
- if (!connection_is_rate_limited(conn))
- return; /* local IPs are free */
if (num_written >= INT_MAX || num_read >= INT_MAX) {
log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, "
"connection type=%s, state=%s",
@@ -2095,16 +2093,24 @@ connection_buckets_decrement(connection_t *conn, time_t now,
tor_fragile_assert();
}
+ /* Count bytes of answering direct and tunneled directory requests */
+ if (conn->type == CONN_TYPE_DIR && conn->purpose == DIR_PURPOSE_SERVER) {
+ if (num_read > 0)
+ rep_hist_note_dir_bytes_read(num_read, now);
+ if (num_written > 0)
+ rep_hist_note_dir_bytes_written(num_written, now);
+ }
+
+ if (!connection_is_rate_limited(conn))
+ return; /* local IPs are free */
if (num_read > 0) {
- if (conn->type == CONN_TYPE_EXIT)
- rep_hist_note_exit_bytes_read(conn->port, num_read);
rep_hist_note_bytes_read(num_read, now);
}
if (num_written > 0) {
- if (conn->type == CONN_TYPE_EXIT)
- rep_hist_note_exit_bytes_written(conn->port, num_written);
rep_hist_note_bytes_written(num_written, now);
}
+ if (conn->type == CONN_TYPE_EXIT)
+ rep_hist_note_exit_bytes(conn->port, num_written, num_read);
if (connection_counts_as_relayed_traffic(conn, now)) {
global_relayed_read_bucket -= (int)num_read;
@@ -2355,7 +2361,7 @@ connection_handle_read_impl(connection_t *conn)
return 0;
}
-loop_again:
+ loop_again:
try_to_read = max_to_read;
tor_assert(!conn->marked_for_close);
@@ -2401,8 +2407,12 @@ loop_again:
connection_t *linked = conn->linked_conn;
if (n_read) {
- /* Probably a no-op, but hey. */
- connection_buckets_decrement(linked, approx_time(), n_read, 0);
+ /* Probably a no-op, since linked conns typically don't count for
+ * bandwidth rate limiting. But do it anyway so we can keep stats
+ * accurately. Note that since we read the bytes from conn, and
+ * we're writing the bytes onto the linked connection, we count
+ * these as <i>written</i> bytes. */
+ connection_buckets_decrement(linked, approx_time(), 0, n_read);
if (connection_flushed_some(linked) < 0)
connection_mark_for_close(linked);
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index e83028fae..64f342993 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -2050,7 +2050,7 @@ get_unique_stream_id_by_circ(origin_circuit_t *circ)
streamid_t test_stream_id;
uint32_t attempts=0;
-again:
+ again:
test_stream_id = circ->next_stream_id++;
if (++attempts > 1<<16) {
/* Make sure we don't loop forever if all stream_id's are used. */
@@ -2988,7 +2988,7 @@ parse_extended_hostname(char *address, int allowdotexit)
if (rend_valid_service_id(query)) {
return ONION_HOSTNAME; /* success */
}
-failed:
+ failed:
/* otherwise, return to previous state and return 0 */
*s = '.';
return BAD_HOSTNAME;
diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h
index c3d6098c5..d1bce48e8 100644
--- a/src/or/connection_edge.h
+++ b/src/or/connection_edge.h
@@ -82,7 +82,6 @@ void addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
int connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath);
-int hostname_is_noconnect_address(const char *address);
/** Possible return values for parse_extended_hostname. */
typedef enum hostname_type_t {
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 405df1578..0ba1bca31 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -349,21 +349,18 @@ connection_or_digest_is_known_relay(const char *id_digest)
return 0;
}
-/** If we don't necessarily know the router we're connecting to, but we
- * have an addr/port/id_digest, then fill in as much as we can. Start
- * by checking to see if this describes a router we know. */
+/** Set the per-conn read and write limits for <b>conn</b>. If it's a known
+ * relay, we will rely on the global read and write buckets, so give it
+ * per-conn limits that are big enough they'll never matter. But if it's
+ * not a known relay, first check if we set PerConnBwRate/Burst, then
+ * check if the consensus sets them, else default to 'big enough'.
+ */
static void
-connection_or_init_conn_from_address(or_connection_t *conn,
- const tor_addr_t *addr, uint16_t port,
- const char *id_digest,
- int started_here)
+connection_or_update_token_buckets_helper(or_connection_t *conn, int reset,
+ or_options_t *options)
{
- or_options_t *options = get_options();
int rate, burst; /* per-connection rate limiting params */
- routerinfo_t *r = router_get_by_digest(id_digest);
- connection_or_set_identity_digest(conn, id_digest);
-
- if (connection_or_digest_is_known_relay(id_digest)) {
+ if (connection_or_digest_is_known_relay(conn->identity_digest)) {
/* It's in the consensus, or we have a descriptor for it meaning it
* was probably in a recent consensus. It's a recognized relay:
* give it full bandwidth. */
@@ -382,7 +379,43 @@ connection_or_init_conn_from_address(or_connection_t *conn,
}
conn->bandwidthrate = rate;
- conn->read_bucket = conn->write_bucket = conn->bandwidthburst = burst;
+ conn->bandwidthburst = burst;
+ if (reset) { /* set up the token buckets to be full */
+ conn->read_bucket = conn->write_bucket = burst;
+ return;
+ }
+ /* If the new token bucket is smaller, take out the extra tokens.
+ * (If it's larger, don't -- the buckets can grow to reach the cap.) */
+ if (conn->read_bucket > burst)
+ conn->read_bucket = burst;
+ if (conn->write_bucket > burst)
+ conn->write_bucket = burst;
+}
+
+/** Either our set of relays or our per-conn rate limits have changed.
+ * Go through all the OR connections and update their token buckets. */
+void
+connection_or_update_token_buckets(smartlist_t *conns, or_options_t *options)
+{
+ SMARTLIST_FOREACH(conns, connection_t *, conn,
+ {
+ if (connection_speaks_cells(conn))
+ connection_or_update_token_buckets_helper(TO_OR_CONN(conn), 0, options);
+ });
+}
+
+/** If we don't necessarily know the router we're connecting to, but we
+ * have an addr/port/id_digest, then fill in as much as we can. Start
+ * by checking to see if this describes a router we know. */
+static void
+connection_or_init_conn_from_address(or_connection_t *conn,
+ const tor_addr_t *addr, uint16_t port,
+ const char *id_digest,
+ int started_here)
+{
+ routerinfo_t *r = router_get_by_digest(id_digest);
+ connection_or_set_identity_digest(conn, id_digest);
+ connection_or_update_token_buckets_helper(conn, 1, get_options());
conn->_base.port = port;
tor_addr_copy(&conn->_base.addr, addr);
diff --git a/src/or/connection_or.h b/src/or/connection_or.h
index 8e3723c15..717630217 100644
--- a/src/or/connection_or.h
+++ b/src/or/connection_or.h
@@ -26,6 +26,8 @@ int connection_or_flushed_some(or_connection_t *conn);
int connection_or_finished_flushing(or_connection_t *conn);
int connection_or_finished_connecting(or_connection_t *conn);
int connection_or_digest_is_known_relay(const char *id_digest);
+void connection_or_update_token_buckets(smartlist_t *conns,
+ or_options_t *options);
void connection_or_connect_failed(or_connection_t *conn,
int reason, const char *msg);
@@ -44,10 +46,6 @@ void connection_or_write_var_cell_to_buf(const var_cell_t *cell,
int connection_or_send_destroy(circid_t circ_id, or_connection_t *conn,
int reason);
int connection_or_send_netinfo(or_connection_t *conn);
-int connection_or_send_cert(or_connection_t *conn);
-int connection_or_send_link_auth(or_connection_t *conn);
-int connection_or_compute_link_auth_hmac(or_connection_t *conn,
- char *hmac_out);
int is_or_protocol_version_known(uint16_t version);
void cell_pack(packed_cell_t *dest, const cell_t *src);
diff --git a/src/or/control.c b/src/or/control.c
index 7cbb1bd1f..7eead0e18 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2259,7 +2259,7 @@ handle_control_setcircuitpurpose(control_connection_t *conn,
circ->_base.purpose = new_purpose;
connection_write_str_to_buf("250 OK\r\n", conn);
-done:
+ done:
if (args) {
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 2760d9666..6f943d78b 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -192,7 +192,7 @@ connection_cpu_process_inbuf(connection_t *conn)
tor_assert(0); /* don't ask me to do handshakes yet */
}
-done_processing:
+ done_processing:
conn->state = CPUWORKER_STATE_IDLE;
num_cpuworkers_busy--;
if (conn->timestamp_created < last_rotation_time) {
diff --git a/src/or/directory.c b/src/or/directory.c
index f584bc385..97ee0c9fb 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -584,7 +584,7 @@ connection_dir_request_failed(dir_connection_t *conn)
if (directory_conn_is_self_reachability_test(conn)) {
return; /* this was a test fetch. don't retry. */
}
- if (entry_list_is_constrained(get_options()))
+ if (!entry_list_is_constrained(get_options()))
router_set_status(conn->identity_digest, 0); /* don't try him again */
if (conn->_base.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) {
log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
diff --git a/src/or/dirserv.h b/src/or/dirserv.h
index fc5a5549c..5ebcb8b2b 100644
--- a/src/or/dirserv.h
+++ b/src/or/dirserv.h
@@ -55,7 +55,6 @@ enum was_router_added_t dirserv_add_multiple_descriptors(
enum was_router_added_t dirserv_add_descriptor(routerinfo_t *ri,
const char **msg,
const char *source);
-void dirserv_free_descriptors(void);
void dirserv_set_router_is_running(routerinfo_t *router, time_t now);
int list_server_status_v1(smartlist_t *routers, char **router_status_out,
int for_controller);
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index fd4d742cc..eae3bc8a4 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -762,7 +762,7 @@ networkstatus_check_weights(int64_t Wgg, int64_t Wgd, int64_t Wmg,
}
}
-out:
+ out:
if (berr) {
log_info(LD_DIR,
"Bw weight mismatch %d. G="I64_FORMAT" M="I64_FORMAT
@@ -2942,6 +2942,7 @@ dirvote_compute_consensuses(void)
strlen(pending_consensus_signatures), 0);
log_notice(LD_DIR, "Signature(s) posted.");
+ smartlist_free(votes);
return 0;
err:
smartlist_free(votes);
@@ -3008,6 +3009,7 @@ dirvote_add_signatures_to_pending_consensus(
networkstatus_vote_free(v);
}
*msg_out = "Signatures added";
+ tor_free(new_signatures);
} else if (r == 0) {
*msg_out = "Signatures ignored";
} else {
@@ -3137,7 +3139,7 @@ void
dirvote_free_all(void)
{
dirvote_clear_votes(1);
- /* now empty as a result of clear_pending_votes. */
+ /* now empty as a result of dirvote_clear_votes(). */
smartlist_free(pending_vote_list);
pending_vote_list = NULL;
smartlist_free(previous_vote_list);
@@ -3146,7 +3148,7 @@ dirvote_free_all(void)
dirvote_clear_pending_consensuses();
tor_free(pending_consensus_signatures);
if (pending_consensus_signature_list) {
- /* now empty as a result of clear_pending_votes. */
+ /* now empty as a result of dirvote_clear_votes(). */
smartlist_free(pending_consensus_signature_list);
pending_consensus_signature_list = NULL;
}
diff --git a/src/or/eventdns.c b/src/or/eventdns.c
index 4e44d1516..14c5d88df 100644
--- a/src/or/eventdns.c
+++ b/src/or/eventdns.c
@@ -3132,7 +3132,7 @@ load_nameservers_with_getnetworkparams(void)
GetNetworkParams_fn_t fn;
/* XXXX Possibly, we should hardcode the location of this DLL. */
- if (!(handle = LoadLibraryW(L"iphlpapi.dll"))) {
+ if (!(handle = LoadLibrary(TEXT("iphlpapi.dll"))) {
log(EVDNS_LOG_WARN, "Could not open iphlpapi.dll");
/* right now status = 0, doesn't that mean "good" - mikec */
status = -1;
@@ -3201,46 +3201,44 @@ load_nameservers_with_getnetworkparams(void)
}
static int
-config_nameserver_from_reg_key(HKEY key, const char *subkey)
+config_nameserver_from_reg_key(HKEY key, const TCHAR *subkey)
{
char *buf;
DWORD bufsz = 0, type = 0;
- WCHAR wsubkey[MAX_PATH] = {0};
- char ansibuf[MAX_PATH] = {0};
int status = 0;
- mbstowcs(wsubkey,subkey,MAX_PATH);
- if (RegQueryValueExW(key, wsubkey, 0, &type, NULL, &bufsz)
+ if (RegQueryValueEx(key, subkey, 0, &type, NULL, &bufsz)
!= ERROR_MORE_DATA)
return -1;
if (!(buf = mm_malloc(bufsz)))
return -1;
- if (RegQueryValueExW(key, wsubkey, 0, &type, (LPBYTE)buf, &bufsz)
+ if (RegQueryValueEx(key, subkey, 0, &type, (LPBYTE)buf, &bufsz)
== ERROR_SUCCESS && bufsz > 1) {
- wcstombs(ansibuf,(wchar_t*)buf,MAX_PATH);
- status = evdns_nameserver_ip_add_line(ansibuf);
+ wcstombs(ansibuf,(wchar_t*)buf,MAX_PATH);/*XXXX UNICODE */
+ status = evdns_nameserver_ip_add_line(buf);
}
mm_free(buf);
return status;
}
-#define SERVICES_KEY L"System\\CurrentControlSet\\Services\\"
-#define WIN_NS_9X_KEY SERVICES_KEY L"VxD\\MSTCP"
-#define WIN_NS_NT_KEY SERVICES_KEY L"Tcpip\\Parameters"
+#define SERVICES_KEY TEXT("System\\CurrentControlSet\\Services\\")
+#define WIN_NS_9X_KEY SERVICES_KEY TEXT("VxD\\MSTCP")
+#define WIN_NS_NT_KEY SERVICES_KEY TEXT("Tcpip\\Parameters")
static int
load_nameservers_from_registry(void)
{
int found = 0;
int r;
- OSVERSIONINFO info = {0};
+ OSVERSIONINFO info;
+ memset(&info, 0, sizeof(info));
info.dwOSVersionInfoSize = sizeof (info);
- GetVersionExW((LPOSVERSIONINFO)&info);
+ GetVersionEx(&info);
#define TRY(k, name) \
- if (!found && config_nameserver_from_reg_key(k,name) == 0) { \
+ if (!found && config_nameserver_from_reg_key(k,TEXT(name)) == 0) { \
log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name); \
found = 1; \
} else if (!found) { \
@@ -3251,12 +3249,12 @@ load_nameservers_from_registry(void)
if (info.dwMajorVersion >= 5) { /* NT */
HKEY nt_key = 0, interfaces_key = 0;
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
KEY_READ, &nt_key) != ERROR_SUCCESS) {
log(EVDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError());
return -1;
}
- r = RegOpenKeyExW(nt_key, L"Interfaces", 0,
+ r = RegOpenKeyEx(nt_key, Text("Interfaces"), 0,
KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS,
&interfaces_key);
if (r != ERROR_SUCCESS) {
@@ -3271,7 +3269,7 @@ load_nameservers_from_registry(void)
RegCloseKey(nt_key);
} else {
HKEY win_key = 0;
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0,
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0,
KEY_READ, &win_key) != ERROR_SUCCESS) {
log(EVDNS_LOG_DEBUG, "Couldn't open registry key, %d", (int)GetLastError());
return -1;
diff --git a/src/or/geoip.c b/src/or/geoip.c
index cde9cabdb..d9c8a0151 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -829,7 +829,7 @@ geoip_get_client_history(geoip_client_action_t action)
smartlist_add(chunks, buf);
});
result = smartlist_join_strings(chunks, ",", 0, NULL);
-done:
+ done:
tor_free(counts);
if (chunks) {
SMARTLIST_FOREACH(chunks, char *, c, tor_free(c));
diff --git a/src/or/hibernate.h b/src/or/hibernate.h
index 8192ac5d8..687fadb66 100644
--- a/src/or/hibernate.h
+++ b/src/or/hibernate.h
@@ -24,7 +24,6 @@ void consider_hibernation(time_t now);
int getinfo_helper_accounting(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
-void accounting_set_bandwidth_usage_from_state(or_state_t *state);
#endif
diff --git a/src/or/main.c b/src/or/main.c
index 2d75a5808..f33dc2f6b 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -791,12 +791,13 @@ run_connection_housekeeping(int i, time_t now)
"Tor gave up on the connection");
connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1;
- } else if (past_keepalive && !connection_state_is_open(conn)) {
- /* We never managed to actually get this connection open and happy. */
- log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).",
- conn->s,conn->address, conn->port);
- connection_mark_for_close(conn);
- conn->hold_open_until_flushed = 1;
+ } else if (!connection_state_is_open(conn)) {
+ if (past_keepalive) {
+ /* We never managed to actually get this connection open and happy. */
+ log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).",
+ conn->s,conn->address, conn->port);
+ connection_mark_for_close(conn);
+ }
} else if (we_are_hibernating() && !or_conn->n_circuits &&
!buf_datalen(conn->outbuf)) {
/* We're hibernating, there's no circuits, and nothing to flush.*/
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index f56ccd9ee..e8f3e7c59 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -53,7 +53,7 @@ HT_PROTOTYPE(microdesc_map, microdesc_t, node,
_microdesc_hash, _microdesc_eq);
HT_GENERATE(microdesc_map, microdesc_t, node,
_microdesc_hash, _microdesc_eq, 0.6,
- _tor_malloc, _tor_realloc, _tor_free);
+ malloc, realloc, free);
/** Write the body of <b>md</b> into <b>f</b>, with appropriate annotations.
* On success, return the total number of bytes written, and set
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 54b77992c..e985679c4 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -14,10 +14,12 @@
#include "circuitbuild.h"
#include "config.h"
#include "connection.h"
+#include "connection_or.h"
#include "control.h"
#include "directory.h"
#include "dirserv.h"
#include "dirvote.h"
+#include "main.h"
#include "networkstatus.h"
#include "relay.h"
#include "router.h"
@@ -1166,14 +1168,11 @@ update_v2_networkstatus_cache_downloads(time_t now)
static void
update_consensus_networkstatus_downloads(time_t now)
{
- or_options_t *options = get_options();
int i;
if (!networkstatus_get_live_consensus(now))
time_to_download_next_consensus = now; /* No live consensus? Get one now!*/
if (time_to_download_next_consensus > now)
return; /* Wait until the current consensus is older. */
- if (authdir_mode_v3(options))
- return; /* Authorities never fetch a consensus */
/* XXXXNM Microdescs: may need to download more types. */
if (!download_status_is_ready(&consensus_dl_status[FLAV_NS], now,
CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES))
@@ -1228,14 +1227,26 @@ update_consensus_networkstatus_fetch_time(time_t now)
if (c) {
long dl_interval;
long interval = c->fresh_until - c->valid_after;
+ long min_sec_before_caching = CONSENSUS_MIN_SECONDS_BEFORE_CACHING;
time_t start;
+
+ if (min_sec_before_caching > interval/16) {
+ /* Usually we allow 2-minutes slop factor in case clocks get
+ desynchronized a little. If we're on a private network with
+ a crazy-fast voting interval, though, 2 minutes may be too
+ much. */
+ min_sec_before_caching = interval/16;
+ }
+
if (directory_fetches_dir_info_early(options)) {
/* We want to cache the next one at some point after this one
* is no longer fresh... */
- start = c->fresh_until + CONSENSUS_MIN_SECONDS_BEFORE_CACHING;
+ start = c->fresh_until + min_sec_before_caching;
/* Some clients may need the consensus sooner than others. */
- if (options->FetchDirInfoExtraEarly) {
+ if (options->FetchDirInfoExtraEarly || authdir_mode_v3(options)) {
dl_interval = 60;
+ if (min_sec_before_caching + dl_interval > interval)
+ dl_interval = interval/2;
} else {
/* But only in the first half-interval after that. */
dl_interval = interval/2;
@@ -1251,10 +1262,9 @@ update_consensus_networkstatus_fetch_time(time_t now)
* to choose the rest of the interval *after* them. */
if (directory_fetches_dir_info_later(options)) {
/* Give all the *clients* enough time to download the consensus. */
- start = start + dl_interval + CONSENSUS_MIN_SECONDS_BEFORE_CACHING;
+ start = start + dl_interval + min_sec_before_caching;
/* But try to get it before ours actually expires. */
- dl_interval = (c->valid_until - start) -
- CONSENSUS_MIN_SECONDS_BEFORE_CACHING;
+ dl_interval = (c->valid_until - start) - min_sec_before_caching;
}
}
if (dl_interval < 1)
@@ -1506,6 +1516,7 @@ networkstatus_set_current_consensus(const char *consensus,
networkstatus_t *c=NULL;
int r, result = -1;
time_t now = time(NULL);
+ or_options_t *options = get_options();
char *unverified_fname = NULL, *consensus_fname = NULL;
int flav = networkstatus_parse_flavor_name(flavor);
const unsigned from_cache = flags & NSSET_FROM_CACHE;
@@ -1543,7 +1554,7 @@ networkstatus_set_current_consensus(const char *consensus,
}
if (flav != USABLE_CONSENSUS_FLAVOR &&
- !directory_caches_dir_info(get_options())) {
+ !directory_caches_dir_info(options)) {
/* This consensus is totally boring to us: we won't use it, and we won't
* serve it. Drop it. */
goto done;
@@ -1678,7 +1689,7 @@ networkstatus_set_current_consensus(const char *consensus,
download_status_failed(&consensus_dl_status[flav], 0);
}
- if (directory_caches_dir_info(get_options())) {
+ if (directory_caches_dir_info(options)) {
dirserv_set_cached_consensus_networkstatus(consensus,
flavor,
&c->digests,
@@ -1691,9 +1702,13 @@ networkstatus_set_current_consensus(const char *consensus,
/* XXXXNM Microdescs: needs a non-ns variant. */
update_consensus_networkstatus_fetch_time(now);
- dirvote_recalculate_timing(get_options(), now);
+ dirvote_recalculate_timing(options, now);
routerstatus_list_update_named_server_map();
- cell_ewma_set_scale_factor(get_options(), current_consensus);
+ cell_ewma_set_scale_factor(options, current_consensus);
+
+ /* XXX022 where is the right place to put this call? */
+ connection_or_update_token_buckets(get_connection_array(), options);
+
circuit_build_times_new_consensus_params(&circ_times, current_consensus);
}
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index 4059dead5..32b71a9ce 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -73,7 +73,6 @@ int networkstatus_set_current_consensus(const char *consensus,
unsigned flags);
void networkstatus_note_certs_arrived(void);
void routers_update_all_from_networkstatus(time_t now, int dir_version);
-void routerstatus_list_update_from_consensus_networkstatus(time_t now);
void routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
int reset_failures);
void signed_descs_update_status_from_consensus_networkstatus(
diff --git a/src/or/ntmain.c b/src/or/ntmain.c
index 9bcb7047e..0b611f0bf 100644
--- a/src/or/ntmain.c
+++ b/src/or/ntmain.c
@@ -7,6 +7,7 @@
#include "or.h"
#include "config.h"
#include "main.h"
+#include "ntmain.h"
#ifdef HAVE_EVENT2_EVENT_H
#include <event2/event.h>
@@ -14,12 +15,12 @@
#include <event.h>
#endif
-#include <tchar.h>
-#define GENSRV_SERVICENAME TEXT("tor")
-#define GENSRV_DISPLAYNAME TEXT("Tor Win32 Service")
+#include <windows.h>
+#define GENSRV_SERVICENAME "tor"
+#define GENSRV_DISPLAYNAME "Tor Win32 Service"
#define GENSRV_DESCRIPTION \
- TEXT("Provides an anonymous Internet communication system")
-#define GENSRV_USERACCT TEXT("NT AUTHORITY\\LocalService")
+ "Provides an anonymous Internet communication system"
+#define GENSRV_USERACCT "NT AUTHORITY\\LocalService"
// Cheating: using the pre-defined error codes, tricks Windows into displaying
// a semi-related human-readable error message if startup fails as
@@ -35,7 +36,6 @@ static SERVICE_STATUS_HANDLE hStatus;
* to the NT service functions. */
static char **backup_argv;
static int backup_argc;
-static char* nt_strerror(uint32_t errnum);
static void nt_service_control(DWORD request);
static void nt_service_body(int argc, char **argv);
@@ -69,30 +69,30 @@ struct service_fns {
SC_HANDLE (WINAPI *CreateServiceA_fn)(
SC_HANDLE hSCManager,
- LPCTSTR lpServiceName,
- LPCTSTR lpDisplayName,
+ LPCSTR lpServiceName,
+ LPCSTR lpDisplayName,
DWORD dwDesiredAccess,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
- LPCTSTR lpBinaryPathName,
- LPCTSTR lpLoadOrderGroup,
+ LPCSTR lpBinaryPathName,
+ LPCSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
- LPCTSTR lpDependencies,
- LPCTSTR lpServiceStartName,
- LPCTSTR lpPassword);
+ LPCSTR lpDependencies,
+ LPCSTR lpServiceStartName,
+ LPCSTR lpPassword);
BOOL (WINAPI *DeleteService_fn)(
SC_HANDLE hService);
SC_HANDLE (WINAPI *OpenSCManagerA_fn)(
- LPCTSTR lpMachineName,
- LPCTSTR lpDatabaseName,
+ LPCSTR lpMachineName,
+ LPCSTR lpDatabaseName,
DWORD dwDesiredAccess);
SC_HANDLE (WINAPI *OpenServiceA_fn)(
SC_HANDLE hSCManager,
- LPCTSTR lpServiceName,
+ LPCSTR lpServiceName,
DWORD dwDesiredAccess);
BOOL (WINAPI *QueryServiceStatus_fn)(
@@ -100,23 +100,23 @@ struct service_fns {
LPSERVICE_STATUS lpServiceStatus);
SERVICE_STATUS_HANDLE (WINAPI *RegisterServiceCtrlHandlerA_fn)(
- LPCTSTR lpServiceName,
+ LPCSTR lpServiceName,
LPHANDLER_FUNCTION lpHandlerProc);
BOOL (WINAPI *SetServiceStatus_fn)(SERVICE_STATUS_HANDLE,
LPSERVICE_STATUS);
BOOL (WINAPI *StartServiceCtrlDispatcherA_fn)(
- const SERVICE_TABLE_ENTRY* lpServiceTable);
+ const SERVICE_TABLE_ENTRYA* lpServiceTable);
BOOL (WINAPI *StartServiceA_fn)(
SC_HANDLE hService,
DWORD dwNumServiceArgs,
- LPCTSTR* lpServiceArgVectors);
+ LPCSTR* lpServiceArgVectors);
BOOL (WINAPI *LookupAccountNameA_fn)(
- LPCTSTR lpSystemName,
- LPCTSTR lpAccountName,
+ LPCSTR lpSystemName,
+ LPCSTR lpAccountName,
PSID Sid,
LPDWORD cbSid,
LPTSTR ReferencedDomainName,
@@ -139,7 +139,7 @@ nt_service_loadlibrary(void)
return;
/* XXXX Possibly, we should hardcode the location of this DLL. */
- if (!(library = LoadLibrary("advapi32.dll"))) {
+ if (!(library = LoadLibrary(TEXT("advapi32.dll")))) {
log_err(LD_GENERAL, "Couldn't open advapi32.dll. Are you trying to use "
"NT services on Windows 98? That doesn't work.");
goto err;
@@ -283,20 +283,20 @@ nt_service_body(int argc, char **argv)
static void
nt_service_main(void)
{
- SERVICE_TABLE_ENTRY table[2];
+ SERVICE_TABLE_ENTRYA table[2];
DWORD result = 0;
char *errmsg;
nt_service_loadlibrary();
table[0].lpServiceName = (char*)GENSRV_SERVICENAME;
- table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)nt_service_body;
+ table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTIONA)nt_service_body;
table[1].lpServiceName = NULL;
table[1].lpServiceProc = NULL;
if (!service_fns.StartServiceCtrlDispatcherA_fn(table)) {
result = GetLastError();
- errmsg = nt_strerror(result);
+ errmsg = format_win32_error(result);
printf("Service error %d : %s\n", (int) result, errmsg);
- LocalFree(errmsg);
+ tor_free(errmsg);
if (result == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
if (tor_init(backup_argc, backup_argv) < 0)
return;
@@ -331,9 +331,9 @@ nt_service_open_scm(void)
nt_service_loadlibrary();
if ((hSCManager = service_fns.OpenSCManagerA_fn(
NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == NULL) {
- errmsg = nt_strerror(GetLastError());
+ errmsg = format_win32_error(GetLastError());
printf("OpenSCManager() failed : %s\n", errmsg);
- LocalFree(errmsg);
+ tor_free(errmsg);
}
return hSCManager;
}
@@ -348,9 +348,9 @@ nt_service_open(SC_HANDLE hSCManager)
nt_service_loadlibrary();
if ((hService = service_fns.OpenServiceA_fn(hSCManager, GENSRV_SERVICENAME,
SERVICE_ALL_ACCESS)) == NULL) {
- errmsg = nt_strerror(GetLastError());
+ errmsg = format_win32_error(GetLastError());
printf("OpenService() failed : %s\n", errmsg);
- LocalFree(errmsg);
+ tor_free(errmsg);
}
return hService;
}
@@ -382,14 +382,14 @@ nt_service_start(SC_HANDLE hService)
printf("Service started successfully\n");
return 0;
} else {
- errmsg = nt_strerror(service_status.dwWin32ExitCode);
+ errmsg = format_win32_error(service_status.dwWin32ExitCode);
printf("Service failed to start : %s\n", errmsg);
- LocalFree(errmsg);
+ tor_free(errmsg);
}
} else {
- errmsg = nt_strerror(GetLastError());
+ errmsg = format_win32_error(GetLastError());
printf("StartService() failed : %s\n", errmsg);
- LocalFree(errmsg);
+ tor_free(errmsg);
}
return -1;
}
@@ -426,14 +426,14 @@ nt_service_stop(SC_HANDLE hService)
} else if (wait_time == MAX_SERVICE_WAIT_TIME) {
printf("Service did not stop within %d seconds.\n", wait_time);
} else {
- errmsg = nt_strerror(GetLastError());
+ errmsg = format_win32_error(GetLastError());
printf("QueryServiceStatus() failed : %s\n",errmsg);
- LocalFree(errmsg);
+ tor_free(errmsg);
}
} else {
- errmsg = nt_strerror(GetLastError());
+ errmsg = format_win32_error(GetLastError());
printf("ControlService() failed : %s\n", errmsg);
- LocalFree(errmsg);
+ tor_free(errmsg);
}
return -1;
}
@@ -447,6 +447,7 @@ static char *
nt_service_command_line(int *using_default_torrc)
{
TCHAR tor_exe[MAX_PATH+1];
+ char tor_exe_ascii[MAX_PATH+1];
char *command, *options=NULL;
smartlist_t *sl;
int i, cmdlen;
@@ -472,18 +473,25 @@ nt_service_command_line(int *using_default_torrc)
options = smartlist_join_strings(sl,"\" \"",0,NULL);
smartlist_free(sl);
+#ifdef UNICODE
+ wcstombs(tor_exe_ascii, tor_exe, sizeof(tor_exe_ascii));
+#else
+ strlcpy(tor_exe_ascii, tor_exe, sizeof(tor_exe_ascii));
+#endif
+
/* Allocate a string for the NT service command line */
- cmdlen = strlen(tor_exe) + (options?strlen(options):0) + 32;
+ cmdlen = strlen(tor_exe_ascii) + (options?strlen(options):0) + 32;
command = tor_malloc(cmdlen);
/* Format the service command */
if (options) {
if (tor_snprintf(command, cmdlen, "\"%s\" --nt-service \"%s\"",
- tor_exe, options)<0) {
+ tor_exe_ascii, options)<0) {
tor_free(command); /* sets command to NULL. */
}
} else { /* ! options */
- if (tor_snprintf(command, cmdlen, "\"%s\" --nt-service", tor_exe)<0) {
+ if (tor_snprintf(command, cmdlen, "\"%s\" --nt-service",
+ tor_exe_ascii)<0) {
tor_free(command); /* sets command to NULL. */
}
}
@@ -508,7 +516,7 @@ nt_service_install(int argc, char **argv)
SC_HANDLE hSCManager = NULL;
SC_HANDLE hService = NULL;
- SERVICE_DESCRIPTION sdBuff;
+ SERVICE_DESCRIPTIONA sdBuff;
char *command;
char *errmsg;
const char *user_acct = GENSRV_USERACCT;
@@ -598,10 +606,10 @@ nt_service_install(int argc, char **argv)
SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,
command, NULL, NULL, NULL,
user_acct, password)) == NULL) {
- errmsg = nt_strerror(GetLastError());
+ errmsg = format_win32_error(GetLastError());
printf("CreateService() failed : %s\n", errmsg);
service_fns.CloseServiceHandle_fn(hSCManager);
- LocalFree(errmsg);
+ tor_free(errmsg);
tor_free(command);
return -1;
}
@@ -642,9 +650,9 @@ nt_service_remove(void)
nt_service_stop(hService);
if (service_fns.DeleteService_fn(hService) == FALSE) {
- errmsg = nt_strerror(GetLastError());
+ errmsg = format_win32_error(GetLastError());
printf("DeleteService() failed : %s\n", errmsg);
- LocalFree(errmsg);
+ tor_free(errmsg);
service_fns.CloseServiceHandle_fn(hService);
service_fns.CloseServiceHandle_fn(hSCManager);
return -1;
@@ -701,20 +709,6 @@ nt_service_cmd_stop(void)
return stop;
}
-/** Given a Win32 error code, this attempts to make Windows
- * return a human-readable error message. The char* returned
- * is allocated by Windows, but should be freed with LocalFree()
- * when finished with it. */
-static char*
-nt_strerror(uint32_t errnum)
-{
- char *msgbuf;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPSTR)&msgbuf, 0, NULL);
- return msgbuf;
-}
-
int
nt_service_parse_options(int argc, char **argv, int *should_exit)
{
diff --git a/src/or/onion.c b/src/or/onion.c
index ebc358364..fa001656e 100644
--- a/src/or/onion.c
+++ b/src/or/onion.c
@@ -63,15 +63,16 @@ onion_pending_add(or_circuit_t *circ, char *onionskin)
if (ol_length >= get_options()->MaxOnionsPending) {
#define WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL (60)
- static time_t last_warned = 0;
- time_t now = time(NULL);
- if (last_warned + WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL < now) {
+ static ratelim_t last_warned =
+ RATELIM_INIT(WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL);
+ char *m;
+ if ((m = rate_limit_log(&last_warned, approx_time()))) {
log_warn(LD_GENERAL,
"Your computer is too slow to handle this many circuit "
"creation requests! Please consider using the "
"MaxAdvertisedBandwidth config option or choosing a more "
- "restricted exit policy.");
- last_warned = now;
+ "restricted exit policy.%s",m);
+ tor_free(m);
}
tor_free(tmp);
return -1;
diff --git a/src/or/or.h b/src/or/or.h
index e1f4541a7..48641c811 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -59,6 +59,9 @@
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
@@ -551,7 +554,7 @@ typedef enum {
#define END_STREAM_REASON_DESTROY 5
#define END_STREAM_REASON_DONE 6
#define END_STREAM_REASON_TIMEOUT 7
-/* 8 is unallocated for historical reasons. */
+#define END_STREAM_REASON_NOROUTE 8
#define END_STREAM_REASON_HIBERNATING 9
#define END_STREAM_REASON_INTERNAL 10
#define END_STREAM_REASON_RESOURCELIMIT 11
@@ -2842,6 +2845,12 @@ typedef struct {
time_t BWHistoryWriteEnds;
int BWHistoryWriteInterval;
smartlist_t *BWHistoryWriteValues;
+ time_t BWHistoryDirReadEnds;
+ int BWHistoryDirReadInterval;
+ smartlist_t *BWHistoryDirReadValues;
+ time_t BWHistoryDirWriteEnds;
+ int BWHistoryDirWriteInterval;
+ smartlist_t *BWHistoryDirWriteValues;
/** Build time histogram */
config_line_t * BuildtimeHistogram;
diff --git a/src/or/policies.c b/src/or/policies.c
index db3c6d886..4fd090415 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -381,7 +381,7 @@ validate_addr_policies(or_options_t *options, char **msg)
ADDR_POLICY_ACCEPT))
REJECT("Error in ReachableDirAddresses entry.");
-err:
+ err:
addr_policy_list_free(addr_policy);
return *msg ? -1 : 0;
#undef REJECT
@@ -1272,7 +1272,7 @@ policy_summarize(smartlist_t *policy)
result = tor_malloc(final_size);
tor_snprintf(result, final_size, "%s %s", prefix, shorter_str);
-cleanup:
+ cleanup:
/* cleanup */
SMARTLIST_FOREACH(summary, policy_summary_item_t *, s, tor_free(s));
smartlist_free(summary);
diff --git a/src/or/reasons.c b/src/or/reasons.c
index 2dd5fe946..ade9a3abf 100644
--- a/src/or/reasons.c
+++ b/src/or/reasons.c
@@ -28,6 +28,7 @@ stream_end_reason_to_control_string(int reason)
case END_STREAM_REASON_DESTROY: return "DESTROY";
case END_STREAM_REASON_DONE: return "DONE";
case END_STREAM_REASON_TIMEOUT: return "TIMEOUT";
+ case END_STREAM_REASON_NOROUTE: return "NOROUTE";
case END_STREAM_REASON_HIBERNATING: return "HIBERNATING";
case END_STREAM_REASON_INTERNAL: return "INTERNAL";
case END_STREAM_REASON_RESOURCELIMIT: return "RESOURCELIMIT";
@@ -62,6 +63,7 @@ stream_end_reason_to_string(int reason)
case END_STREAM_REASON_DESTROY: return "destroyed";
case END_STREAM_REASON_DONE: return "closed normally";
case END_STREAM_REASON_TIMEOUT: return "gave up (timeout)";
+ case END_STREAM_REASON_NOROUTE: return "no route to host";
case END_STREAM_REASON_HIBERNATING: return "server is hibernating";
case END_STREAM_REASON_INTERNAL: return "internal error at server";
case END_STREAM_REASON_RESOURCELIMIT: return "server out of resources";
@@ -104,6 +106,8 @@ stream_end_reason_to_socks5_response(int reason)
return SOCKS5_SUCCEEDED;
case END_STREAM_REASON_TIMEOUT:
return SOCKS5_TTL_EXPIRED;
+ case END_STREAM_REASON_NOROUTE:
+ return SOCKS5_HOST_UNREACHABLE;
case END_STREAM_REASON_RESOURCELIMIT:
return SOCKS5_GENERAL_ERROR;
case END_STREAM_REASON_HIBERNATING:
@@ -164,6 +168,14 @@ errno_to_stream_end_reason(int e)
S_CASE(ENOTCONN):
S_CASE(ENETUNREACH):
return END_STREAM_REASON_INTERNAL;
+ S_CASE(EHOSTUNREACH):
+ /* XXXX022
+ * The correct behavior is END_STREAM_REASON_NOROUTE, but older
+ * clients don't recognize it. So we're going to continue sending
+ * "MISC" until 0.2.1.27 or later is "well established".
+ */
+ /* return END_STREAM_REASON_NOROUTE; */
+ return END_STREAM_REASON_MISC;
S_CASE(ECONNREFUSED):
return END_STREAM_REASON_CONNECTREFUSED;
S_CASE(ECONNRESET):
diff --git a/src/or/relay.c b/src/or/relay.c
index 22ecdaafa..0d51ea406 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -52,6 +52,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *conn,
crypt_path_t *layer_hint);
static int
circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint);
+static int circuit_queue_streams_are_blocked(circuit_t *circ);
/** Cache the current hi-res time; the cache gets reset when libevent
* calls us. */
@@ -268,7 +269,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
* we might kill the circ before we relay
* the cells. */
- append_cell_to_circuit_queue(circ, or_conn, cell, cell_direction);
+ append_cell_to_circuit_queue(circ, or_conn, cell, cell_direction, 0);
return 0;
}
@@ -365,7 +366,7 @@ relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction,
static int
circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
cell_direction_t cell_direction,
- crypt_path_t *layer_hint)
+ crypt_path_t *layer_hint, streamid_t on_stream)
{
or_connection_t *conn; /* where to send the cell */
@@ -409,7 +410,7 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
}
++stats_n_relay_cells_relayed;
- append_cell_to_circuit_queue(circ, conn, cell, cell_direction);
+ append_cell_to_circuit_queue(circ, conn, cell, cell_direction, on_stream);
return 0;
}
@@ -536,7 +537,7 @@ relay_command_to_string(uint8_t command)
* return 0.
*/
int
-relay_send_command_from_edge(uint16_t stream_id, circuit_t *circ,
+relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ,
uint8_t relay_command, const char *payload,
size_t payload_len, crypt_path_t *cpath_layer)
{
@@ -624,8 +625,8 @@ relay_send_command_from_edge(uint16_t stream_id, circuit_t *circ,
}
}
- if (circuit_package_relay_cell(&cell, circ, cell_direction, cpath_layer)
- < 0) {
+ if (circuit_package_relay_cell(&cell, circ, cell_direction, cpath_layer,
+ stream_id) < 0) {
log_warn(LD_BUG,"circuit_package_relay_cell failed. Closing.");
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
return -1;
@@ -692,7 +693,8 @@ edge_reason_is_retriable(int reason)
reason == END_STREAM_REASON_RESOURCELIMIT ||
reason == END_STREAM_REASON_EXITPOLICY ||
reason == END_STREAM_REASON_RESOLVEFAILED ||
- reason == END_STREAM_REASON_MISC;
+ reason == END_STREAM_REASON_MISC ||
+ reason == END_STREAM_REASON_NOROUTE;
}
/** Called when we receive an END cell on a stream that isn't open yet,
@@ -787,6 +789,7 @@ connection_ap_process_end_not_open(
case END_STREAM_REASON_RESOLVEFAILED:
case END_STREAM_REASON_TIMEOUT:
case END_STREAM_REASON_MISC:
+ case END_STREAM_REASON_NOROUTE:
if (client_dns_incr_failures(conn->socks_request->address)
< MAX_RESOLVE_FAILURES) {
/* We haven't retried too many times; reattach the connection. */
@@ -1234,6 +1237,10 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
conn->package_window += STREAMWINDOW_INCREMENT;
log_debug(domain,"stream-level sendme, packagewindow now %d.",
conn->package_window);
+ if (circuit_queue_streams_are_blocked(circ)) {
+ /* Still waiting for queue to flush; don't touch conn */
+ return 0;
+ }
connection_start_reading(TO_CONN(conn));
/* handle whatever might still be on the inbuf */
if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
@@ -1326,7 +1333,7 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial)
return 0;
}
-repeat_connection_edge_package_raw_inbuf:
+ repeat_connection_edge_package_raw_inbuf:
circ = circuit_get_by_edge_conn(conn);
if (!circ) {
@@ -1434,7 +1441,10 @@ connection_edge_consider_sending_sendme(edge_connection_t *conn)
static void
circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
{
-
+ if (circuit_queue_streams_are_blocked(circ)) {
+ log_debug(layer_hint?LD_APP:LD_EXIT,"Too big queue, no resuming");
+ return;
+ }
log_debug(layer_hint?LD_APP:LD_EXIT,"resuming");
if (CIRCUIT_IS_ORIGIN(circ))
@@ -2090,12 +2100,19 @@ connection_or_unlink_all_active_circs(or_connection_t *orconn)
/** Block (if <b>block</b> is true) or unblock (if <b>block</b> is false)
* every edge connection that is using <b>circ</b> to write to <b>orconn</b>,
- * and start or stop reading as appropriate. */
-static void
+ * and start or stop reading as appropriate.
+ *
+ * If <b>stream_id</b> is nonzero, block only the edge connection whose
+ * stream_id matches it.
+ *
+ * Returns the number of streams whose status we changed.
+ */
+static int
set_streams_blocked_on_circ(circuit_t *circ, or_connection_t *orconn,
- int block)
+ int block, streamid_t stream_id)
{
edge_connection_t *edge = NULL;
+ int n = 0;
if (circ->n_conn == orconn) {
circ->streams_blocked_on_n_conn = block;
if (CIRCUIT_IS_ORIGIN(circ))
@@ -2108,7 +2125,13 @@ set_streams_blocked_on_circ(circuit_t *circ, or_connection_t *orconn,
for (; edge; edge = edge->next_stream) {
connection_t *conn = TO_CONN(edge);
- edge->edge_blocked_on_circ = block;
+ if (stream_id && edge->stream_id != stream_id)
+ continue;
+
+ if (edge->edge_blocked_on_circ != block) {
+ ++n;
+ edge->edge_blocked_on_circ = block;
+ }
if (!conn->read_event) {
/* This connection is a placeholder for something; probably a DNS
@@ -2125,6 +2148,8 @@ set_streams_blocked_on_circ(circuit_t *circ, or_connection_t *orconn,
connection_start_reading(conn);
}
}
+
+ return n;
}
/** Pull as many cells as possible (but no more than <b>max</b>) from the
@@ -2250,7 +2275,7 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max,
/* Is the cell queue low enough to unblock all the streams that are waiting
* to write to this circuit? */
if (streams_blocked && queue->n <= CELL_QUEUE_LOWWATER_SIZE)
- set_streams_blocked_on_circ(circ, conn, 0); /* unblock streams */
+ set_streams_blocked_on_circ(circ, conn, 0, 0); /* unblock streams */
/* Did we just run out of cells on this circuit's queue? */
if (queue->n == 0) {
@@ -2267,7 +2292,8 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max,
* transmitting in <b>direction</b>. */
void
append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn,
- cell_t *cell, cell_direction_t direction)
+ cell_t *cell, cell_direction_t direction,
+ streamid_t fromstream)
{
cell_queue_t *queue;
int streams_blocked;
@@ -2289,7 +2315,12 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn,
/* If we have too many cells on the circuit, we should stop reading from
* the edge streams for a while. */
if (!streams_blocked && queue->n >= CELL_QUEUE_HIGHWATER_SIZE)
- set_streams_blocked_on_circ(circ, orconn, 1); /* block streams */
+ set_streams_blocked_on_circ(circ, orconn, 1, 0); /* block streams */
+
+ if (streams_blocked && fromstream) {
+ /* This edge connection is apparently not blocked; block it. */
+ set_streams_blocked_on_circ(circ, orconn, 1, fromstream);
+ }
if (queue->n == 1) {
/* This was the first cell added to the queue. We need to make this
@@ -2403,3 +2434,15 @@ assert_active_circuits_ok(or_connection_t *orconn)
tor_assert(n == smartlist_len(orconn->active_circuit_pqueue));
}
+/** Return 1 if we shouldn't restart reading on this circuit, even if
+ * we get a SENDME. Else return 0.
+*/
+static int
+circuit_queue_streams_are_blocked(circuit_t *circ)
+{
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ return circ->streams_blocked_on_n_conn;
+ } else {
+ return circ->streams_blocked_on_p_conn;
+ }
+}
diff --git a/src/or/relay.h b/src/or/relay.h
index 73855a52b..0ef17b6ff 100644
--- a/src/or/relay.h
+++ b/src/or/relay.h
@@ -45,7 +45,8 @@ void cell_queue_append(cell_queue_t *queue, packed_cell_t *cell);
void cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell);
void append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn,
- cell_t *cell, cell_direction_t direction);
+ cell_t *cell, cell_direction_t direction,
+ streamid_t fromstream);
void connection_or_unlink_all_active_circs(or_connection_t *conn);
int connection_or_flush_from_first_active_circuit(or_connection_t *conn,
int max, time_t now);
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 0377f121c..68abb886a 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -209,7 +209,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
return 0;
-err:
+ err:
circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL);
circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_REASON_INTERNAL);
return -1;
diff --git a/src/or/rendservice.h b/src/or/rendservice.h
index f979a3941..1767714c6 100644
--- a/src/or/rendservice.h
+++ b/src/or/rendservice.h
@@ -15,7 +15,6 @@
int num_rend_services(void);
int rend_config_services(or_options_t *options, int validate_only);
int rend_service_load_keys(void);
-void rend_services_init(void);
void rend_services_introduce(void);
void rend_consider_services_upload(time_t now);
void rend_hsdir_routers_changed(void);
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 72addde5b..056fc5cc1 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -1284,13 +1284,21 @@ bw_array_new(void)
static bw_array_t *read_array = NULL;
/** Recent history of bandwidth observations for write operations. */
static bw_array_t *write_array = NULL;
-
-/** Set up read_array and write_array. */
+/** Recent history of bandwidth observations for read operations for the
+ directory protocol. */
+static bw_array_t *dir_read_array = NULL;
+/** Recent history of bandwidth observations for write operations for the
+ directory protocol. */
+static bw_array_t *dir_write_array = NULL;
+
+/** Set up [dir-]read_array and [dir-]write_array. */
static void
bw_arrays_init(void)
{
read_array = bw_array_new();
write_array = bw_array_new();
+ dir_read_array = bw_array_new();
+ dir_write_array = bw_array_new();
}
/** We read <b>num_bytes</b> more bytes in second <b>when</b>.
@@ -1324,6 +1332,24 @@ rep_hist_note_bytes_read(size_t num_bytes, time_t when)
add_obs(read_array, when, num_bytes);
}
+/** We wrote <b>num_bytes</b> more directory bytes in second <b>when</b>.
+ * (like rep_hist_note_bytes_written() above)
+ */
+void
+rep_hist_note_dir_bytes_written(size_t num_bytes, time_t when)
+{
+ add_obs(dir_write_array, when, num_bytes);
+}
+
+/** We read <b>num_bytes</b> more directory bytes in second <b>when</b>.
+ * (like rep_hist_note_bytes_written() above)
+ */
+void
+rep_hist_note_dir_bytes_read(size_t num_bytes, time_t when)
+{
+ add_obs(dir_read_array, when, num_bytes);
+}
+
/** Helper: Return the largest value in b->maxima. (This is equal to the
* most bandwidth used in any NUM_SECS_ROLLING_MEASURE period for the last
* NUM_SECS_BW_SUM_IS_VALID seconds.)
@@ -1359,9 +1385,9 @@ rep_hist_bandwidth_assess(void)
return (int)(U64_TO_DBL(r)/NUM_SECS_ROLLING_MEASURE);
}
-/** Print the bandwidth history of b (either read_array or write_array)
- * into the buffer pointed to by buf. The format is simply comma
- * separated numbers, from oldest to newest.
+/** Print the bandwidth history of b (either [dir-]read_array or
+ * [dir-]write_array) into the buffer pointed to by buf. The format is
+ * simply comma separated numbers, from oldest to newest.
*
* It returns the number of bytes written.
*/
@@ -1419,20 +1445,37 @@ rep_hist_get_bandwidth_lines(int for_extrainfo)
char *buf, *cp;
char t[ISO_TIME_LEN+1];
int r;
- bw_array_t *b;
+ bw_array_t *b = NULL;
+ const char *desc = NULL;
size_t len;
- /* opt (read|write)-history yyyy-mm-dd HH:MM:SS (n s) n,n,n,n,n... */
- len = (60+21*NUM_TOTALS)*2;
+ /* opt [dirreq-](read|write)-history yyyy-mm-dd HH:MM:SS (n s) n,n,n... */
+ len = (67+21*NUM_TOTALS)*4;
buf = tor_malloc_zero(len);
cp = buf;
- for (r=0;r<2;++r) {
- b = r?read_array:write_array;
+ for (r=0;r<4;++r) {
+ switch (r) {
+ case 0:
+ b = write_array;
+ desc = "write-history";
+ break;
+ case 1:
+ b = read_array;
+ desc = "read-history";
+ break;
+ case 2:
+ b = dir_write_array;
+ desc = "dirreq-write-history";
+ break;
+ case 3:
+ b = dir_read_array;
+ desc = "dirreq-read-history";
+ break;
+ }
tor_assert(b);
format_iso_time(t, b->next_period-NUM_SECS_BW_SUM_INTERVAL);
tor_snprintf(cp, len-(cp-buf), "%s%s %s (%d s) ",
- for_extrainfo ? "" : "opt ",
- r ? "read-history" : "write-history", t,
+ for_extrainfo ? "" : "opt ", desc, t,
NUM_SECS_BW_SUM_INTERVAL);
cp += strlen(cp);
cp += rep_hist_fill_bandwidth_history(cp, len-(cp-buf), b);
@@ -1448,20 +1491,41 @@ rep_hist_update_state(or_state_t *state)
{
int len, r;
char *buf, *cp;
- smartlist_t **s_values;
- time_t *s_begins;
- int *s_interval;
- bw_array_t *b;
+ smartlist_t **s_values = NULL;
+ time_t *s_begins = NULL;
+ int *s_interval = NULL;
+ bw_array_t *b = NULL;
len = 20*NUM_TOTALS+1;
buf = tor_malloc_zero(len);
- for (r=0;r<2;++r) {
- b = r?read_array:write_array;
- s_begins = r?&state->BWHistoryReadEnds :&state->BWHistoryWriteEnds;
- s_interval= r?&state->BWHistoryReadInterval:&state->BWHistoryWriteInterval;
- s_values = r?&state->BWHistoryReadValues :&state->BWHistoryWriteValues;
-
+ for (r=0;r<4;++r) {
+ switch (r) {
+ case 0:
+ b = write_array;
+ s_begins = &state->BWHistoryWriteEnds;
+ s_interval = &state->BWHistoryWriteInterval;
+ s_values = &state->BWHistoryWriteValues;
+ break;
+ case 1:
+ b = read_array;
+ s_begins = &state->BWHistoryReadEnds;
+ s_interval = &state->BWHistoryReadInterval;
+ s_values = &state->BWHistoryReadValues;
+ break;
+ case 2:
+ b = dir_write_array;
+ s_begins = &state->BWHistoryDirWriteEnds;
+ s_interval = &state->BWHistoryDirWriteInterval;
+ s_values = &state->BWHistoryDirWriteValues;
+ break;
+ case 3:
+ b = dir_read_array;
+ s_begins = &state->BWHistoryDirReadEnds;
+ s_interval = &state->BWHistoryDirReadInterval;
+ s_values = &state->BWHistoryDirReadValues;
+ break;
+ }
if (*s_values) {
SMARTLIST_FOREACH(*s_values, char *, val, tor_free(val));
smartlist_free(*s_values);
@@ -1501,23 +1565,45 @@ rep_hist_update_state(or_state_t *state)
int
rep_hist_load_state(or_state_t *state, char **err)
{
- time_t s_begins, start;
+ time_t s_begins = 0, start;
time_t now = time(NULL);
uint64_t v;
int r,i,ok;
int all_ok = 1;
- int s_interval;
- smartlist_t *s_values;
- bw_array_t *b;
+ int s_interval = 0;
+ smartlist_t *s_values = NULL;
+ bw_array_t *b = NULL;
/* Assert they already have been malloced */
tor_assert(read_array && write_array);
- for (r=0;r<2;++r) {
- b = r?read_array:write_array;
- s_begins = r?state->BWHistoryReadEnds:state->BWHistoryWriteEnds;
- s_interval = r?state->BWHistoryReadInterval:state->BWHistoryWriteInterval;
- s_values = r?state->BWHistoryReadValues:state->BWHistoryWriteValues;
+ for (r=0;r<4;++r) {
+ switch (r) {
+ case 0:
+ b = write_array;
+ s_begins = state->BWHistoryWriteEnds;
+ s_interval = state->BWHistoryWriteInterval;
+ s_values = state->BWHistoryWriteValues;
+ break;
+ case 1:
+ b = read_array;
+ s_begins = state->BWHistoryReadEnds;
+ s_interval = state->BWHistoryReadInterval;
+ s_values = state->BWHistoryReadValues;
+ break;
+ case 2:
+ b = dir_write_array;
+ s_begins = state->BWHistoryDirWriteEnds;
+ s_interval = state->BWHistoryDirWriteInterval;
+ s_values = state->BWHistoryDirWriteValues;
+ break;
+ case 3:
+ b = dir_read_array;
+ s_begins = state->BWHistoryDirReadEnds;
+ s_interval = state->BWHistoryDirReadInterval;
+ s_values = state->BWHistoryDirReadValues;
+ break;
+ }
if (s_values && s_begins >= now - NUM_SECS_BW_SUM_INTERVAL*NUM_TOTALS) {
start = s_begins - s_interval*(smartlist_len(s_values));
if (start > now)
@@ -1889,6 +1975,16 @@ rep_hist_exit_stats_init(time_t now)
sizeof(uint32_t));
}
+/** Reset counters for exit port statistics. */
+void
+rep_hist_reset_exit_stats(time_t now)
+{
+ start_of_exit_stats_interval = now;
+ memset(exit_bytes_read, 0, EXIT_STATS_NUM_PORTS * sizeof(uint64_t));
+ memset(exit_bytes_written, 0, EXIT_STATS_NUM_PORTS * sizeof(uint64_t));
+ memset(exit_streams, 0, EXIT_STATS_NUM_PORTS * sizeof(uint32_t));
+}
+
/** Stop collecting exit port stats in a way that we can re-start doing
* so in rep_hist_exit_stats_init(). */
void
@@ -1900,164 +1996,173 @@ rep_hist_exit_stats_term(void)
tor_free(exit_streams);
}
-/** Write exit stats to $DATADIR/stats/exit-stats, reset counters, and
- * return when we would next want to write exit stats. */
-time_t
-rep_hist_exit_stats_write(time_t now)
+/** Return a newly allocated string containing the exit port statistics
+ * until <b>now</b>, or NULL if we're not collecting exit stats. */
+char *
+rep_hist_format_exit_stats(time_t now)
{
+ int i;
+ uint64_t total_bytes = 0, threshold_bytes, other_read = 0,
+ other_written = 0;
+ uint32_t other_streams = 0;
+ char *buf;
+ smartlist_t *written_strings, *read_strings, *streams_strings;
+ char *written_string, *read_string, *streams_string;
char t[ISO_TIME_LEN+1];
- int r, i, comma;
- uint64_t *b, total_bytes, threshold_bytes, other_bytes;
- uint32_t other_streams;
-
- char *statsdir = NULL, *filename = NULL;
- open_file_t *open_file = NULL;
- FILE *out = NULL;
+ char *result;
if (!start_of_exit_stats_interval)
- return 0; /* Not initialized. */
- if (start_of_exit_stats_interval + WRITE_STATS_INTERVAL > now)
- goto done; /* Not ready to write. */
-
- statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE) < 0)
- goto done;
- filename = get_datadir_fname2("stats", "exit-stats");
- format_iso_time(t, now);
- log_info(LD_HIST, "Writing exit port statistics to disk for period "
- "ending at %s.", t);
-
- if (!open_file) {
- out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND,
- 0600, &open_file);
- if (!out) {
- log_warn(LD_HIST, "Couldn't open '%s'.", filename);
- goto done;
- }
- }
-
- /* written yyyy-mm-dd HH:MM:SS (n s) */
- if (fprintf(out, "exit-stats-end %s (%d s)\n", t,
- (unsigned) (now - start_of_exit_stats_interval)) < 0)
- goto done;
+ return NULL; /* Not initialized. */
- /* Count the total number of bytes, so that we can attribute all
- * observations below a threshold of 1 / EXIT_STATS_THRESHOLD_RECIPROCAL
+ /* Count total number of bytes, so that we can attribute observations
+ * below or equal to a threshold of 1 / EXIT_STATS_THRESHOLD_RECIPROCAL
* of all bytes to a special port 'other'. */
- total_bytes = 0;
for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) {
total_bytes += exit_bytes_read[i];
total_bytes += exit_bytes_written[i];
}
threshold_bytes = total_bytes / EXIT_STATS_THRESHOLD_RECIPROCAL;
- /* exit-kibibytes-(read|written) port=kibibytes,.. */
- for (r = 0; r < 2; r++) {
- b = r ? exit_bytes_read : exit_bytes_written;
- tor_assert(b);
- if (fprintf(out, "%s ",
- r ? "exit-kibibytes-read"
- : "exit-kibibytes-written") < 0)
- goto done;
-
- comma = 0;
- other_bytes = 0;
- for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) {
- if (b[i] > 0) {
- if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) {
- uint64_t num = round_uint64_to_next_multiple_of(b[i],
- EXIT_STATS_ROUND_UP_BYTES);
- num /= 1024;
- if (fprintf(out, "%s%d="U64_FORMAT,
- comma++ ? "," : "", i,
- U64_PRINTF_ARG(num)) < 0)
- goto done;
- } else
- other_bytes += b[i];
- }
- }
- other_bytes = round_uint64_to_next_multiple_of(other_bytes,
- EXIT_STATS_ROUND_UP_BYTES);
- other_bytes /= 1024;
- if (fprintf(out, "%sother="U64_FORMAT"\n",
- comma ? "," : "", U64_PRINTF_ARG(other_bytes))<0)
- goto done;
- }
- /* exit-streams-opened port=num,.. */
- if (fprintf(out, "exit-streams-opened ") < 0)
- goto done;
- comma = 0;
- other_streams = 0;
+ /* Add observations of all ports above the threshold to smartlists and
+ * join them to single strings. Also count bytes and streams of ports
+ * below or equal to the threshold. */
+ written_strings = smartlist_create();
+ read_strings = smartlist_create();
+ streams_strings = smartlist_create();
for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) {
- if (exit_streams[i] > 0) {
- if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) {
+ if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) {
+ if (exit_bytes_written[i] > 0) {
+ uint64_t num = round_uint64_to_next_multiple_of(
+ exit_bytes_written[i], EXIT_STATS_ROUND_UP_BYTES);
+ num /= 1024;
+ buf = NULL;
+ tor_asprintf(&buf, "%d="U64_FORMAT, i, U64_PRINTF_ARG(num));
+ smartlist_add(written_strings, buf);
+ }
+ if (exit_bytes_read[i] > 0) {
+ uint64_t num = round_uint64_to_next_multiple_of(
+ exit_bytes_read[i], EXIT_STATS_ROUND_UP_BYTES);
+ num /= 1024;
+ buf = NULL;
+ tor_asprintf(&buf, "%d="U64_FORMAT, i, U64_PRINTF_ARG(num));
+ smartlist_add(read_strings, buf);
+ }
+ if (exit_streams[i] > 0) {
uint32_t num = round_uint32_to_next_multiple_of(exit_streams[i],
- EXIT_STATS_ROUND_UP_STREAMS);
- if (fprintf(out, "%s%d=%u",
- comma++ ? "," : "", i, num)<0)
- goto done;
- } else
- other_streams += exit_streams[i];
+ EXIT_STATS_ROUND_UP_STREAMS);
+ buf = NULL;
+ tor_asprintf(&buf, "%d=%u", i, num);
+ smartlist_add(streams_strings, buf);
+ }
+ } else {
+ other_read += exit_bytes_read[i];
+ other_written += exit_bytes_written[i];
+ other_streams += exit_streams[i];
}
}
+ other_written = round_uint64_to_next_multiple_of(other_written,
+ EXIT_STATS_ROUND_UP_BYTES);
+ other_written /= 1024;
+ buf = NULL;
+ tor_asprintf(&buf, "other="U64_FORMAT, U64_PRINTF_ARG(other_written));
+ smartlist_add(written_strings, buf);
+ other_read = round_uint64_to_next_multiple_of(other_read,
+ EXIT_STATS_ROUND_UP_BYTES);
+ other_read /= 1024;
+ buf = NULL;
+ tor_asprintf(&buf, "other="U64_FORMAT, U64_PRINTF_ARG(other_read));
+ smartlist_add(read_strings, buf);
other_streams = round_uint32_to_next_multiple_of(other_streams,
- EXIT_STATS_ROUND_UP_STREAMS);
- if (fprintf(out, "%sother=%u\n",
- comma ? "," : "", other_streams)<0)
+ EXIT_STATS_ROUND_UP_STREAMS);
+ buf = NULL;
+ tor_asprintf(&buf, "other=%u", other_streams);
+ smartlist_add(streams_strings, buf);
+ written_string = smartlist_join_strings(written_strings, ",", 0, NULL);
+ read_string = smartlist_join_strings(read_strings, ",", 0, NULL);
+ streams_string = smartlist_join_strings(streams_strings, ",", 0, NULL);
+ SMARTLIST_FOREACH(written_strings, char *, cp, tor_free(cp));
+ SMARTLIST_FOREACH(read_strings, char *, cp, tor_free(cp));
+ SMARTLIST_FOREACH(streams_strings, char *, cp, tor_free(cp));
+ smartlist_free(written_strings);
+ smartlist_free(read_strings);
+ smartlist_free(streams_strings);
+
+ /* Put everything together. */
+ format_iso_time(t, now);
+ tor_asprintf(&result, "exit-stats-end %s (%d s)\n"
+ "exit-kibibytes-written %s\n"
+ "exit-kibibytes-read %s\n"
+ "exit-streams-opened %s\n",
+ t, (unsigned) (now - start_of_exit_stats_interval),
+ written_string,
+ read_string,
+ streams_string);
+ tor_free(written_string);
+ tor_free(read_string);
+ tor_free(streams_string);
+ return result;
+}
+
+/** If 24 hours have passed since the beginning of the current exit port
+ * stats period, write exit stats to $DATADIR/stats/exit-stats (possibly
+ * overwriting an existing file) and reset counters. Return when we would
+ * next want to write exit stats or 0 if we never want to write. */
+time_t
+rep_hist_exit_stats_write(time_t now)
+{
+ char *statsdir = NULL, *filename = NULL, *str = NULL;
+
+ if (!start_of_exit_stats_interval)
+ return 0; /* Not initialized. */
+ if (start_of_exit_stats_interval + WRITE_STATS_INTERVAL > now)
+ goto done; /* Not ready to write. */
+
+ log_info(LD_HIST, "Writing exit port statistics to disk.");
+
+ /* Generate history string. */
+ str = rep_hist_format_exit_stats(now);
+
+ /* Reset counters. */
+ rep_hist_reset_exit_stats(now);
+
+ /* Try to write to disk. */
+ statsdir = get_datadir_fname("stats");
+ if (check_private_dir(statsdir, CPD_CREATE) < 0) {
+ log_warn(LD_HIST, "Unable to create stats/ directory!");
goto done;
- /* Reset counters */
- memset(exit_bytes_read, 0, EXIT_STATS_NUM_PORTS * sizeof(uint64_t));
- memset(exit_bytes_written, 0, EXIT_STATS_NUM_PORTS * sizeof(uint64_t));
- memset(exit_streams, 0, EXIT_STATS_NUM_PORTS * sizeof(uint32_t));
- start_of_exit_stats_interval = now;
+ }
+ filename = get_datadir_fname2("stats", "exit-stats");
+ if (write_str_to_file(filename, str, 0) < 0)
+ log_warn(LD_HIST, "Unable to write exit port statistics to disk!");
- if (open_file)
- finish_writing_to_file(open_file);
- open_file = NULL;
done:
- if (open_file)
- abort_writing_to_file(open_file);
- tor_free(filename);
+ tor_free(str);
tor_free(statsdir);
+ tor_free(filename);
return start_of_exit_stats_interval + WRITE_STATS_INTERVAL;
}
-/** Note that we wrote <b>num_bytes</b> to an exit connection to
- * <b>port</b>. */
-void
-rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes)
-{
- if (!get_options()->ExitPortStatistics)
- return;
- if (!exit_bytes_written)
- return; /* Not initialized */
- exit_bytes_written[port] += num_bytes;
- log_debug(LD_HIST, "Written %lu bytes to exit connection to port %d.",
- (unsigned long)num_bytes, port);
-}
-
-/** Note that we read <b>num_bytes</b> from an exit connection to
- * <b>port</b>. */
+/** Note that we wrote <b>num_written</b> bytes and read <b>num_read</b>
+ * bytes to/from an exit connection to <b>port</b>. */
void
-rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes)
+rep_hist_note_exit_bytes(uint16_t port, size_t num_written,
+ size_t num_read)
{
- if (!get_options()->ExitPortStatistics)
- return;
- if (!exit_bytes_read)
- return; /* Not initialized */
- exit_bytes_read[port] += num_bytes;
- log_debug(LD_HIST, "Read %lu bytes from exit connection to port %d.",
- (unsigned long)num_bytes, port);
+ if (!start_of_exit_stats_interval)
+ return; /* Not initialized. */
+ exit_bytes_written[port] += num_written;
+ exit_bytes_read[port] += num_read;
+ log_debug(LD_HIST, "Written %lu bytes and read %lu bytes to/from an "
+ "exit connection to port %d.",
+ (unsigned long)num_written, (unsigned long)num_read, port);
}
/** Note that we opened an exit stream to <b>port</b>. */
void
rep_hist_note_exit_stream_opened(uint16_t port)
{
- if (!get_options()->ExitPortStatistics)
- return;
- if (!exit_streams)
- return; /* Not initialized */
+ if (!start_of_exit_stats_interval)
+ return; /* Not initialized. */
exit_streams[port]++;
log_debug(LD_HIST, "Opened exit stream to port %d", port);
}
diff --git a/src/or/rephist.h b/src/or/rephist.h
index fe45a81a3..c3914dcaf 100644
--- a/src/or/rephist.h
+++ b/src/or/rephist.h
@@ -23,12 +23,10 @@ void rep_hist_note_extend_failed(const char *from_name, const char *to_name);
void rep_hist_dump_stats(time_t now, int severity);
void rep_hist_note_bytes_read(size_t num_bytes, time_t when);
void rep_hist_note_bytes_written(size_t num_bytes, time_t when);
-void rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes);
-void rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes);
-void rep_hist_note_exit_stream_opened(uint16_t port);
-void rep_hist_exit_stats_init(time_t now);
-time_t rep_hist_exit_stats_write(time_t now);
-void rep_hist_exit_stats_term(void);
+
+void rep_hist_note_dir_bytes_read(size_t num_bytes, time_t when);
+void rep_hist_note_dir_bytes_written(size_t num_bytes, time_t when);
+
int rep_hist_bandwidth_assess(void);
char *rep_hist_get_bandwidth_lines(int for_extrainfo);
void rep_hist_update_state(or_state_t *state);
@@ -63,13 +61,14 @@ void dump_pk_ops(int severity);
void rep_hist_free_all(void);
-/* for hidden service usage statistics */
-void hs_usage_note_publish_total(const char *service_id, time_t now);
-void hs_usage_note_publish_novel(const char *service_id, time_t now);
-void hs_usage_note_fetch_total(const char *service_id, time_t now);
-void hs_usage_note_fetch_successful(const char *service_id, time_t now);
-void hs_usage_write_statistics_to_file(time_t now);
-void hs_usage_free_all(void);
+void rep_hist_exit_stats_init(time_t now);
+void rep_hist_reset_exit_stats(time_t now);
+void rep_hist_exit_stats_term(void);
+char *rep_hist_format_exit_stats(time_t now);
+time_t rep_hist_exit_stats_write(time_t now);
+void rep_hist_note_exit_bytes(uint16_t port, size_t num_written,
+ size_t num_read);
+void rep_hist_note_exit_stream_opened(uint16_t port);
void rep_hist_buffer_stats_init(time_t now);
void rep_hist_buffer_stats_add_circ(circuit_t *circ,
diff --git a/src/or/routerparse.h b/src/or/routerparse.h
index 2313f68e0..e5ebf0761 100644
--- a/src/or/routerparse.h
+++ b/src/or/routerparse.h
@@ -30,11 +30,6 @@ int router_parse_list_from_string(const char **s, const char *eos,
int is_extrainfo,
int allow_annotations,
const char *prepend_annotations);
-int router_parse_routerlist_from_directory(const char *s,
- routerlist_t **dest,
- crypto_pk_env_t *pkey,
- int check_version,
- int write_to_cache);
int router_parse_runningrouters(const char *str);
int router_parse_directory(const char *str);