[or-cvs] r11312: broke down huge encoding/parsing functions (in tor/branches/114-dist-storage: doc doc/spec doc/spec/proposals src/common src/or)

kloesing at seul.org kloesing at seul.org
Wed Aug 29 21:52:34 UTC 2007


Author: kloesing
Date: 2007-08-29 17:52:32 -0400 (Wed, 29 Aug 2007)
New Revision: 11312

Modified:
   tor/branches/114-dist-storage/doc/spec/proposals/114-distributed-storage.txt
   tor/branches/114-dist-storage/doc/spec/rend-spec.txt
   tor/branches/114-dist-storage/doc/tor.1.in
   tor/branches/114-dist-storage/src/common/crypto.c
   tor/branches/114-dist-storage/src/common/crypto.h
   tor/branches/114-dist-storage/src/or/config.c
   tor/branches/114-dist-storage/src/or/directory.c
   tor/branches/114-dist-storage/src/or/dirserv.c
   tor/branches/114-dist-storage/src/or/or.h
   tor/branches/114-dist-storage/src/or/rendcommon.c
   tor/branches/114-dist-storage/src/or/rendservice.c
   tor/branches/114-dist-storage/src/or/routerlist.c
   tor/branches/114-dist-storage/src/or/routerparse.c
   tor/branches/114-dist-storage/src/or/test.c
Log:
broke down huge encoding/parsing functions

Modified: tor/branches/114-dist-storage/doc/spec/proposals/114-distributed-storage.txt
===================================================================
--- tor/branches/114-dist-storage/doc/spec/proposals/114-distributed-storage.txt	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/doc/spec/proposals/114-distributed-storage.txt	2007-08-29 21:52:32 UTC (rev 11312)
@@ -524,7 +524,7 @@
     The new v2 hidden service descriptor format looks like this:
 
       onion-address = h(public-key) + cookie
