瀏覽代碼

if the rend desc cache entry was fetched more than 15 mins ago,
then try to fetch a new one. but if the new fetch fails, use the
old one.


svn:r1540

Roger Dingledine 20 年之前
父節點
當前提交
e79a578fec
共有 5 個文件被更改,包括 31 次插入31 次删除
  1. 4 1
      src/or/connection.c
  2. 4 3
      src/or/connection_edge.c
  3. 6 4
      src/or/directory.c
  4. 5 4
      src/or/or.h
  5. 12 19
      src/or/rendclient.c

+ 4 - 1
src/or/connection.c

@@ -178,9 +178,12 @@ _connection_mark_for_close(connection_t *conn, char reason)
     case CONN_TYPE_AP_LISTENER:
     case CONN_TYPE_DIR_LISTENER:
     case CONN_TYPE_CPUWORKER:
-    case CONN_TYPE_DIR:
       /* No special processing needed. */
       break;
+    case CONN_TYPE_DIR:
+      if(conn->purpose == DIR_PURPOSE_FETCH_RENDDESC)
+        rend_client_desc_fetched(conn->rend_query, 0);
+      break;
     case CONN_TYPE_OR:
       /* Remember why we're closing this connection. */
       if (conn->state != OR_CONN_STATE_OPEN) {

+ 4 - 3
src/or/connection_edge.c

@@ -728,13 +728,14 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
     return connection_ap_handshake_attach_circuit(conn);
   } else {
     /* it's a hidden-service request */
-    const char *descp;
-    int desc_len;
+    rend_cache_entry_t *entry;
 
     strcpy(conn->rend_query, socks->address); /* this strcpy is safe -RD */
     log_fn(LOG_INFO,"Got a hidden service request for ID '%s'", conn->rend_query);
     /* see if we already have it cached */
-    if (rend_cache_lookup_desc(conn->rend_query, &descp, &desc_len) == 1) {
+    if (rend_cache_lookup_entry(conn->rend_query, &entry) == 1 &&
+#define NUM_SECONDS_BEFORE_REFETCH (60*15)
+      entry->received + NUM_SECONDS_BEFORE_REFETCH < time(NULL)) {
       conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
       return connection_ap_handshake_attach_circuit(conn);
     } else {

+ 6 - 4
src/or/directory.c

@@ -275,16 +275,18 @@ int connection_dir_process_inbuf(connection_t *conn) {
       switch(status_code) {
         case 200:
           if(rend_cache_store(body, body_len) < 0) {
-            log_fn(LOG_WARN,"Failed to store rendezvous descriptor. Abandoning stream.");
-            /* alice's ap_stream is just going to have to time out. */
+            log_fn(LOG_WARN,"Failed to store rendezvous descriptor.");
+            /* alice's ap_stream will notice when connection_mark_for_close
+             * cleans it up */
           } else {
             /* success. notify pending connections about this. */
             rend_client_desc_fetched(conn->rend_query, 1);
+            conn->purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
           }
           break;
         case 404:
-          /* not there. also notify pending connections. */
-          rend_client_desc_fetched(conn->rend_query, 0);
+          /* not there. pending connections will be notified when
+           * connection_mark_for_close cleans it up. */
           break;
         case 400:
           log_fn(LOG_WARN,"http status 400 (bad request). Dirserver didn't like our rendezvous query?");

+ 5 - 4
src/or/or.h

@@ -176,10 +176,11 @@
 #define _DIR_PURPOSE_MIN 1
 #define DIR_PURPOSE_FETCH_DIR 1
 #define DIR_PURPOSE_FETCH_RENDDESC 2
-#define DIR_PURPOSE_UPLOAD_DIR 3
-#define DIR_PURPOSE_UPLOAD_RENDDESC 4
-#define DIR_PURPOSE_SERVER 5
-#define _DIR_PURPOSE_MAX 5
+#define DIR_PURPOSE_HAS_FETCHED_RENDDESC 3
+#define DIR_PURPOSE_UPLOAD_DIR 4
+#define DIR_PURPOSE_UPLOAD_RENDDESC 5
+#define DIR_PURPOSE_SERVER 6
+#define _DIR_PURPOSE_MAX 6
 
 #define CIRCUIT_STATE_BUILDING 0 /* I'm the OP, still haven't done all my handshakes */
 #define CIRCUIT_STATE_ONIONSKIN_PENDING 1 /* waiting to process the onionskin */

+ 12 - 19
src/or/rendclient.c

@@ -46,31 +46,24 @@ rend_client_send_establish_rendezvous(circuit_t *circ)
  */
 int
 rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc) {
-  const char *descp;
-  int desc_len, payload_len, r;
+  int payload_len, r;
   char payload[RELAY_PAYLOAD_SIZE];
   char tmp[(MAX_NICKNAME_LEN+1)+REND_COOKIE_LEN+DH_KEY_LEN];
-  rend_service_descriptor_t *parsed=NULL;
+  rend_cache_entry_t *entry;
   crypt_path_t *cpath;
 
   assert(introcirc->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
   assert(rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY);
   assert(!rend_cmp_service_ids(introcirc->rend_query, rendcirc->rend_query));
 
-  if(rend_cache_lookup_desc(introcirc->rend_query, &descp, &desc_len) < 1) {
+  if(rend_cache_lookup_entry(introcirc->rend_query, &entry) < 1) {
     log_fn(LOG_WARN,"query '%s' didn't have valid rend desc in cache. Failing.",
            introcirc->rend_query);
     goto err;
   }
 
-  parsed = rend_parse_service_descriptor(descp,desc_len);
-  if (!parsed) {
-    log_fn(LOG_WARN,"Couldn't parse service descriptor");
-    goto err;
-  }
-
   /* first 20 bytes of payload are the hash of bob's pk */
-  if (crypto_pk_get_digest(parsed->pk, payload)<0) {
+  if (crypto_pk_get_digest(entry->parsed->pk, payload)<0) {
     log_fn(LOG_WARN, "Couldn't hash public key.");
     goto err;
   }
@@ -97,7 +90,7 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc) {
     goto err;
   }
 
-  r = crypto_pk_public_hybrid_encrypt(parsed->pk, tmp,
+  r = crypto_pk_public_hybrid_encrypt(entry->parsed->pk, tmp,
                            MAX_NICKNAME_LEN+1+REND_COOKIE_LEN+DH_KEY_LEN,
                                       payload+DIGEST_LEN,
                                       PK_PKCS1_OAEP_PADDING, 0);
@@ -108,8 +101,6 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc) {
 
   payload_len = DIGEST_LEN + r;
 
-  rend_service_descriptor_free(parsed);
-
   if (connection_edge_send_command(NULL, introcirc,
                                    RELAY_COMMAND_INTRODUCE1,
                                    payload, payload_len,
@@ -124,8 +115,6 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc) {
 
   return 0;
 err:
-  if(parsed)
-    rend_service_descriptor_free(parsed);
   circuit_mark_for_close(introcirc);
   circuit_mark_for_close(rendcirc);
   return -1;
@@ -239,6 +228,7 @@ void rend_client_desc_fetched(char *query, int success) {
   connection_t **carray;
   connection_t *conn;
   int n, i;
+  rend_cache_entry_t *entry;
 
   get_connection_array(&carray, &n);
 
@@ -250,7 +240,10 @@ void rend_client_desc_fetched(char *query, int success) {
     if (rend_cmp_service_ids(conn->rend_query, query))
       continue;
     /* great, this guy was waiting */
-    if(success) {
+    if(success ||
+       rend_cache_lookup_entry(conn->rend_query, &entry) == 1) {
+      /* either this fetch worked, or it failed but there was a
+       * valid entry from before which we should reuse */
       log_fn(LOG_INFO,"Rend desc retrieved. Launching circuits.");
       conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
       if (connection_ap_handshake_attach_circuit(conn) < 0) {
@@ -258,8 +251,8 @@ void rend_client_desc_fetched(char *query, int success) {
         log_fn(LOG_WARN,"attaching to a rend circ failed. Closing conn.");
         connection_mark_for_close(conn,0);
       }
-    } else { /* 404 */
-      log_fn(LOG_WARN,"service id '%s' not found. Closing conn.", query);
+    } else { /* 404, or fetch didn't get that far */
+      log_fn(LOG_WARN,"service id '%s' fetched failed, and not in cache. Closing conn.", query);
       connection_mark_for_close(conn,0);
     }
   }