summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2004-04-13 17:16:47 +0000
committerNick Mathewson <nickm@torproject.org>2004-04-13 17:16:47 +0000
commita2ece0fc08ce7c59ce82402591a4b28b86038a92 (patch)
tree05f90f2f41975a24c2efaf2398acda8933221503
parente0ce205a763fbddc9d87d305fc0ec79c333394bc (diff)
downloadtor-a2ece0fc08ce7c59ce82402591a4b28b86038a92.tar.gz
tor-a2ece0fc08ce7c59ce82402591a4b28b86038a92.zip
Separate "start-establishing-introduction" from "upload descriptors"; only upload descriptors containing fully established intro points.
svn:r1607
-rw-r--r--src/or/circuit.c2
-rw-r--r--src/or/main.c12
-rw-r--r--src/or/or.h4
-rw-r--r--src/or/rendservice.c100
4 files changed, 84 insertions, 34 deletions
diff --git a/src/or/circuit.c b/src/or/circuit.c
index 7b51905329..a599e891db 100644
--- a/src/or/circuit.c
+++ b/src/or/circuit.c
@@ -546,7 +546,7 @@ void circuit_build_needed_circs(time_t now) {
connection_ap_attach_pending();
/* make sure any hidden services have enough intro points */
- rend_services_init();
+ rend_services_introduce();
circ = circuit_get_youngest_clean_open(CIRCUIT_PURPOSE_C_GENERAL);
diff --git a/src/or/main.c b/src/or/main.c
index ee7070acd9..c44d772e6e 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -354,6 +354,8 @@ static void run_scheduled_events(time_t now) {
/* We're a directory; dump any old descriptors. */
dirserv_remove_old_servers();
}
+ /* Force an upload of our descriptors every DirFetchPostPeriod seconds. */
+ rend_services_upload(1);
rend_cache_clean(); /* should this go elsewhere? */
time_to_fetch_directory = now + options.DirFetchPostPeriod;
}
@@ -393,6 +395,10 @@ static void run_scheduled_events(time_t now) {
/* 5. And remove any marked circuits... */
circuit_close_all_marked();
+ /* 6. And upload service descriptors for any services whose intro points
+ * have changed in the last second. */
+ rend_services_upload(0);
+
#if 0
/* 6. and blow away any connections that need to die. can't do this later
* because we might open up a circuit and not realize we're about to cull
@@ -501,7 +507,7 @@ static int do_hup(void) {
exit(1);
}
/* reload keys as needed for rendezvous services. */
- if (rend_service_init_keys()<0) {
+ if (rend_service_load_keys()<0) {
log_fn(LOG_ERR,"Error reloading rendezvous service keys");
exit(1);
}
@@ -518,7 +524,7 @@ static int do_hup(void) {
}
/* Since we aren't fetching a directory, we won't retry rendezvous points
* when it gets in. Try again now. */
- rend_services_init();
+ rend_services_introduce();
} else {
/* fetch a new directory */
directory_initiate_command(router_pick_directory_server(),
@@ -547,7 +553,7 @@ static int do_main_loop(void) {
/* load the private keys, if we're supposed to have them, and set up the
* TLS context. */
- if (init_keys() < 0 || rend_service_init_keys() < 0) {
+ if (init_keys() < 0 || rend_service_load_keys() < 0) {
log_fn(LOG_ERR,"Error initializing keys; exiting");
return -1;
}
diff --git a/src/or/or.h b/src/or/or.h
index 9f85af996a..c6949281e7 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1082,8 +1082,10 @@ int rend_cache_store(char *desc, int desc_len);
/********************************* rendservice.c ***************************/
int rend_config_services(or_options_t *options);
-int rend_service_init_keys(void);
+int rend_service_load_keys(void);
void rend_services_init(void);
+void rend_services_introduce(void);
+void rend_services_upload(int force);
void rend_service_intro_is_ready(circuit_t *circuit);
int rend_service_intro_established(circuit_t *circuit, const char *request, int request_len);
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 608a19773b..22c521916b 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -7,6 +7,8 @@
#include "or.h"
+static circuit_t *find_intro_circuit(routerinfo_t *router, const char *pk_digest);
+
/* Represents the mapping from a virtual port of a rendezvous service to
* a real port on some IP.
*/
@@ -32,8 +34,9 @@ typedef struct rend_service_t {
crypto_pk_env_t *private_key;
char service_id[REND_SERVICE_ID_LEN+1];
char pk_digest[DIGEST_LEN];
- smartlist_t *intro_nodes; /* list of nicknames */
+ smartlist_t *intro_nodes; /* list of nicknames for intro points we _want_ */
rend_service_descriptor_t *desc;
+ int desc_is_dirty;
} rend_service_t;
/* A list of rend_service_t's for services run on this OP.
@@ -231,7 +234,9 @@ int rend_config_services(or_options_t *options)
static void rend_service_update_descriptor(rend_service_t *service)
{
rend_service_descriptor_t *d;
+ circuit_t *circ;
int i,n;
+ routerinfo_t *router;
if (service->desc) {
rend_service_descriptor_free(service->desc);
@@ -240,17 +245,23 @@ static void rend_service_update_descriptor(rend_service_t *service)
d = service->desc = tor_malloc(sizeof(rend_service_descriptor_t));
d->pk = crypto_pk_dup_key(service->private_key);
d->timestamp = time(NULL);
- n = d->n_intro_points = smartlist_len(service->intro_nodes);
+ n = smartlist_len(service->intro_nodes);
+ d->n_intro_points = 0;
d->intro_points = tor_malloc(sizeof(char*)*n);
for (i=0; i < n; ++i) {
- d->intro_points[i] = tor_strdup(smartlist_get(service->intro_nodes, i));
+ router = router_get_by_nickname(smartlist_get(service->intro_nodes, i));
+ circ = find_intro_circuit(router, service->pk_digest);
+ if (circ->purpose == CIRCUIT_PURPOSE_S_INTRO) {
+ /* We have an entirely established intro circuit. */
+ d->intro_points[d->n_intro_points++] = tor_strdup(router->nickname);
+ }
}
}
/* Load and/or generate private keys for all hidden services. Return 0 on
* success, -1 on failure.
*/
-int rend_service_init_keys(void)
+int rend_service_load_keys(void)
{
int i;
rend_service_t *s;
@@ -529,14 +540,23 @@ rend_service_intro_is_ready(circuit_t *circuit)
circuit_mark_for_close(circuit);
}
-/* Handle an intro_established cell. */
+/* Handle an INTRO_ESTABLISHED cell. */
int
rend_service_intro_established(circuit_t *circuit, const char *request, int request_len)
{
+ rend_service_t *service;
+
if (circuit->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
log_fn(LOG_WARN, "received INTRO_ESTABLISHED cell on non-intro circuit");
goto err;
}
+ service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
+ if (!service) {
+ log_fn(LOG_WARN, "Unknown service on introduction circuit %d",
+ circuit->n_circ_id);
+ goto err;
+ }
+ service->desc_is_dirty = 1;
circuit->purpose = CIRCUIT_PURPOSE_S_INTRO;
return 0;
@@ -653,6 +673,31 @@ find_intro_circuit(routerinfo_t *router, const char *pk_digest)
return NULL;
}
+static void
+upload_service_descriptor(rend_service_t *service)
+{
+ char *desc;
+ int desc_len;
+ if (!service->desc_is_dirty)
+ return;
+
+ /* Update the descriptor. */
+ rend_service_update_descriptor(service);
+ if (rend_encode_service_descriptor(service->desc,
+ service->private_key,
+ &desc, &desc_len)<0) {
+ log_fn(LOG_WARN, "Couldn't encode service descriptor; not uploading");
+ return;
+ }
+
+ /* Post it to the dirservers */
+ router_post_to_dirservers(DIR_PURPOSE_UPLOAD_RENDDESC, desc, desc_len);
+ tor_free(desc);
+
+ service->desc_is_dirty = 0;
+}
+
+
/* XXXX Make this longer once directories remember service descriptors across
* restarts.*/
#define MAX_SERVICE_PUBLICATION_INTERVAL (15*60)
@@ -660,18 +705,16 @@ find_intro_circuit(routerinfo_t *router, const char *pk_digest)
/* For every service, check how many intro points it currently has, and:
* - Pick new intro points as necessary.
* - Launch circuits to any new intro points.
- * - Upload a fresh service descriptor if anything has changed.
*/
-void rend_services_init(void) {
+void rend_services_introduce(void) {
int i,j,r;
routerinfo_t *router;
routerlist_t *rl;
rend_service_t *service;
- char *desc, *intro;
- int changed, prev_intro_nodes, desc_len;
+ char *intro;
+ int changed, prev_intro_nodes;
smartlist_t *intro_routers, *exclude_routers;
int n_old_routers;
- time_t now;
router_get_routerlist(&rl);
intro_routers = smartlist_create();
@@ -686,7 +729,7 @@ void rend_services_init(void) {
assert(service);
changed = 0;
- /* Find out which introduction points we really have for this service. */
+ /* Find out which introduction points we have in progress for this service. */
for (j=0;j< smartlist_len(service->intro_nodes); ++j) {
router = router_get_by_nickname(smartlist_get(service->intro_nodes,j));
if (!router || !find_intro_circuit(router,service->pk_digest)) {
@@ -728,26 +771,10 @@ void rend_services_init(void) {
* time around the loop. */
smartlist_truncate(exclude_routers, n_old_routers);
- /* If there's no need to republish, stop here. */
- now = time(NULL);
- if (!changed && service->desc &&
- service->desc->timestamp+MAX_SERVICE_PUBLICATION_INTERVAL >= now)
+ /* If there's no need to launch new circuits, stop here. */
+ if (!changed)
continue;
- /* Update the descriptor. */
- rend_service_update_descriptor(service);
- if (rend_encode_service_descriptor(service->desc,
- service->private_key,
- &desc, &desc_len)<0) {
-
- log_fn(LOG_WARN, "Couldn't encode service descriptor; not uploading");
- continue;
- }
-
- /* Post it to the dirservers */
- router_post_to_dirservers(DIR_PURPOSE_UPLOAD_RENDDESC, desc, desc_len);
- tor_free(desc);
-
/* Establish new introduction points. */
for (j=prev_intro_nodes; j < smartlist_len(service->intro_nodes); ++j) {
intro = smartlist_get(service->intro_nodes, j);
@@ -762,6 +789,21 @@ void rend_services_init(void) {
}
void
+rend_services_upload(int force)
+{
+ int i;
+ rend_service_t *service;
+
+ for (i=0; i< smartlist_len(rend_service_list); ++i) {
+ service = smartlist_get(rend_service_list, i);
+ if (force)
+ service->desc_is_dirty = 1;
+ if (service->desc_is_dirty)
+ upload_service_descriptor(service);
+ }
+}
+
+void
rend_service_dump_stats(int severity)
{
int i,j;