-      descriptor-id = h(h(public-key) + h(time-period + cookie + relica))
+      descriptor-id = h(h(public-key) + h(time-period + cookie + replica))
       descriptor-content = {
         descriptor-id,
         version,

Modified: tor/branches/114-dist-storage/doc/spec/rend-spec.txt
===================================================================
--- tor/branches/114-dist-storage/doc/spec/rend-spec.txt	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/doc/spec/rend-spec.txt	2007-08-29 21:52:32 UTC (rev 11312)
@@ -227,12 +227,12 @@
        Indicates the beginning of the descriptor. "descriptor-id" is a
        temporary identifier of 160 bits formatted as 32 base32 chars that can
        only be calculated by the hidden service and its clients, i.e. by
-       everyone who is aware of a secret "cookie". (Further, everyone can
+       everyone who is aware of a "secret-cookie". (Further, everyone can
        verify that this "descriptor-id" belongs to the rest of the descriptor,
-       even without knowing "cookie", as described below.) The "descriptor-id"
-       is calculated by performing the following operation:
+       even without knowing "secret-cookie", as described below.) The
+       "descriptor-id" is calculated by performing the following operation:
 
-         descriptor-id = h(permanent-id, h(time-period, cookie))
+         descriptor-id = h(permanent-id, h(time-period, secret-cookie, replica))
 
        "h" denotes the cryptographically secure hash function SHA1 that takes
        an ordered sequence of one or more byte arrays as arguments and returns
@@ -244,30 +244,33 @@
 
          permanent-id = h(public-key)
 
-       "h(time-period, cookie)" is the secret id part that is necessary to
+       "h(time-period, cookie, replica)" is the secret id part that is
+       necessary to
        verify that the hidden service is the true originator of this
        descriptor. It can only be created by the hidden service and its
        clients, but the "signature" below can only be created by the service.
 
        "cookie" is a secret password of 120 bits that is shared between the
        hidden service provider and its clients.
+       
+       "replica" denotes the number of the non-consecutive replica.
 
        The "time-period" changes periodically depending on the global time and
        as a function of "permanent-id". The current value for "time-period" can
        be calculated using the following formula:
 
-         time-period = floor(current-time / period-length
-                             + permanent-id / (max-id + 1))
+         time-period = (current-time + permanent-id-byte * 86400 / 256)
+                         / 86400
 
-       "current-time" is the current system time in seconds since 1970-01-01
-       00:00. "period-length" is a system-wide constant in seconds that
-       determines how often "descriptor-id" changes, e.g. one day. "max-id"
-       denotes the theoretical value of the maximum possible "permanent-id" ---
-       it is used to normalize "permanent-id" to a [0.0..1.0[ range so that
-       "time-period" does not change for all descriptors at the same time. All
-       operations have double floating-point precision. "floor" truncates all
-       decimal places.
-
+       "current-time" contains the current system time in seconds since
+       1970-01-01 00:00, e.g. 1188241957. "permanent-id-byte" is the first
+       (unsigned) byte of the permanent identifier (which is in network
+       order), e.g. 143. Adding the product of "permanent-id-byte" and
+       86400 (seconds per day), divided by 256, prevents "time-period" from
+       changing for all descriptors at the same time of the day. The result
+       of the overall operation is a (network-ordered) 32-bit integer, e.g.
+       13753 or 0x000035B9 with the example values given above.
+       
      "version" version-number NL
 
        [Exactly once]
@@ -289,7 +292,7 @@
        32 base32 chars. Using this secret id part, everyone can verify that
        the signed descriptor belongs to "descriptor-id".
 
-         secret-id-part = h(time-period, cookie)
+         secret-id-part = h(time-period, cookie, replica)
    
      "publication-time" YYYY-MM-DD HH:MM:SS NL
    

Modified: tor/branches/114-dist-storage/doc/tor.1.in
===================================================================
--- tor/branches/114-dist-storage/doc/tor.1.in	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/doc/tor.1.in	2007-08-29 21:52:32 UTC (rev 11312)
@@ -101,6 +101,12 @@
 Windows since that platform lacks getrlimit(). (Default: 1000)
 .LP
 .TP
+\fBConsiderAllRoutersAsHidServDirectories \fR\fB0\fR|\fB1\fR\fP
+If set, Tor will consider all routers in the network as hidden service
+directories for v2 descriptors. This option is only useful for testing!
+(Default: 0)
+.LP
+.TP
 \fBConstrainedSockets \fR\fB0\fR|\fB1\fR\fP
 If set, Tor will tell the kernel to attempt to shrink the buffers for all 
 sockets to the size specified in \fBConstrainedSockSize\fP.  This is useful 

Modified: tor/branches/114-dist-storage/src/common/crypto.c
===================================================================
--- tor/branches/114-dist-storage/src/common/crypto.c	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/src/common/crypto.c	2007-08-29 21:52:32 UTC (rev 11312)
@@ -1155,8 +1155,8 @@
  * return the number of bytes written, on failure, return -1.
  */
 int
-crypto_cipher_encrypt_cbc(char *key, char *to, size_t tolen, const char *from,
-                          size_t fromlen)
+crypto_cipher_encrypt_cbc(const char *key, char *to, size_t tolen,
+                          const char *from, size_t fromlen)
 {
 
   EVP_CIPHER_CTX ctx_msg, ctx_iv; /* cipher contexts for message and IV */
@@ -1236,8 +1236,8 @@
  * wrong key), return -1.
  */
 int
-crypto_cipher_decrypt_cbc(char *key, char *to, size_t tolen, const char *from,
-                          size_t fromlen)
+crypto_cipher_decrypt_cbc(const char *key, char *to, size_t tolen,
+                          const char *from, size_t fromlen)
 {
   EVP_CIPHER_CTX ctx_msg, ctx_iv; /* cipher contexts for message and IV */
   unsigned char iv[AES_IV_SIZE]; /* initialization vector */

Modified: tor/branches/114-dist-storage/src/common/crypto.h
===================================================================
--- tor/branches/114-dist-storage/src/common/crypto.h	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/src/common/crypto.h	2007-08-29 21:52:32 UTC (rev 11312)
@@ -124,9 +124,9 @@
 int crypto_cipher_decrypt(crypto_cipher_env_t *env, char *to,
                           const char *from, size_t fromlen);
 
-int crypto_cipher_encrypt_cbc(char *key, char *to, size_t tolen,
+int crypto_cipher_encrypt_cbc(const char *key, char *to, size_t tolen,
                               const char *from, size_t fromlen);
-int crypto_cipher_decrypt_cbc(char *key, char *to, size_t tolen,
+int crypto_cipher_decrypt_cbc(const char *key, char *to, size_t tolen,
                               const char *from, size_t fromlen);
 
 /* SHA-1 */

Modified: tor/branches/114-dist-storage/src/or/config.c
===================================================================
--- tor/branches/114-dist-storage/src/or/config.c	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/src/or/config.c	2007-08-29 21:52:32 UTC (rev 11312)
@@ -151,6 +151,8 @@
   VAR("ControlListenAddress",LINELIST, ControlListenAddress, NULL),
   VAR("ControlPort",         UINT,     ControlPort,          "0"),
   VAR("ControlSocket",       LINELIST, ControlSocket,        NULL),
+  VAR("ConsiderAllRoutersAsHidServDirectories", BOOL,
+                     ConsiderAllRoutersAsHidServDirectories, "0"),
   VAR("CookieAuthentication",BOOL,     CookieAuthentication, "0"),
   VAR("DataDirectory",       STRING,   DataDirectory,        NULL),
   OBSOLETE("DebugLogFile"),

Modified: tor/branches/114-dist-storage/src/or/directory.c
===================================================================
--- tor/branches/114-dist-storage/src/or/directory.c	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/src/or/directory.c	2007-08-29 21:52:32 UTC (rev 11312)
@@ -2605,23 +2605,32 @@
   return 0;
 }
 
-/** Determine the responsible hidden service directories for <b>desc_ids</b>
- * and upload the appropriate descriptor from <b>descs</b> to them.
- *
- * TODO114 enable tunneling when available!!
- */
+/** Determine the responsible hidden service directories for
+ * <b>desc_ids</b> and upload the appropriate descriptor from
+ * <b>desc_strs</b> to them; each smartlist must contain
+ * NUMBER_OF_NON_CONSECUTIVE_REPLICAS entries; <b>service_id</b> and
+ * <b>seconds_valid</b> are only passed for logging purposes.*/
+/* TODO114 enable tunneling when available!! */
 void
-directory_post_to_hs_dir(const char *service_id,
-                         char desc_ids[][DIGEST_LEN],
-                         smartlist_t *descs, int seconds_valid)
+directory_post_to_hs_dir(smartlist_t *desc_ids, smartlist_t *desc_strs,
+                         const char *service_id, int seconds_valid)
 {
   int i, j;
   smartlist_t *hs_dirs = smartlist_create();
   routerstatus_t *hs_dir;
+  if (desc_ids->num_used != NUMBER_OF_NON_CONSECUTIVE_REPLICAS ||
+      desc_strs->num_used != NUMBER_OF_NON_CONSECUTIVE_REPLICAS) {
+    log_warn(LD_REND, "Could not post descriptors to hidden service "
+                      "directories: Illegal number of descriptor "
+                      "IDs/strings");
+    return;
+  }
   for (i = 0; i < NUMBER_OF_NON_CONSECUTIVE_REPLICAS; i++) {
+    const char *desc_id = desc_ids->list[i];
+    const char *desc_str = desc_strs->list[i];
     /* Determine responsible dirs. */
     smartlist_clear(hs_dirs);
-    if (get_responsible_hs_dirs(desc_ids[i], hs_dirs) < 0) {
+    if (get_responsible_hs_dirs(desc_id, hs_dirs) < 0) {
       log_warn(LD_REND, "Could not determine the responsible hidden service "
                         "directories to post descriptors to.");
       return;
@@ -2633,10 +2642,10 @@
       directory_initiate_command_routerstatus(hs_dir,
                                               DIR_PURPOSE_UPLOAD_RENDDESC_V2,
                                               ROUTER_PURPOSE_GENERAL, 0,
-                                              NULL, descs->list[i],
-                                              strlen(descs->list[i]));
+                                              NULL, desc_str,
+                                              strlen(desc_str));
       base32_encode(desc_id_base32, REND_DESC_ID_V2_LEN + 1,
-                    desc_ids[i], DIGEST_LEN);
+                    desc_id, DIGEST_LEN);
       log_info(LD_REND, "Sending publish request for v2 descriptor for "
                         "service '%s' with descriptor ID '%s' with validity "
                         "of %d seconds to hidden service directory '%s' on "
@@ -2759,12 +2768,14 @@
     if (!pred_router) {
       log_warn(LD_REND, "Did not find combined status for router. "
                         "Skipping router for replication.");
+      i--;
       continue;
     }
     pred_status = &(pred_router->status);
     if (!pred_status) {
       log_warn(LD_REND, "Could not determine router status. "
                         "Skipping router for replication.");
+      i--;
       continue;
     }
     base32_encode(from_id_base32, REND_DESC_ID_V2_LEN + 1, predecessor1,

Modified: tor/branches/114-dist-storage/src/or/dirserv.c
===================================================================
--- tor/branches/114-dist-storage/src/or/dirserv.c	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/src/or/dirserv.c	2007-08-29 21:52:32 UTC (rev 11312)
@@ -1872,6 +1872,8 @@
       guard_bandwidth_excluding_exits));
   rs->is_bad_exit = listbadexits && ri->is_bad_exit;
   ri->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, now);
+  if (get_options()->ConsiderAllRoutersAsHidServDirectories)
+    ri->is_hs_dir = 1; /* Override real value. */
   rs->is_hs_dir = ri->is_hs_dir;
   /* 0.1.1.9-alpha is the first version to support fetch by descriptor
    * hash. */

Modified: tor/branches/114-dist-storage/src/or/or.h
===================================================================
--- tor/branches/114-dist-storage/src/or/or.h	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/src/or/or.h	2007-08-29 21:52:32 UTC (rev 11312)
@@ -1970,6 +1970,8 @@
   int FetchV2HidServDescriptors; /**< and v2 hidden service descriptors? */
   int HidServDirectoryV2; /**< Do we act as hs dir? */
   int MinUptimeHidServDirectoryV2; /**< Accept hs dirs after what time? */
+  int ConsiderAllRoutersAsHidServDirectories; /**< Consider all routers as
+                                               * hidden service directories? */
   int FetchUselessDescriptors; /**< Do we fetch non-running descriptors too? */
   int AllDirActionsPrivate; /**< Should every directory action be sent
                              * through a Tor circuit? */
@@ -2798,9 +2800,8 @@
                                     int decode_hex, int sort_uniq);
 char *directory_dump_request_log(void);
 int router_supports_extrainfo(const char *identity_digest, int is_authority);
-void directory_post_to_hs_dir(const char *service_id,
-                              char desc_ids[][DIGEST_LEN],
-                              smartlist_t *descs, int seconds_valid);
+void directory_post_to_hs_dir(smartlist_t *desc_ids, smartlist_t *descs,
+                              const char *service_id, int seconds_valid);
 void directory_get_from_hs_dir(const char *desc_id, const char *query,
                                const char *secret_cookie);
 void hs_dir_fetch_replicas(routerstatus_t *hs_dir,
@@ -3265,14 +3266,16 @@
 int rend_cache_store_v2_dir(const char *desc);
 int rend_cache_size(void);
 int rend_cache_size_v2_dir(void);
-int rend_encode_v2_descriptors(smartlist_t *desc_strs,
-                               char desc_ids2[][DIGEST_LEN],
+int rend_encode_v2_descriptors(smartlist_t *desc_strs, smartlist_t *desc_ids,
                                rend_service_descriptor_t *desc, time_t now,
-                               const char *secret_cookie, int period);
+                               const char *secret_cookie, uint8_t period);
 void rend_cache_clean_up(void);
 int rend_compute_v2_desc_id(char *desc_id, const char *service_id,
-                         const char *secret_cookie, time_t now, int replica);
+                            const char *secret_cookie, time_t now,
+                            uint8_t replica);
 int hs_dir_is_in_interval(const char *a, const char *b, const char *c);
+void get_descriptor_id_bytes(char *descriptor_id, const char *service_id,
+                             const char *secret_id_part);
 
 /********************************* rendservice.c ***************************/
 
@@ -3643,9 +3646,10 @@
 authority_cert_t *authority_cert_parse_from_string(const char *s,
                                                    const char **end_of_string);
 int rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed,
-                                 char *desc_id, char **intro_points_encrypted,
+                                 char *desc_id,
+                                 char **intro_points_encrypted,
                                  size_t *intro_points_encrypted_size,
-                                 const char **desc, int eat_desc);
+                                 const char **next, const char *desc);
 int rend_decrypt_introduction_points(rend_service_descriptor_t *parsed,
                                  const char *secret_cookie,
                                  char *intro_content, size_t intro_size);

Modified: tor/branches/114-dist-storage/src/or/rendcommon.c
===================================================================
--- tor/branches/114-dist-storage/src/or/rendcommon.c	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/src/or/rendcommon.c	2007-08-29 21:52:32 UTC (rev 11312)
@@ -43,242 +43,288 @@
   tor_free(desc);
 }
 
+/* Compute the descriptor ID for <b>service_id</b> of length DIGEST_LEN / 2
+ * and <b>secret_id_part</b> of length DIGEST_LEN, and write it to
+ * <b>descriptor_id</b> of length DIGEST_LEN. */
+void
+get_descriptor_id_bytes(char *descriptor_id, const char *service_id,
+                        const char *secret_id_part)
+{
+  crypto_digest_env_t *digest = crypto_new_digest_env();
+  crypto_digest_add_bytes(digest, service_id, 10);
+  crypto_digest_add_bytes(digest, secret_id_part, 20);
+  crypto_digest_get_digest(digest, descriptor_id, 20);
+  crypto_free_digest_env(digest);
+}
+
+/* Compute the secret ID part for <b>time_period</b> of length DIGEST_LEN,
+ * <b>secret_cookie</b> of length 16, and <b>replica</b>, and write it to
+ * <b>secret_id_part</b> of length DIGEST_LEN. */
+static void
+get_secret_id_part_bytes(char *secret_id_part, const char *time_period,
+                         const char *secret_cookie, uint8_t replica)
+{
+  crypto_digest_env_t *digest = crypto_new_digest_env();
+  crypto_digest_add_bytes(digest, time_period, 4);
+  crypto_digest_add_bytes(digest, secret_cookie, 16);
+  crypto_digest_add_bytes(digest, (const char *)&replica, 1);
+  crypto_digest_get_digest(digest, secret_id_part, 20);
+  crypto_free_digest_env(digest);
+}
+
+/* Compute the time period bytes for time <b>now</b> plus a potentially
+ * intended <b>deviation</b> of one or more periods, and the first byte of
+ * <b>service_id</b>, and write it to <b>time_period</b> of length 4. */
+static void
+get_time_period_bytes(char *time_period, time_t now, uint8_t deviation,
+                      const char *service_id)
+{
+  uint32_t host_order =
+    (uint32_t) (now + ((uint8_t) *service_id) * TIME_PERIOD_LENGTH / 256)
+    / TIME_PERIOD_LENGTH + deviation;
+  uint32_t network_order = htonl(host_order);
+  set_uint32(time_period, network_order);
+}
+
+/* Compute the time in seconds that a descriptor that is generated
+ * <b>now</b> for <b>service_id</b> will be valid. */
+static uint32_t
+get_seconds_valid(time_t now, const char *service_id)
+{
+  uint32_t result = TIME_PERIOD_LENGTH -
+    (uint32_t) (now + ((uint8_t) *service_id) * TIME_PERIOD_LENGTH / 256)
+    % TIME_PERIOD_LENGTH;
+  return result;
+}
+
 /* Compute the <b>desc_id</b> for a given base32-encoded <b>service_id</b> and
  * base32-encoded <b>secret_cookie</b> at time <b>now</b> for replica number
- * <b>replica</b>.
- */
-/* TODO114 break up functionality and distribute to multiple functions. */
+ * <b>replica</b>. Return 0 for success, -1 otherwise. */
 int
-rend_compute_v2_desc_id(char *desc_id, const char *service_id,
-                     const char *secret_cookie, time_t now, int replica)
+rend_compute_v2_desc_id(char *desc_id, const char *service_id_base32,
+                        const char *secret_cookie_base32, time_t now,
+                        uint8_t replica)
 {
-  uint64_t permanent_id_value = 0;
-  double time_period_part1;
-  double time_period_part2;
-  char time_period_bytes[4];
-  uint32_t time_period;
-  crypto_digest_env_t *digest;
-  char secret_id_part_digest[DIGEST_LEN];
-  char service_id_binary[10];
-  char secret_cookie_binary[16];
-  char replica_byte[1];
-  tor_assert(service_id);
-  tor_assert(strlen(service_id) == REND_SERVICE_ID_LEN);
-  tor_assert(secret_cookie);
-  tor_assert(strlen(secret_cookie) == REND_SECRET_COOKIE_LEN);
-  tor_assert(replica >= 0 && replica < NUMBER_OF_NON_CONSECUTIVE_REPLICAS);
+  char service_id[10];
+  char secret_cookie[16];
+  char time_period[4];
+  char secret_id_part[DIGEST_LEN];
+  if (!service_id_base32 ||
+      strlen(service_id_base32) != REND_SERVICE_ID_LEN) {
+    log_warn(LD_REND, "Could not compute v2 descriptor ID: "
+                      "Illegal service ID: %s", service_id_base32);
+    return -1;
+  }
+  if (!secret_cookie_base32 ||
+      strlen(secret_cookie_base32) != REND_SECRET_COOKIE_LEN) {
+    log_warn(LD_REND, "Could not compute v2 descriptor ID: "
+                      "Illegal secret cookie.");
+    return -1;
+  }
+  if (replica < NUMBER_OF_NON_CONSECUTIVE_REPLICAS) {
+    log_warn(LD_REND, "Could not compute v2 descriptor ID: "
+                      "Replica number out of range: %d", replica);
+    return -1;
+  }
   /* Convert service ID and secret cookie to binary. */
-  base32_decode(service_id_binary, 10, service_id, REND_SERVICE_ID_LEN);
-  base32_decode(secret_cookie_binary, 15, secret_cookie,
-                REND_SECRET_COOKIE_LEN);
-  secret_cookie_binary[15] = 0;
+  base32_decode(service_id, 10, service_id_base32, REND_SERVICE_ID_LEN);
+  base32_decode(secret_cookie, 15,
+                secret_cookie_base32, REND_SECRET_COOKIE_LEN);
+  secret_cookie[15] = 0;
   /* Calculate current time-period. */
-  /* TODO114 make this endian clean. */
-  time_period_part1 = ((double) now) / ((double) TIME_PERIOD_LENGTH);
-  permanent_id_value = ((((uint64_t) service_id_binary[0]) + 256) % 256) << 32;
-  permanent_id_value +=((((uint64_t) service_id_binary[1]) + 256) % 256) << 24;
-  permanent_id_value +=((((uint64_t) service_id_binary[2]) + 256) % 256) << 16;
-  permanent_id_value +=((((uint64_t) service_id_binary[3]) + 256) % 256) << 8;
-  permanent_id_value += (((uint64_t) service_id_binary[4]) + 256) % 256;
-  time_period_part2 = ((double) permanent_id_value) /
-                              ((double) (((uint64_t) 1) << 40));
-  time_period = (uint32_t) (time_period_part1 + time_period_part2);
-  /* Convert time-period to binary. */
-  time_period_bytes[0] = (char) (time_period >> 24);
-  time_period_bytes[1] = (char) (time_period >> 16);
-  time_period_bytes[2] = (char) (time_period >> 8);
-  time_period_bytes[3] = (char) time_period;
-  /* Give this replica a number. */
-  replica_byte[0] = (char) replica;
+  get_time_period_bytes(time_period, now, 0, service_id);
   /* Calculate secret-id-part = h(time-period + cookie + replica). */
-  digest = crypto_new_digest_env();
-  crypto_digest_add_bytes(digest, time_period_bytes, 4);
-  crypto_digest_add_bytes(digest, secret_cookie_binary, 16);
-  crypto_digest_add_bytes(digest, replica_byte, 1);
-  crypto_digest_get_digest(digest, secret_id_part_digest, 20);
-  crypto_free_digest_env(digest);
+  get_secret_id_part_bytes(secret_id_part, time_period, secret_cookie,
+                           replica);
   /* Calculate descriptor ID. */
-  digest = crypto_new_digest_env();
-  crypto_digest_add_bytes(digest, service_id_binary, 10);
-  crypto_digest_add_bytes(digest, secret_id_part_digest, 20);
-  crypto_digest_get_digest(digest, desc_id, 20);
-  crypto_free_digest_env(digest);
+  get_descriptor_id_bytes(desc_id, service_id, secret_id_part);
   return 0;
 }
 
-/** Encode a set of new service descriptors for <b>desc</b> at time <b>now</b>
- * using <b>secret_cookie</b> for period <b>period</b> (e.g. 0 for the current
- * period, 1 for the next period, etc.) and write the ASCII-encoded output to
- * <b>desc_str</b> and the descriptor IDs to <b>desc_ids</b>; return the number
- * of seconds that this descriptor will be found under that <b>desc_id</b> by
- * clients, or -1 if the encoding was not successful. */
-/* TODO114 break up functionality and distribute to multiple functions. */
-int
-rend_encode_v2_descriptors(smartlist_t *desc_strs,
-                           char desc_ids[][DIGEST_LEN],
-                           rend_service_descriptor_t *desc, time_t now,
-                           const char *secret_cookie, int period)
+/* Encode the introduction points in <b>desc</b>, encrypt them with
+ * <b>secret_cookie</b> of length DIGEST_LEN, write them to a newly
+ * allocated string, and write a pointer to it to <b>ipos_base64</b>.
+ * Return 0 for success, -1 otherwise. */
+static int
+rend_encode_v2_intro_points(char **ipos_base64,
+                            rend_service_descriptor_t *desc,
+                            const char *secret_cookie)
 {
-  char *pkey;
-  size_t pkeylen;
-  char published[ISO_TIME_LEN+1];
-  size_t iposlen;
-  char *ipos;
-  int ipowritten;
-  char *ipos_enc;
+  size_t unenc_len;
+  char *unenc;
+  size_t unenc_written = 0;
+  char *enc;
   int enclen;
-  char *ipos_encrypted_base64;
-  int result = 0;
-  size_t written = 0;
-  char desc_digest[DIGEST_LEN];
-  char permanent_id_temp[DIGEST_LEN];
-  char permanent_id[10];
-  double time_period_part1;
-  double time_period_part2;
-  uint64_t permanent_id_value = 0;
-  uint32_t time_period;
-  crypto_digest_env_t *digest;
-  char desc_id_base32[REND_DESC_ID_V2_LEN+1];
-  char secret_id_part_bytes[DIGEST_LEN];
-  char time_period_bytes[4];
-  char secret_id_part[32+1];
-  int seconds_valid;
-  int j, k;
+  int i;
+  /* Assemble unencrypted list of introduction points. */
+  unenc_len = desc->n_intro_points * 1000; /* too long, but ok. */
+  unenc = tor_malloc_zero(unenc_len);
+  for (i = 0; i < desc->n_intro_points; i++) {
+    char id_base32[32 + 1];
+    char *onion_key;
+    size_t onion_key_len;
+    char *service_key;
+    size_t service_key_len;
+    int res;
+    /* Obtain extend info with introduction point details. */
+    extend_info_t *info = desc->intro_point_extend_info[i];
+    /* Encode introduction point ID. */
+    base32_encode(id_base32, 32 + 1, info->identity_digest, DIGEST_LEN);
+    /* Encode onion key. */
+    if (crypto_pk_write_public_key_to_string(info->onion_key, &onion_key,
+                                             &onion_key_len) < 0) {
+      log_warn(LD_REND, "Could not write onion key.");
+      continue;
+    }
+    /* Encode service key.
+     * TODO114 replace Bob's public key with newly generated service key */
+    if (crypto_pk_write_public_key_to_string(desc->pk, &service_key,
+                                             &service_key_len) < 0) {
+      log_warn(LD_REND, "Could not write service key.");
+      continue;
+    }
+    /* Assemble everything for this introduction point. */
+    res = tor_snprintf(unenc + unenc_written, unenc_len - unenc_written,
+                         "introduction-point %s\n"
+                         "ip-address %s\n"
+                         "onion-port %d\n"
+                         "onion-key\n%s"
+                         "service-key\n%s",
+                       id_base32,
+                       tor_dup_addr(info->addr),
+                       info->port,
+                       onion_key,
+                       service_key);
+    if (res < 0) {
+      log_warn(LD_REND, "Not enough space for writing introduction point "
+                        "string.");
+      return -1;
+    }
+    /* Update total number of written bytes for unencrypted intro points. */
+    unenc_written += res;
+    /* Free memory. */
+    tor_free(onion_key);
+    tor_free(service_key);
+  }
+  /* Finalize unencrypted introduction points. */
+  if (unenc_len < unenc_written + 2) {
+    log_warn(LD_REND, "Not enough space for finalizing introduction point "
+                      "string.");
+    return -1;
+  }
+  unenc[unenc_written++] = '\n';
+  unenc[unenc_written++] = 0;
+  /* Encrypt introduction points. */
+  enc = tor_malloc_zero(unenc_written + 32);
+  enclen = crypto_cipher_encrypt_cbc(secret_cookie,
+                                     enc, unenc_written + 32,
+                                     unenc, unenc_written);
+  if (enclen < 0) {
+    log_warn(LD_REND, "Could not encrypt introduction point string.");
+    return -1;
+  }
+  /* Free memory for unencrypted introduction points. */
+  tor_free(unenc);
+  /* Base64-encode introduction points. */
+  *ipos_base64 = tor_malloc_zero(enclen * 2);
+  if (base64_encode(*ipos_base64, enclen * 2, enc, enclen) < 0) {
+    log_warn(LD_REND, "Could not encode introduction point string to "
+                      "base64.");
+    return -1;
+  }
+  return 0;
+}
+
+/** Attempt to parse the given <b>desc_str</b> and return 0 if this
+ * succees, -1 otherwise. */
+static int
+rend_desc_v2_is_parsable(const char *desc_str)
+{
   rend_service_descriptor_t *test_parsed;
   char test_desc_id[DIGEST_LEN];
   char *test_intro_content;
   size_t test_intro_size;
-  char *desc_str;
-  char *desc_id;
-  char secret_cookie_bin[16];
-  char replica_byte[1];
-  size_t desc_len;
-  tor_assert(desc);
-  tor_assert(secret_cookie);
-  tor_assert(strlen(secret_cookie) == REND_SECRET_COOKIE_LEN);
+  const char *test_next;
+  int res = rend_parse_v2_service_descriptor(&test_parsed, test_desc_id,
+                                         &test_intro_content,
+                                         &test_intro_size,
+                                         &test_next, desc_str);
+  tor_free(test_parsed);
+  tor_free(test_intro_content);
+  return res;
+}
+
+/** Encode a set of new service descriptors for <b>desc</b> at time
+ * <b>now</b> using <b>secret_cookie_base32</b> and <b>period</b> (e.g. 0
+ * for the current period, 1 for the next period, etc.), write the
+ * ASCII-encoded outputs to newly allocated strings and add them to the
+ * existing <b>desc_strs</b>, and write the descriptor IDs to newly
+ * allocated strings and add them to the existing <b>desc_ids</b>; return
+ * the number of seconds that the descriptors will be found under those
+ * <b>desc_ids</b> by clients, or -1 if the encoding was not successful. */
+int
+rend_encode_v2_descriptors(smartlist_t *desc_strs, smartlist_t *desc_ids,
+                           rend_service_descriptor_t *desc, time_t now,
+                           const char *secret_cookie_base32, uint8_t period)
+{
+  char service_id[DIGEST_LEN];
+  char secret_cookie[16];
+  char time_period[4];
+  char *ipos_base64 = NULL;
+  int k;
+  uint32_t seconds_valid;
+  if (!desc) {
+    log_warn(LD_REND, "Could not encode v2 descriptor: No desc given.");
+    return -1;
+  }
+  if (!secret_cookie_base32 ||
+      strlen(secret_cookie_base32) != REND_SECRET_COOKIE_LEN) {
+    log_warn(LD_REND, "Could not encode v2 descriptor: "
+                      "Illegal secret cookie.");
+    return -1;
+  }
+  /* Obtain service_id from public key. */
+  crypto_pk_get_digest(desc->pk, service_id);
+  /* Convert secret_cookie to binary. */
+  base32_decode(secret_cookie, sizeof(secret_cookie),
+                secret_cookie_base32, strlen(secret_cookie_base32));
+  secret_cookie[15] = 0;
+  /* Calculate current time-period. */
+  get_time_period_bytes(time_period, now, period, service_id);
+  /* Determine how many seconds the descriptor will be valid. */
+  seconds_valid = get_seconds_valid(now, service_id);
+  /* Encode and encrypt introduction points. */
+  rend_encode_v2_intro_points(&ipos_base64, desc, secret_cookie);
+  /* Encode NUMBER_OF_NON_CONSECUTIVE_REPLICAS descriptors. */
   for (k = 0; k < NUMBER_OF_NON_CONSECUTIVE_REPLICAS; k++) {
-    desc_id = *(desc_ids + k);
-    /* Obtain permanent-id from public key. */
-    crypto_pk_get_digest(desc->pk, permanent_id_temp);
-    memcpy(permanent_id, permanent_id_temp, 10);
-    /* Convert secret_cookie to binary. */
-    base32_decode(secret_cookie_bin, sizeof(secret_cookie_bin), secret_cookie,
-                  strlen(secret_cookie));
-    secret_cookie_bin[15] = 0;
-    /* Calculate current time-period. */
-    /* TODO114 make this endian clean. */
-    time_period_part1 = ((double) now) / ((double) TIME_PERIOD_LENGTH);
-    permanent_id_value = ((((uint64_t) permanent_id[0]) + 256) % 256) << 32;
-    permanent_id_value +=((((uint64_t) permanent_id[1]) + 256) % 256) << 24;
-    permanent_id_value +=((((uint64_t) permanent_id[2]) + 256) % 256) << 16;
-    permanent_id_value +=((((uint64_t) permanent_id[3]) + 256) % 256) << 8;
-    permanent_id_value += (((uint64_t) permanent_id[4]) + 256) % 256;
-    time_period_part2 = ((double) permanent_id_value) /
-                                ((double) (((uint64_t) 1) << 40));
-    time_period = (uint32_t) (time_period_part1 + time_period_part2);
-    time_period += period;
-    seconds_valid = TIME_PERIOD_LENGTH
-                    - (uint32_t) (((time_period_part1 + time_period_part2) -
-                                   (double) time_period)
-                                  * TIME_PERIOD_LENGTH);
-    /* Convert time-period to binary. */
-    time_period_bytes[0] = (char) ((time_period) >> 24);
-    time_period_bytes[1] = (char) ((time_period) >> 16);
-    time_period_bytes[2] = (char) ((time_period) >> 8);
-    time_period_bytes[3] = (char) (time_period);
-    /* Give this replica a number. */
-    replica_byte[0] = (char) k;
+    char secret_id_part[DIGEST_LEN];
+    char secret_id_part_base32[32+1];
+    char *desc_id;
+    char desc_id_base32[REND_DESC_ID_V2_LEN+1];
+    char *permanent_key;
+    size_t permanent_key_len;
+    char published[ISO_TIME_LEN+1];
+    size_t desc_len;
+    char *desc_str;
+    int result = 0;
+    size_t written = 0;
+    char desc_digest[DIGEST_LEN];
     /* Calculate secret-id-part = h(time-period + cookie + replica). */
-    digest = crypto_new_digest_env();
-    crypto_digest_add_bytes(digest, time_period_bytes, 4);
-    crypto_digest_add_bytes(digest, secret_cookie_bin, 16);
-    crypto_digest_add_bytes(digest, replica_byte, 1);
-    crypto_digest_get_digest(digest, secret_id_part_bytes, 20);
-    crypto_free_digest_env(digest);
-    base32_encode(secret_id_part, 32 + 1, secret_id_part_bytes, 20);
+    get_secret_id_part_bytes(secret_id_part, time_period, secret_cookie, k);
+    base32_encode(secret_id_part_base32, 32 + 1,
+                  secret_id_part, DIGEST_LEN);
     /* Calculate descriptor ID. */
-    digest = crypto_new_digest_env();
-    crypto_digest_add_bytes(digest, permanent_id, 10);
-    crypto_digest_add_bytes(digest, secret_id_part_bytes, 20);
-    crypto_digest_get_digest(digest, desc_id, 20);
-    crypto_free_digest_env(digest);
+    desc_id = tor_malloc_zero(DIGEST_LEN);
+    get_descriptor_id_bytes(desc_id, service_id, secret_id_part);
     base32_encode(desc_id_base32, 32 + 1, desc_id, 20);
     /* PEM-encode the public key */
-    if (crypto_pk_write_public_key_to_string(desc->pk, &pkey, &pkeylen) < 0) {
-      log_warn(LD_REND, "Could not write public key to string.");
+    if (crypto_pk_write_public_key_to_string(desc->pk, &permanent_key,
+                                             &permanent_key_len) < 0) {
+      log_warn(LD_BUG, "Could not write public key to string.");
       return -1;
     }
     /* Encode timestamp. */
     format_iso_time(published, desc->timestamp);
-    /* Assemble unencrypted list of introduction points. */
-    iposlen = desc->n_intro_points * 1000; /* too long, but ok. */
-    ipos = tor_malloc_zero(iposlen);
-    ipowritten = 0;
-    for (j=0; j < desc->n_intro_points; ++j) {
-      char id_base32[32 + 1];
-      char *okey;
-      size_t okeylen;
-      char *skey;
-      size_t skeylen;
-      int res;
-      /* Obtain extend info with introduction point details. */
-      extend_info_t *info = desc->intro_point_extend_info[j];
-      /* Encode introduction point ID. */
-      base32_encode(id_base32, 32 + 1, info->identity_digest, DIGEST_LEN);
-      /* Encode onion key. */
-      if (crypto_pk_write_public_key_to_string(info->onion_key, &okey,
-                                               &okeylen) < 0) {
-        log_warn(LD_REND, "Could not write onion key.");
-        continue;
-      }
-      /* Encode service key.
-       * TODO114 replace Bob's public key by newly generated service key */
-      if (crypto_pk_write_public_key_to_string(desc->pk, &skey,
-                                               &skeylen) < 0) {
-        log_warn(LD_REND, "Could not write service key.");
-        continue;
-      }
-      /* Assemble everything for this introduction point. */
-      res = tor_snprintf(ipos+ipowritten, iposlen-ipowritten,
-                           "introduction-point %s\n"
-                           "ip-address %u.%u.%u.%u\n"
-                           "onion-port %d\n"
-                           "onion-key\n%s"
-                           "service-key\n%s",
-                         id_base32,
-                         (info->addr >> 24) % 256,
-                         (info->addr >> 16) % 256,
-                         (info->addr >> 8) % 256,
-                         info->addr % 256,
-                         info->port,
-                         okey,
-                         skey);
-      if (res < 0) {
-        log_warn(LD_BUG, "Not enough space for writing ipo.");
-        return -1;
-      }
-      /* Update total number of written bytes for unencrypted intro points. */
-      ipowritten += res;
-      /* Free memory. */
-      tor_free(okey);
-      tor_free(skey);
-    }
-    /* Finalize unencrypted introduction points. */
-    ipos[ipowritten++] = '\n';
-    ipos[ipowritten++] = 0;
-    /* Encrypt introduction points. */
-    ipos_enc = tor_malloc_zero(ipowritten + 32);
-    enclen = crypto_cipher_encrypt_cbc(secret_cookie_bin, ipos_enc,
-                                       ipowritten + 32, ipos, ipowritten);
-    /* Free memory for unencrypted introduction points. */
-    tor_free(ipos);
-    /* Base64-encode introduction points. */
-    ipos_encrypted_base64 = tor_malloc_zero(ipowritten * 2);
-    if (base64_encode(ipos_encrypted_base64, ipowritten * 2, ipos_enc,
-                      enclen) < 0) {
-      log_warn(LD_REND, "Could not encode ipos to base64.");
-      return -1;
-    }
     /* Assemble complete descriptor. */
     desc_len = 2000 + desc->n_intro_points * 1000; /* far too long, but ok. */
     desc_str = tor_malloc_zero(desc_len);
@@ -289,16 +335,17 @@
              "secret-id-part %s\n"
              "publication-time %s\n"
              "protocol-versions %d\n"
-             "introduction-points\n-----BEGIN AES ENCRYPTED MESSAGE-----\n%s"
+             "introduction-points\n"
+             "-----BEGIN AES ENCRYPTED MESSAGE-----\n%s"
              "-----END AES ENCRYPTED MESSAGE-----\n",
         desc_id_base32,
-        pkey,
-        secret_id_part,
+        permanent_key,
+        secret_id_part_base32,
         published,
         desc->protocols,
-        ipos_encrypted_base64);
+        ipos_base64);
     if (result < 0) {
-      log_warn(LD_REND, "Descriptor ran out of room.");
+      log_warn(LD_BUG, "Descriptor ran out of room.");
       return -1;
     }
     written = result;
@@ -310,7 +357,8 @@
         log_warn(LD_BUG, "could not create digest.");
       return -1;
     }
-    if (router_append_dirobj_signature(desc_str + written, desc_len - written,
+    if (router_append_dirobj_signature(desc_str + written,
+                                       desc_len - written,
                                        desc_digest, desc->pk) < 0) {
       log_warn(LD_BUG, "Couldn't sign desc.");
       return -1;
@@ -322,20 +370,19 @@
     }
     desc_str[written++] = '\n';
     desc_str[written++] = 0;
-    /* Free memory. */
-    tor_free(pkey);
     /* Check if we can parse our own descriptor. */
-    if (rend_parse_v2_service_descriptor(&test_parsed, test_desc_id,
-                                         &test_intro_content, &test_intro_size,
-                                         (const char **)(&desc_str), 0) < 0) {
-      log_warn(LD_REND, "Could not parse my own descriptor.");
+    if (rend_desc_v2_is_parsable(desc_str)) {
+      log_warn(LD_BUG, "Could not parse my own descriptor: %s",
+               desc_str);
       return -1;
     }
     smartlist_add(desc_strs, desc_str);
-    tor_free(test_parsed);
-    tor_free(test_intro_content);
+    smartlist_add(desc_ids, desc_id);
+    /* Free memory. */
+    tor_free(permanent_key);
   }
-
+  /* Free memory. */
+  tor_free(ipos_base64);
   log_info(LD_REND, "Successfully encoded a v2 descriptor and "
                     "confirmed that it is parsable.");
   return seconds_valid;
@@ -874,8 +921,9 @@
   char *intro_content;
   size_t intro_size;
   char desc_id_base32[REND_DESC_ID_V2_LEN+1];
-  int number_parsed = 0;
-  const char **current_desc = (const char **)(&desc);
+  int number_stored = 0;
+  const char *current_desc = desc;
+  const char *next_desc;
   rend_cache_entry_t *e;
   time_t now = time(NULL);
   tor_assert(rend_cache_v2_dir);
@@ -887,7 +935,8 @@
     return -1;
   }
   while (rend_parse_v2_service_descriptor(&parsed, desc_id, &intro_content,
-                                          &intro_size, current_desc, 0) >= 0) {
+                                          &intro_size, &next_desc,
+                                          current_desc) >= 0) {
     tor_assert(parsed);
     /* We don't care about the introduction points. */
     tor_free(intro_content);
@@ -949,16 +998,14 @@
     e->len = strlen(desc);
     log_info(LD_REND, "Successfully stored service descriptor with desc ID "
                        "'%s' and len %d.", desc_id_base32, strlen(desc));
-    number_parsed++; // TODO114 rename to number_stored
+    number_stored++;
  skip:
-    // TODO114 don't need to parse again, just skip to next descriptor, if
-    // available!
-    rend_parse_v2_service_descriptor(&parsed, desc_id, &intro_content,
-                                          &intro_size, current_desc, 1);
+    /* advance to next descriptor, if available. */
+    current_desc = next_desc;
   }
   log_info(LD_REND, "Parsed and added %d descriptor%s.",
-           number_parsed, number_parsed > 1 ? "s" : "");
-  return number_parsed;
+           number_stored, number_stored != 1 ? "s" : "");
+  return number_stored;
 }
 
 /** Parse the v2 service descriptor in <b>desc</b>, decrypt the included list
@@ -978,7 +1025,8 @@
   char desc_id[DIGEST_LEN];
   char *intro_content = NULL;
   size_t intro_size;
-  const char **first_desc = (const char **)(&desc);
+  //const char **first_desc = (const char **)(&desc);
+  const char *next_desc;
   time_t now = time(NULL);
   char key[REND_SERVICE_ID_LEN+2];
   char service_id[REND_SERVICE_ID_LEN+1];
@@ -989,7 +1037,8 @@
   tor_assert(strlen(secret_cookie) == REND_SECRET_COOKIE_LEN);
   /* Parse the descriptor. */
   if (rend_parse_v2_service_descriptor(&parsed, desc_id, &intro_content,
-                                       &intro_size, first_desc, 0) < 0) {
+                                       &intro_size, &next_desc,
+                                       desc) < 0) {
     log_warn(LD_REND, "Could not parse descriptor.");
     return -1;
   }

