[or-cvs] Implement rennd_services_init

Nick Mathewson nickm at seul.org
Fri Apr 2 23:01:03 UTC 2004


Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/tmp/cvs-serv32664/src/or

Modified Files:
	or.h rendservice.c 
Log Message:
Implement rennd_services_init

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.281
retrieving revision 1.282
diff -u -d -r1.281 -r1.282
--- or.h	2 Apr 2004 22:30:39 -0000	1.281
+++ or.h	2 Apr 2004 23:01:00 -0000	1.282
@@ -977,7 +977,7 @@
 routerinfo_t *router_pick_directory_server(void);
 routerinfo_t *router_choose_random_node(routerlist_t *dir,
                                         char *preferred, char *excluded,
-                                        smartlist_t *excludedsmartlist);
+                                        struct smartlist_t *excludedsmartlist);
 routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
 routerinfo_t *router_get_by_link_pk(crypto_pk_env_t *pk);
 routerinfo_t *router_get_by_nickname(char *nickname);

Index: rendservice.c
===================================================================
RCS file: /home/or/cvsroot/src/or/rendservice.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- rendservice.c	2 Apr 2004 22:23:15 -0000	1.10
+++ rendservice.c	2 Apr 2004 23:01:00 -0000	1.11
@@ -16,18 +16,22 @@
   uint32_t real_address;
 } rend_service_port_config_t;
 
+#define NUM_INTRO_POINTS 3
+
 /* Represents a single hidden service running at this OP.
  */
 typedef struct rend_service_t {
   /* Fields specified in config file */
   char *directory; /* where in the filesystem it stores it */
   smartlist_t *ports;
-  char *intro_nodes;
+  char *intro_prefer_nodes;
   char *intro_exclude_nodes;
   /* Other fields */
   crypto_pk_env_t *private_key;
   char service_id[REND_SERVICE_ID_LEN+1];
   char pk_digest[20];
+  smartlist_t *intro_nodes; /* list of nicknames */
+  rend_service_descriptor_t *desc;
 } rend_service_t;
 
 /* A list of rend_service_t.
@@ -45,6 +49,15 @@
   smartlist_free(config->ports);
   if (config->private_key)
     crypto_free_pk_env(config->private_key);
+  tor_free(config->intro_prefer_nodes);
+  tor_free(config->intro_exclude_nodes);
+  for (i=0; i<config->intro_nodes->num_used; ++i) {
+    tor_free(config->intro_nodes->list[i]);
+  }
+  smartlist_free(config->intro_nodes);
+  if (config->desc)
+    rend_service_descriptor_free(config->desc);
+  tor_free(config);
 }
 
 static void rend_service_free_all(void)
@@ -67,6 +80,11 @@
   rend_service_port_config_t *p;
   struct in_addr addr;
 
+  if (!service->intro_prefer_nodes)
+    service->intro_prefer_nodes = tor_strdup("");
+  if (!service->intro_exclude_nodes)
+    service->intro_exclude_nodes = tor_strdup("");
+
   if (!service->ports->num_used) {
     log_fn(LOG_WARN, "Hidden service with no ports configured; ignoring.");
     rend_service_free(service);
@@ -167,6 +185,7 @@
       service = tor_malloc_zero(sizeof(rend_service_t));
       service->directory = tor_strdup(line->value);
       service->ports = smartlist_create();
+      service->intro_nodes = smartlist_create();
       continue;
     }
     if (!service) {
@@ -182,11 +201,11 @@
       }
       smartlist_add(service->ports, portcfg);
     } else if (!strcasecmp(line->key, "HiddenServiceNodes")) {
-      if (service->intro_nodes) {
+      if (service->intro_prefer_nodes) {
         log_fn(LOG_WARN, "Got multiple HiddenServiceNodes lines for a single service");
         return -1;
       }
-      service->intro_nodes = tor_strdup(line->value);
+      service->intro_prefer_nodes = tor_strdup(line->value);
     } else {
       assert(!strcasecmp(line->key, "HiddenServiceExcludeNodes"));
       if (service->intro_exclude_nodes) {
@@ -202,6 +221,28 @@
   return 0;
 }
 
+/*
+ * DOCDOC
+ */
+static void rend_service_update_descriptor(rend_service_t *service)
+{
+  rend_service_descriptor_t *d;
+  int i,n;
+
+  if (service->desc) {
+    rend_service_descriptor_free(service->desc);
+    service->desc = NULL;
+  }
+  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 = service->intro_nodes->num_used;
+  d->intro_points = tor_malloc(sizeof(char*)*n);
+  for (i=0; i < n; ++i) {
+    d->intro_points[i] = tor_strdup(service->intro_nodes->list[i]);
+  }
+}
+
 /* Load and/or generate private keys for all hidden services.  Return 0 on
  * success, -1 on failure.
  */
