diff options
author | Nick Mathewson <nickm@torproject.org> | 2008-12-10 18:16:58 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2008-12-10 18:16:58 +0000 |
commit | 426b53d85a246a31e7c2da3a591f6b70ece3a8c6 (patch) | |
tree | 2fd74b4aea9ef35f0d1be96931b47caee61ac8e6 /src/or/rendservice.c | |
parent | c24627fa6ffb09de364d92be9135ef3c4e7f620b (diff) | |
download | tor-426b53d85a246a31e7c2da3a591f6b70ece3a8c6.tar.gz tor-426b53d85a246a31e7c2da3a591f6b70ece3a8c6.zip |
Apply patch from Karsten to fix bug 879. Backport candidate.
svn:r17562
Diffstat (limited to 'src/or/rendservice.c')
-rw-r--r-- | src/or/rendservice.c | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 8495d49889..efc8b4571e 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -291,9 +291,10 @@ rend_config_services(or_options_t *options, int validate_only) config_line_t *line; rend_service_t *service = NULL; rend_service_port_config_t *portcfg; + smartlist_t *old_service_list = NULL; if (!validate_only) { - rend_service_free_all(); + old_service_list = rend_service_list; rend_service_list = smartlist_create(); } @@ -473,6 +474,64 @@ rend_config_services(or_options_t *options, int validate_only) rend_add_service(service); } + /* If this is a reload and there were hidden services configured before, + * keep the introduction points that are still needed and close the + * other ones. */ + if (old_service_list && !validate_only) { + smartlist_t *surviving_services = smartlist_create(); + circuit_t *circ; + + /* Copy introduction points to new services. */ + /* XXXX This is O(n^2), but it's only called on reconfigure, so it's + * probably ok? */ + SMARTLIST_FOREACH(rend_service_list, rend_service_t *, new, { + SMARTLIST_FOREACH(old_service_list, rend_service_t *, old, { + if (!strcmp(old->directory, new->directory) && + old->descriptor_version == new->descriptor_version) { + smartlist_add_all(new->intro_nodes, old->intro_nodes); + smartlist_clear(old->intro_nodes); + smartlist_add(surviving_services, old); + break; + } + }); + }); + + /* Close introduction circuits of services we don't serve anymore. */ + /* XXXX it would be nicer if we had a nicer abstraction to use here, + * so we could just iterate over the list of services to close, but + * once again, this isn't critical-path code. */ + for (circ = _circuit_get_global_list(); circ; circ = circ->next) { + if (!circ->marked_for_close && + circ->state == CIRCUIT_STATE_OPEN && + (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || + circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) { + origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ); + int keep_it = 0; + tor_assert(oc->rend_data); + SMARTLIST_FOREACH(surviving_services, rend_service_t *, ptr, { + if (!memcmp(ptr->pk_digest, oc->rend_data->rend_pk_digest, + DIGEST_LEN) && + ptr->descriptor_version == oc->rend_data->rend_desc_version) { + keep_it = 1; + break; + } + }); + if (keep_it) + continue; + log_info(LD_REND, "Closing intro point %s for service %s version %d.", + safe_str(oc->build_state->chosen_exit->nickname), + oc->rend_data->onion_address, + oc->rend_data->rend_desc_version); + circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); + /* XXXX Is there another reason we should use here? */ + } + } + smartlist_free(surviving_services); + SMARTLIST_FOREACH(old_service_list, rend_service_t *, ptr, + rend_service_free(ptr)); + smartlist_free(old_service_list); + } + return 0; } |