Modified: tor/branches/114-dist-storage/src/or/rendservice.c
===================================================================
--- tor/branches/114-dist-storage/src/or/rendservice.c	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/src/or/rendservice.c	2007-08-29 21:52:32 UTC (rev 11312)
@@ -984,7 +984,7 @@
   return NULL;
 }
 
-/** Encode and sign up-to-date v0/1 and/or v2 service descriptors for
+/** Encode and sign up-to-date v0 and/or v2 service descriptors for
  * <b>service</b>, and upload it to all the dirservers/to the responsible
  * hidden service directories.
  */
@@ -994,6 +994,7 @@
   time_t now = time(NULL);
   int rendpostperiod;
   char serviceid[REND_SERVICE_ID_LEN+1];
+  int uploaded = 0;
 
   /* Update the descriptor. */
   rend_service_update_descriptor(service);
@@ -1022,13 +1023,14 @@
                                HIDSERV_AUTHORITY, desc, desc_len, 0);
     tor_free(desc);
     service->next_upload_time = now + rendpostperiod;
+    uploaded = 1;
   }
 
   /* Upload v2 descriptor? */
   if (get_options()->PublishV2HidServDescriptors && have_enough_hs_dirs()) {
     int seconds_valid;
     smartlist_t *desc_strs = smartlist_create();
-    char desc_ids[NUMBER_OF_NON_CONSECUTIVE_REPLICAS][DIGEST_LEN];
+    smartlist_t *desc_ids = smartlist_create();
     int i;
     /* Encode the current descriptor. */
     seconds_valid = rend_encode_v2_descriptors(desc_strs, desc_ids,
@@ -1041,30 +1043,43 @@
     }
     /* Post the current descriptors to the hidden service directories. */
     rend_get_service_id(service->desc->pk, serviceid);
-    directory_post_to_hs_dir(serviceid, desc_ids, desc_strs, seconds_valid);
+    directory_post_to_hs_dir(desc_ids, desc_strs, serviceid, seconds_valid);
     /* Free memory for descriptors. */
-    for (i = 0; i < NUMBER_OF_NON_CONSECUTIVE_REPLICAS; i++)
+    for (i = 0; i < NUMBER_OF_NON_CONSECUTIVE_REPLICAS; i++) {
       tor_free(desc_strs->list[i]);
+      tor_free(desc_ids->list[i]);
+    }
     smartlist_free(desc_strs);
+    smartlist_free(desc_ids);
     /* Post also the next descriptors, if necessary. */
     if (seconds_valid < TIME_PERIOD_TWO_V2_DESCS) {
       desc_strs = smartlist_create();
+      desc_ids = smartlist_create();
       seconds_valid = rend_encode_v2_descriptors(desc_strs, desc_ids,
                                                  service->desc, now,
                                                  service->secret_cookie, 1);
-      directory_post_to_hs_dir(serviceid, desc_ids, desc_strs, seconds_valid);
-      /* Free memory for descriptors. */
-      for (i = 0; i < NUMBER_OF_NON_CONSECUTIVE_REPLICAS; i++)
-        tor_free(desc_strs->list[i]);
-      smartlist_free(desc_strs);
+      directory_post_to_hs_dir(desc_ids, desc_strs, serviceid, seconds_valid);
     }
+    /* Free memory for descriptors. */
+    for (i = 0; i < NUMBER_OF_NON_CONSECUTIVE_REPLICAS; i++) {
+      tor_free(desc_strs->list[i]);
+      tor_free(desc_ids->list[i]);
+    }
+    smartlist_free(desc_strs);
+    smartlist_free(desc_ids);
+    /* Update next upload time. */
     if (seconds_valid - TIME_PERIOD_TWO_V2_DESCS < rendpostperiod)
       service->next_upload_time = now + seconds_valid -
                                   TIME_PERIOD_TWO_V2_DESCS + 1;
     else
       service->next_upload_time = now + rendpostperiod;
+    uploaded = 1;
   }
 