@@ -499,40 +540,105 @@
  * Manage introduction points
  ******/
 
-#define NUM_INTRO_POINTS 3
+/* 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.
+ *  -
+ */
 int rend_services_init(void) {
   int i,j,r;
   routerinfo_t *router;
   routerlist_t *rl;
   rend_service_t *service;
+  circuit_t *circ;
+  char *desc, *intro;
+  int changed, found, prev_intro_nodes, desc_len;
 
   router_get_routerlist(&rl);
 
   for (i=0;i<rend_service_list->num_used;++i) {
     service = rend_service_list->list[i];
+    assert(service);
+    changed = 0;
 
-    /* The directory is now here. Pick three ORs as intro points. */
-    for (j=0;j<rl->n_routers;j++) {
-      router = rl->routers[j];
-      //...
-      // maybe built a smartlist of all of them, then pick at random
-      // until you have three? or something smarter.
+    /* Find out which introduction points we really have for this service. */
+    for (j=0;j<service->intro_nodes->num_used;++j) {
+      router = router_get_by_nickname(service->intro_nodes->list[j]);
+      if (!router)
+        goto remove_point;
+      circ = NULL;
+      found = 1;
+      while ((circ = circuit_get_next_by_service_and_purpose(
+                                                circ,service->pk_digest,
+                                                CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
+        assert(circ->cpath);
+        if (circ->cpath->prev->addr == router->addr &&
+            circ->cpath->prev->port == router->or_port) {
+          found = 1; break;
+        }
+      }
+      if (found) continue;
+
+    remove_point:
+      tor_free(service->intro_nodes->list[j]);
+      service->intro_nodes->list[j] =
+        service->intro_nodes->list[service->intro_nodes->num_used-1];
+      --service->intro_nodes->num_used;
+      --j;
+      changed = 1;
     }
 
-    /* build a service descriptor out of them, and tuck it away
-     * somewhere so we don't lose it */
+    /* We have enough intro points, and the intro points we thought we had were
+     * all connected.
+     */
+    if (!changed && service->intro_nodes->num_used >= NUM_INTRO_POINTS)
+      continue;
 
-    /* post it to the dirservers */
-    //call router_post_to_dirservers(DIR_PURPOSE_UPLOAD_HIDSERV, desc, desc_len);
+    /* Remember how many introduction circuits we started with. */
+    prev_intro_nodes = service->intro_nodes->num_used;
 
-    // for each intro point,
-    {
-      //r = rend_service_launch_establish_intro(service, intro->nickname);
-      //if (r<0) freak out
+    /* The directory is now here. Pick three ORs as intro points. */
+    for (j=prev_intro_nodes; j < NUM_INTRO_POINTS; ++j) {
+      router = router_choose_random_node(rl,
+                                         service->intro_prefer_nodes,
+                                         service->intro_exclude_nodes,
+                                         service->intro_nodes);
+      if (!router) {
+        log_fn(LOG_WARN, "Can't establish more than %d introduction points",
+               service->intro_nodes->num_used);
+        break;
+      }
+      changed = 1;
+      smartlist_add(service->intro_nodes, tor_strdup(router->nickname));
     }
 
-    // anything else?
+    /* If there's no need to republish, 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 (i=prev_intro_nodes; i < service->intro_nodes->num_used; ++i) {
+      intro = (char*) service->intro_nodes->list[i];
+      r = rend_service_launch_establish_intro(service, intro);
+      if (r<0) {
+        log_fn(LOG_WARN, "Error launching circuit to node %s", intro);
+      }
+    }
   }
+  return 0;
 }
 
 /*



More information about the tor-commits mailing list