Ticket #874: patch874a.txt

File patch874a.txt, 3.0 KB (added by karsten, 11 years ago)
Line 
1Index: /home/karsten/tor/tor-trunk-874-2/src/or/rendservice.c
2===================================================================
3--- /home/karsten/tor/tor-trunk-874-2/src/or/rendservice.c      (revision 17476)
4+++ /home/karsten/tor/tor-trunk-874-2/src/or/rendservice.c      (working copy)
5@@ -291,9 +291,10 @@
6   config_line_t *line;
7   rend_service_t *service = NULL;
8   rend_service_port_config_t *portcfg;
9+  smartlist_t *old_service_list = NULL;
10 
11   if (!validate_only) {
12-    rend_service_free_all();
13+    old_service_list = rend_service_list;
14     rend_service_list = smartlist_create();
15   }
16 
17@@ -473,6 +474,61 @@
18       rend_add_service(service);
19   }
20 
21+  /* If this is a reload and there were hidden services configured before,
22+   * keep the introduction points that are still needed and close the
23+   * other ones. */
24+  if (old_service_list && !validate_only) {
25+    smartlist_t *surviving_services = smartlist_create();
26+    circuit_t *circ;
27+
28+    /* Copy introduction points to new services. */
29+    SMARTLIST_FOREACH(rend_service_list, rend_service_t *, new, {
30+      SMARTLIST_FOREACH(old_service_list, rend_service_t *, old, {
31+        if (strlen(old->directory) == strlen(new->directory) &&
32+            !strncmp(old->directory, new->directory, strlen(old->directory)) &&
33+              /* ^ Is there a better way to compare the two directories? */
34+            old->descriptor_version == new->descriptor_version) {
35+          smartlist_add_all(new->intro_nodes, old->intro_nodes);
36+          smartlist_clear(old->intro_nodes);
37+          smartlist_add(surviving_services, old);
38+          break;
39+        }
40+      });
41+    });
42+
43+    /* Close introduction circuits of services we don't serve anymore. */
44+    for (circ = _circuit_get_global_list(); circ; circ = circ->next) {
45+      if (!circ->marked_for_close &&
46+          circ->state == CIRCUIT_STATE_OPEN &&
47+          (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
48+           circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) {
49+        origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
50+        int keep_it = 0;
51+        tor_assert(oc->rend_data);
52+        SMARTLIST_FOREACH(surviving_services, rend_service_t *, ptr, {
53+          if (!memcmp(ptr->pk_digest, oc->rend_data->rend_pk_digest,
54+                      DIGEST_LEN) &&
55+              ptr->descriptor_version == oc->rend_data->rend_desc_version) {
56+            keep_it = 1;
57+            break;
58+          }
59+        });
60+        if (keep_it)
61+          continue;
62+        log_info(LD_REND, "Closing intro point %s for service %s version %d.",
63+                 safe_str(oc->build_state->chosen_exit->nickname),
64+                 oc->rend_data->onion_address,
65+                 oc->rend_data->rend_desc_version);
66+        circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
67+          /* ^ Is there another reason we should use here? */
68+      }
69+    }
70+    smartlist_free(surviving_services);
71+    SMARTLIST_FOREACH(old_service_list, rend_service_t *, ptr,
72+                      rend_service_free(ptr));
73+    smartlist_free(old_service_list);
74+  }
75+
76   return 0;
77 }
78 
79