+  /* If not uploaded, try again in one minute. */
+  if (!uploaded)
+    service->next_upload_time = now + 60;
+
   /* Unmark dirty flag of this service. */
   service->desc_is_dirty = 0;
 }

Modified: tor/branches/114-dist-storage/src/or/routerlist.c
===================================================================
--- tor/branches/114-dist-storage/src/or/routerlist.c	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/src/or/routerlist.c	2007-08-29 21:52:32 UTC (rev 11312)
@@ -5584,14 +5584,10 @@
   return (routerlist->hs_dirs->num_used > NUMBER_OF_CONSECUTIVE_REPLICAS);
 }
 
-/** Determine the routers that are responsible for <b>id</b> (binary) and
- * return those routers' routerstatus_t. if we don't have enough hidden
- * service directories, return -1, else 0.
- *
- * id is binary
- *
- * hs_dirs is an array with NUMBER_OF_CONSECUTIVE_REPLICAS elements
- */
+/** Determine the NUMBER_OF_CONSECUTIVE_REPLICAS routers that are
+ * responsible for <b>id</b> (binary) and add pointers to those routers'
+ * routerstatus_t to <b>hs_dirs</b>. If we don't have enough hidden service
+ * directories, return -1, else 0. */
 int
 get_responsible_hs_dirs(const char *id, smartlist_t *hs_dirs)
 {
@@ -5611,7 +5607,19 @@
   for (i = 0; i < NUMBER_OF_CONSECUTIVE_REPLICAS; i++) {
     digest = next_hs_dir(digest);
     router = router_get_combined_status_by_digest(digest);
+    if (!router) {
+      log_warn(LD_REND, "Did not find combined status for router. "
+                        "Skipping router.");
+      i--;
+      continue;
+    }
     status = &(router->status);
+    if (!status) {
+      log_warn(LD_REND, "Could not determine router status. "
+                        "Skipping router.");
+      i--;
+      continue;
+    }
     smartlist_add(hs_dirs, status);
   }
   return 0;

Modified: tor/branches/114-dist-storage/src/or/routerparse.c
===================================================================
--- tor/branches/114-dist-storage/src/or/routerparse.c	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/src/or/routerparse.c	2007-08-29 21:52:32 UTC (rev 11312)
@@ -2981,20 +2981,21 @@
     smartlist_uniq(versions, _compare_tor_version_str_ptr, NULL);
 }
 
