[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r15008: infrastructure for the 'bootstrap status event' feature, so (tor/trunk/src/or)
Author: arma
Date: 2008-06-07 01:27:34 -0400 (Sat, 07 Jun 2008)
New Revision: 15008
Modified:
tor/trunk/src/or/circuitbuild.c
tor/trunk/src/or/connection_or.c
tor/trunk/src/or/control.c
tor/trunk/src/or/networkstatus.c
tor/trunk/src/or/or.h
tor/trunk/src/or/relay.c
tor/trunk/src/or/routerlist.c
Log:
infrastructure for the 'bootstrap status event' feature, so we can
tell the controller how we're doing at bootstrapping, and it can
tell the user.
Modified: tor/trunk/src/or/circuitbuild.c
===================================================================
--- tor/trunk/src/or/circuitbuild.c 2008-06-07 05:24:47 UTC (rev 15007)
+++ tor/trunk/src/or/circuitbuild.c 2008-06-07 05:27:34 UTC (rev 15008)
@@ -373,6 +373,8 @@
circ->_base.n_port = firsthop->extend_info->port;
if (!n_conn || n_conn->_base.or_is_obsolete) { /* launch the connection */
+ if (circ->build_state->onehop_tunnel)
+ control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DIR, 0);
n_conn = connection_or_connect(firsthop->extend_info->addr,
firsthop->extend_info->port,
firsthop->extend_info->identity_digest);
@@ -590,6 +592,10 @@
int fast;
uint8_t cell_type;
log_debug(LD_CIRC,"First skin; sending create cell.");
+ if (circ->build_state->onehop_tunnel)
+ control_event_bootstrap(BOOTSTRAP_STATUS_ONEHOP_CREATE, 0);
+ else
+ control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0);
router = router_get_by_digest(circ->_base.n_conn->identity_digest);
fast = should_use_create_fast_for_router(router, circ);
@@ -641,6 +647,8 @@
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
log_info(LD_CIRC,"circuit built!");
circuit_reset_failure_count(0);
+ if (circ->build_state->onehop_tunnel)
+ control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_STATUS, 0);
if (!has_completed_circuit && !circ->build_state->onehop_tunnel) {
or_options_t *options = get_options();
has_completed_circuit=1;
@@ -648,6 +656,7 @@
log(LOG_NOTICE, LD_GENERAL,
"Tor has successfully opened a circuit. "
"Looks like client functionality is working.");
+ control_event_bootstrap(BOOTSTRAP_STATUS_DONE, 0);
control_event_client_status(LOG_NOTICE, "CIRCUIT_ESTABLISHED");
if (server_mode(options) && !check_whether_orport_reachable()) {
inform_testing_reachability();
Modified: tor/trunk/src/or/connection_or.c
===================================================================
--- tor/trunk/src/or/connection_or.c 2008-06-07 05:24:47 UTC (rev 15007)
+++ tor/trunk/src/or/connection_or.c 2008-06-07 05:27:34 UTC (rev 15008)
@@ -344,6 +344,7 @@
log_debug(LD_OR,"OR connect() to router at %s:%u finished.",
conn->address,conn->port);
+ control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0);
if (get_options()->HttpsProxy) {
char buf[1024];
Modified: tor/trunk/src/or/control.c
===================================================================
--- tor/trunk/src/or/control.c 2008-06-07 05:24:47 UTC (rev 15007)
+++ tor/trunk/src/or/control.c 2008-06-07 05:27:34 UTC (rev 15008)
@@ -3823,3 +3823,94 @@
return 0;
}
+/** Convert the name of a bootstrapping phase <b>s</b> into a string
+ * suitable for display by the controller. */
+static const char *
+bootstrap_status_to_string(bootstrap_status_t s)
+{
+ switch (s) {
+ case BOOTSTRAP_STATUS_STARTING:
+ return "Starting";
+ case BOOTSTRAP_STATUS_CONN_DIR:
+ return "Connecting to directory mirror";
+ case BOOTSTRAP_STATUS_HANDSHAKE:
+ return "Finishing handshake";
+ case BOOTSTRAP_STATUS_HANDSHAKE_DIR:
+ return "Finishing handshake with directory mirror";
+ case BOOTSTRAP_STATUS_ONEHOP_CREATE:
+ return "Establishing one-hop circuit for dir info";
+ case BOOTSTRAP_STATUS_REQUESTING_STATUS:
+ return "Asking for networkstatus consensus";
+ case BOOTSTRAP_STATUS_LOADING_STATUS:
+ return "Loading networkstatus consensus";
+ case BOOTSTRAP_STATUS_LOADING_KEYS:
+ return "Loading authority key certs";
+ case BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS:
+ return "Asking for relay descriptors";
+ case BOOTSTRAP_STATUS_LOADING_DESCRIPTORS:
+ return "Loading relay descriptors";
+ case BOOTSTRAP_STATUS_CONN_OR:
+ return "Connecting to entry guard";
+ case BOOTSTRAP_STATUS_HANDSHAKE_OR:
+ return "Finishing handshake with entry guard";
+ case BOOTSTRAP_STATUS_CIRCUIT_CREATE:
+ return "Establishing circuits";
+ case BOOTSTRAP_STATUS_DONE:
+ return "Done!";
+ default:
+ log_warn(LD_BUG, "Unrecognized bootstrap status code %d", s);
+ return "unknown";
+ }
+}
+
+/** Called when Tor has made progress at bootstrapping its directory
+ * information and initial circuits. <b>status</b> is the new status,
+ * that is, what task we will be doing next. <b>percent</b> is zero if
+ * we just started this task, else it represents progress on the task.
+ */
+int
+control_event_bootstrap(bootstrap_status_t status, int percent)
+{
+ static int last_percent = 0;
+
+ if (last_percent == 100)
+ return 0; /* already bootstrapped; nothing to be done here. */
+
+ /* special case for handshaking status, since our tls handshaking code
+ * can't distinguish what the connection is going to be for. */
+ if (status == BOOTSTRAP_STATUS_HANDSHAKE) {
+ if (last_percent < BOOTSTRAP_STATUS_HANDSHAKE_OR) {
+ status = BOOTSTRAP_STATUS_HANDSHAKE_DIR;
+ } else {
+ status = BOOTSTRAP_STATUS_HANDSHAKE_OR;
+ }
+ }
+
+#if 0
+ if (status <= last_percent)
+ switch (status) {
+ case BOOTSTRAP_STATUS_CONN_DIR:
+ case BOOTSTRAP_STATUS_ONEHOP_CREATE:
+ case BOOTSTRAP_STATUS_HANDSHAKE_DIR:
+ case BOOTSTRAP_STATUS_REQUESTING_STATUS:
+ case BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS:
+ boring = 1;
+ break;
+ default: ;
+ }
+
+ if (!boring)
+#endif
+ if (status > last_percent || (percent && percent > last_percent))
+ log_notice(LD_CONTROL, "Bootstrapped %d%% (last %d): %s.",
+ status, last_percent, bootstrap_status_to_string(status));
+
+ /* ... This is where we tell the controller ... */
+
+ if (percent > last_percent) /* incremental progress within a milestone */
+ last_percent = percent;
+ if (status > last_percent) /* new milestone reached */
+ last_percent = status ;
+ return 0;
+}
+
Modified: tor/trunk/src/or/networkstatus.c
===================================================================
--- tor/trunk/src/or/networkstatus.c 2008-06-07 05:24:47 UTC (rev 15007)
+++ tor/trunk/src/or/networkstatus.c 2008-06-07 05:27:34 UTC (rev 15008)
@@ -1196,6 +1196,14 @@
authority_certs_fetch_missing(current_consensus, now);
}
+/** Return 1 if we have a consensus but we don't have enough certificates
+ * to start using it yet. */
+int
+consensus_is_waiting_for_certs(void)
+{
+ return consensus_waiting_for_certs ? 1 : 0;
+}
+
/** Return the network status with a given identity digest. */
networkstatus_v2_t *
networkstatus_v2_get_by_digest(const char *digest)
Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h 2008-06-07 05:24:47 UTC (rev 15007)
+++ tor/trunk/src/or/or.h 2008-06-07 05:27:34 UTC (rev 15008)
@@ -3016,6 +3016,27 @@
void disable_control_logging(void);
void enable_control_logging(void);
+/** Enum describing various stages of bootstrapping, for use with controller
+ * bootstrap status events. The values range from 0 to 100. */
+typedef enum {
+ BOOTSTRAP_STATUS_STARTING=0,
+ BOOTSTRAP_STATUS_CONN_DIR=5,
+ BOOTSTRAP_STATUS_HANDSHAKE=-1,
+ BOOTSTRAP_STATUS_HANDSHAKE_DIR=10,
+ BOOTSTRAP_STATUS_ONEHOP_CREATE=15,
+ BOOTSTRAP_STATUS_REQUESTING_STATUS=20,
+ BOOTSTRAP_STATUS_LOADING_STATUS=25,
+ BOOTSTRAP_STATUS_LOADING_KEYS=40,
+ BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS=45,
+ BOOTSTRAP_STATUS_LOADING_DESCRIPTORS=50,
+ BOOTSTRAP_STATUS_CONN_OR=80,
+ BOOTSTRAP_STATUS_HANDSHAKE_OR=85,
+ BOOTSTRAP_STATUS_CIRCUIT_CREATE=90,
+ BOOTSTRAP_STATUS_DONE=100
+} bootstrap_status_t;
+
+int control_event_bootstrap(bootstrap_status_t status, int percent);
+
#ifdef CONTROL_PRIVATE
/* Used only by control.c and test.c */
size_t write_escaped_data(const char *data, size_t len, char **out);
@@ -3442,6 +3463,7 @@
int should_delay_dir_fetches(or_options_t *options);
void update_networkstatus_downloads(time_t now);
void update_certificate_downloads(time_t now);
+int consensus_is_waiting_for_certs(void);
networkstatus_v2_t *networkstatus_v2_get_by_digest(const char *digest);
networkstatus_t *networkstatus_get_latest_consensus(void);
networkstatus_t *networkstatus_get_live_consensus(time_t now);
Modified: tor/trunk/src/or/relay.c
===================================================================
--- tor/trunk/src/or/relay.c 2008-06-07 05:24:47 UTC (rev 15007)
+++ tor/trunk/src/or/relay.c 2008-06-07 05:27:34 UTC (rev 15008)
@@ -932,6 +932,28 @@
/* don't send a socks reply to transparent conns */
if (!conn->socks_request->has_finished)
connection_ap_handshake_socks_reply(conn, NULL, 0, 0);
+
+ /* Was it a linked dir conn? If so, a dir request just started to
+ * fetch something; this could be a bootstrap status milestone. */
+ log_debug(LD_APP, "considering");
+ if (TO_CONN(conn)->linked_conn &&
+ TO_CONN(conn)->linked_conn->type == CONN_TYPE_DIR) {
+ connection_t *dirconn = TO_CONN(conn)->linked_conn;
+ log_debug(LD_APP, "it is! %d", dirconn->purpose);
+ switch (dirconn->purpose) {
+ case DIR_PURPOSE_FETCH_CERTIFICATE:
+ if (consensus_is_waiting_for_certs())
+ control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_KEYS, 0);
+ break;
+ case DIR_PURPOSE_FETCH_CONSENSUS:
+ control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_STATUS, 0);
+ break;
+ case DIR_PURPOSE_FETCH_SERVERDESC:
+ control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS, 0);
+ break;
+ }
+ }
+
/* handle anything that might have queued */
if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
/* (We already sent an end cell if possible) */
Modified: tor/trunk/src/or/routerlist.c
===================================================================
--- tor/trunk/src/or/routerlist.c 2008-06-07 05:24:47 UTC (rev 15007)
+++ tor/trunk/src/or/routerlist.c 2008-06-07 05:27:34 UTC (rev 15008)
@@ -4217,6 +4217,7 @@
tor_snprintf(dir_info_status, sizeof(dir_info_status),
"We have only %d/%d usable descriptors.", num_present, num_usable);
res = 0;
+ control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0);
} else if (num_present < 2) {
tor_snprintf(dir_info_status, sizeof(dir_info_status),
"Only %d descriptor%s here and believed reachable!",
@@ -4231,6 +4232,7 @@
log(LOG_NOTICE, LD_DIR,
"We now have enough directory information to build circuits.");
control_event_client_status(LOG_NOTICE, "ENOUGH_DIR_INFO");
+ control_event_bootstrap(BOOTSTRAP_STATUS_CONN_OR, 0);
}
if (!res && have_min_dir_info) {
log(LOG_NOTICE, LD_DIR,"Our directory information is no longer up-to-date "