-/** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>, write
- * the parsed descriptor to (the newly allocated) <b>parsed</b>, the binary
- * descriptor ID to <b>desc_id</b>, the encrypted introduction points to (the
- * newly allocated) <b>intro_points_encrypted</b>, their encrypted size to
- * <b>intro_points_encrypted_size</b>, and advance to the possibly next
- * descriptor if <b>eat_desc</b> is 1; return 0 for success (including
- * descriptor validation) or -1 for failure.
+/** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
+ * write the parsed descriptor to the newly allocated <b>parsed</b>, the
+ * binary descriptor ID of length DIGEST_LEN to <b>desc_id</b>, the
+ * encrypted introduction points to the newly allocated
+ * <b>intro_points_encrypted</b>, their encrypted size to
+ * <b>intro_points_encrypted_size</b>, and a pointer to the possibly next
+ * descriptor to <b>next</b>; return 0 for success (including validation)
+ * and -1 for failure.
  */
-/* TODO114 break up functionality and distribute to multiple functions. */
 int
 rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed,
-                                 char *desc_id, char **intro_points_encrypted,
+                                 char *desc_id,
+                                 char **intro_points_encrypted,
                                  size_t *intro_points_encrypted_size,
-                                 const char **desc, int eat_desc)
+                                 const char **next, const char *desc)
 {
   rend_service_descriptor_t *result =
                             tor_malloc_zero(sizeof(rend_service_descriptor_t));
@@ -3006,34 +3007,33 @@
   int protocols;
   char public_key_hash[DIGEST_LEN];
   char test_desc_id[DIGEST_LEN];
-  crypto_digest_env_t *digest;
-  tor_assert(*desc);
+  tor_assert(desc);
   /* Check if desc starts correctly. */
-  if (strncmp(*desc, "rendezvous-service-descriptor ",
+  if (strncmp(desc, "rendezvous-service-descriptor ",
               strlen("rendezvous-service-descriptor "))) {
     log_info(LD_REND, "Descriptor does not start correctly.");
     goto err;
   }
   /* Compute descriptor hash for later validation. */
-  if (router_get_hash_impl(*desc, desc_hash, "rendezvous-service-descriptor ",
+  if (router_get_hash_impl(desc, desc_hash,
+                           "rendezvous-service-descriptor ",
                            "\nsignature", '\n') < 0) {
     log_warn(LD_REND, "Couldn't compute descriptor hash.");
     goto err;
   }
   /* Determine end of string. */
-  eos = strstr(*desc, "\nrendezvous-service-descriptor ");
+  eos = strstr(desc, "\nrendezvous-service-descriptor ");
   if (!eos)
-    eos = *desc + strlen(*desc);
+    eos = desc + strlen(desc);
   else
     eos = eos + 1;
   /* Tokenize descriptor. */
-  if (tokenize_string(*desc, eos, tokens, desc_token_table)) {
+  if (tokenize_string(desc, eos, tokens, desc_token_table)) {
     log_warn(LD_REND, "Error tokenizing descriptor.");
     goto err;
   }
-  /* If requested, set desc to next descriptor, if available. */
-  if (eat_desc)
-    *desc = eos;
+  /* Set next to next descriptor, if available. */
+  *next = eos;
   /* Check min allowed length of token list. */
   if (smartlist_len(tokens) < 8) {
     log_warn(LD_REND, "Impossibly short descriptor.");
@@ -3109,11 +3109,7 @@
     goto err;
   /* Verify that descriptor ID belongs to public key and secret ID part. */
   crypto_pk_get_digest(result->pk, public_key_hash);
-  digest = crypto_new_digest_env();
-  crypto_digest_add_bytes(digest, public_key_hash, 10);
-  crypto_digest_add_bytes(digest, secret_id_part, 20);
-  crypto_digest_get_digest(digest, test_desc_id, 20);
-  crypto_free_digest_env(digest);
+  get_descriptor_id_bytes(test_desc_id, public_key_hash, secret_id_part);
   if (memcmp(desc_id, test_desc_id, DIGEST_LEN)) {
     log_warn(LD_REND, "Parsed descriptor ID does not match "
              "computed descriptor ID.");

Modified: tor/branches/114-dist-storage/src/or/test.c
===================================================================
--- tor/branches/114-dist-storage/src/or/test.c	2007-08-29 21:36:34 UTC (rev 11311)
+++ tor/branches/114-dist-storage/src/or/test.c	2007-08-29 21:52:32 UTC (rev 11312)
@@ -3182,8 +3182,9 @@
 test_v2_rend_desc(void)
 {
   rend_service_descriptor_t *generated, *parsed;
+  const char *next_desc;
   smartlist_t *desc_strs = smartlist_create();
-  char desc_ids[NUMBER_OF_NON_CONSECUTIVE_REPLICAS][DIGEST_LEN];
+  smartlist_t *desc_ids = smartlist_create();
   char parsed_desc_id[DIGEST_LEN];
   crypto_pk_env_t *pk1;
   time_t now;
@@ -3226,8 +3227,8 @@
   test_assert(rend_parse_v2_service_descriptor(&parsed, parsed_desc_id,
                                                &intro_points_encrypted,
                                                &intro_points_size,
-                                          (const char **)&desc_strs->list[0],
-                                               0) == 0);
+                                               &next_desc,
+                                               desc_strs->list[0]) == 0);
   test_assert(parsed);
   test_assert(rend_decrypt_introduction_points(parsed, secret_cookie_base32,
                                                intro_points_encrypted,



More information about the tor-commits mailing list