[or-cvs] Handle unavailable hidden services better. We try each intr...

Roger Dingledine arma at seul.org
Wed Jan 19 23:16:02 UTC 2005


Update of /home2/or/cvsroot/tor/src/or
In directory moria.mit.edu:/home2/arma/work/onion/cvs/tor/src/or

Modified Files:
	circuituse.c connection.c cpuworker.c directory.c or.h 
	rendclient.c rendcommon.c 
Log Message:
Handle unavailable hidden services better. We try each intro point
until none are left, then we try to refetch the descriptor. If it's
the same one we had before, then close streams right then. Whenever
a new stream arrives, even if it's right after, optimistically try
refetching the descriptor, just in case.


Index: circuituse.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/circuituse.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- circuituse.c	19 Jan 2005 17:13:11 -0000	1.45
+++ circuituse.c	19 Jan 2005 23:15:59 -0000	1.46
@@ -817,18 +817,22 @@
 
     if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
       /* need to pick an intro point */
+try_an_intro_point:
       exitname = rend_client_get_random_intro(conn->rend_query);
       if (!exitname) {
-        log_fn(LOG_WARN,"Couldn't get an intro point for '%s'. Closing.",
+        log_fn(LOG_INFO,"No intro points for '%s': refetching service descriptor.",
                conn->rend_query);
-        return -1;
+        rend_client_refetch_renddesc(conn->rend_query);
+        conn->state = AP_CONN_STATE_RENDDESC_WAIT;
+        return 0;
       }
       if (!router_get_by_nickname(exitname)) {
-        log_fn(LOG_WARN,"Advertised intro point '%s' is not known. Closing.", exitname);
+        log_fn(LOG_NOTICE,"Advertised intro point '%s' is not recognized for '%s'. Skipping over.",
+               exitname, conn->rend_query);
+        rend_client_remove_intro_point(exitname, conn->rend_query);
         tor_free(exitname);
-        return -1;
+        goto try_an_intro_point;
       }
-      /* XXX if we failed, then refetch the descriptor */
       log_fn(LOG_INFO,"Chose %s as intro point for %s.", exitname, conn->rend_query);
     }
 
@@ -839,7 +843,7 @@
       if (conn->chosen_exit_name) {
         exitname = tor_strdup(conn->chosen_exit_name);
         if (!router_get_by_nickname(exitname)) {
-          log_fn(LOG_WARN,"Requested exit point '%s' is not known. Closing.", exitname);
+          log_fn(LOG_NOTICE,"Requested exit point '%s' is not known. Closing.", exitname);
           tor_free(exitname);
           return -1;
         }

Index: connection.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/connection.c,v
retrieving revision 1.316
retrieving revision 1.317
diff -u -d -r1.316 -r1.317
--- connection.c	12 Jan 2005 12:19:00 -0000	1.316
+++ connection.c	19 Jan 2005 23:15:59 -0000	1.317
@@ -219,7 +219,7 @@
         connection_dir_connect_failed(conn);
       }
       if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC)
-        rend_client_desc_fetched(conn->rend_query, 0);
+        rend_client_desc_here(conn->rend_query); /* give it a try */
       break;
     case CONN_TYPE_OR:
       /* Remember why we're closing this connection. */
@@ -1243,9 +1243,11 @@
 }
 
 /** Return a connection of type <b>type</b> that has rendquery equal
- * to <b>rendquery</b>, and that is not marked for close.
+ * to <b>rendquery</b>, and that is not marked for close. If state
+ * is non-zero, conn must be of that state too.
  */
-connection_t *connection_get_by_type_rendquery(int type, const char *rendquery) {
+connection_t *
+connection_get_by_type_state_rendquery(int type, int state, const char *rendquery) {
   int i, n;
   connection_t *conn;
   connection_t **carray;
@@ -1255,6 +1257,7 @@
     conn = carray[i];
     if (conn->type == type &&
         !conn->marked_for_close &&
+        (!state || state == conn->state) &&
         !rend_cmp_service_ids(rendquery, conn->rend_query))
       return conn;
   }

Index: cpuworker.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/cpuworker.c,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -d -r1.64 -r1.65
--- cpuworker.c	19 Jan 2005 21:34:42 -0000	1.64
+++ cpuworker.c	19 Jan 2005 23:15:59 -0000	1.65
@@ -227,7 +227,7 @@
       if (r == 0) {
         log_fn(LOG_INFO,"CPU worker exiting because Tor process closed connection (either rotated keys or died).");
       } else {
-        log_fn(LOG_INFO,"CPU worker editing because of error on connection To Tor process.");
+        log_fn(LOG_INFO,"CPU worker editing because of error on connection to Tor process.");
         log_fn(LOG_INFO,"(Error on %d was %s)", fd, tor_socket_strerror(tor_socket_errno(fd)));
       }
       goto end;

Index: directory.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/directory.c,v
retrieving revision 1.195
retrieving revision 1.196
diff -u -d -r1.195 -r1.196
--- directory.c	19 Jan 2005 22:47:48 -0000	1.195
+++ directory.c	19 Jan 2005 23:15:59 -0000	1.196
@@ -746,8 +746,8 @@
            * 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;
+          rend_client_desc_here(conn->rend_query);
         }
         break;
       case 404:

Index: or.h
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/or.h,v
retrieving revision 1.526
retrieving revision 1.527
diff -u -d -r1.526 -r1.527
--- or.h	18 Jan 2005 23:44:55 -0000	1.526
+++ or.h	19 Jan 2005 23:15:59 -0000	1.527
@@ -1206,7 +1206,7 @@
 connection_t *connection_get_by_type(int type);
 connection_t *connection_get_by_type_state(int type, int state);
 connection_t *connection_get_by_type_state_lastwritten(int type, int state);
-connection_t *connection_get_by_type_rendquery(int type, const char *rendquery);
+connection_t *connection_get_by_type_state_rendquery(int type, int state, const char *rendquery);
 
 #define connection_speaks_cells(conn) ((conn)->type == CONN_TYPE_OR)
 #define connection_has_pending_tls_data(conn) \
@@ -1495,7 +1495,7 @@
 int rend_client_remove_intro_point(char *failed_intro, const char *query);
 int rend_client_rendezvous_acked(circuit_t *circ, const char *request, size_t request_len);
 int rend_client_receive_rendezvous(circuit_t *circ, const char *request, size_t request_len);
-void rend_client_desc_fetched(char *query, int status);
+void rend_client_desc_here(char *query);
 
 char *rend_client_get_random_intro(char *query);
 

Index: rendclient.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/rendclient.c,v
retrieving revision 1.75
retrieving revision 1.76
diff -u -d -r1.75 -r1.76
--- rendclient.c	19 Jan 2005 17:13:11 -0000	1.75
+++ rendclient.c	19 Jan 2005 23:15:59 -0000	1.76
@@ -239,7 +239,7 @@
 void
 rend_client_refetch_renddesc(const char *query)
 {
-  if (connection_get_by_type_rendquery(CONN_TYPE_DIR, query)) {
+  if (connection_get_by_type_state_rendquery(CONN_TYPE_DIR, 0, query)) {
     log_fn(LOG_INFO,"Would fetch a new renddesc here (for %s), but one is already in progress.", query);
   } else {
     /* not one already; initiate a dir rend desc lookup */
@@ -258,6 +258,7 @@
 {
   int i, r;
   rend_cache_entry_t *ent;
+  connection_t *conn;
 
   r = rend_cache_lookup_entry(query, &ent);
   if (r<0) {
@@ -282,6 +283,13 @@
   if (!ent->parsed->n_intro_points) {
     log_fn(LOG_INFO,"No more intro points remain for %s. Re-fetching descriptor.", query);
     rend_client_refetch_renddesc(query);
+
+    /* move all pending streams back to renddesc_wait */
+    while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
+                                   AP_CONN_STATE_CIRCUIT_WAIT, query))) {
+      conn->state = AP_CONN_STATE_RENDDESC_WAIT;
+    }
+
     return 0;
   }
   log_fn(LOG_INFO,"%d options left for %s.", ent->parsed->n_intro_points, query);
@@ -366,30 +374,21 @@
 }
 
 /** Find all the apconns in state AP_CONN_STATE_RENDDESC_WAIT that
- * are waiting on query. If status==1, move them to the next state.
- * If status==0, fail them.
+ * are waiting on query. If there's a working cache entry here
+ * with at least one intro point, move them to the next state;
+ * else fail them.
  */
-void rend_client_desc_fetched(char *query, int status) {
-  connection_t **carray;
+void rend_client_desc_here(char *query) {
   connection_t *conn;
-  int n, i;
   rend_cache_entry_t *entry;
 
-  get_connection_array(&carray, &n);
-
-  for (i = 0; i < n; ++i) {
-    conn = carray[i];
-    if (conn->type != CONN_TYPE_AP ||
-        conn->state != AP_CONN_STATE_RENDDESC_WAIT)
-      continue;
-    if (rend_cmp_service_ids(conn->rend_query, query))
-      continue;
-    /* great, this guy was waiting */
-    if (status!=0 ||
-       rend_cache_lookup_entry(conn->rend_query, &entry) == 1) {
+  while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
+                                 AP_CONN_STATE_RENDDESC_WAIT, query))) {
+    if (rend_cache_lookup_entry(conn->rend_query, &entry) == 1 &&
+        entry->parsed->n_intro_points > 0) {
       /* 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.");
+      log_fn(LOG_INFO,"Rend desc is usable. Launching circuits.");
       conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
       if (connection_ap_handshake_attach_circuit(conn) < 0) {
         /* it will never work */
@@ -397,8 +396,9 @@
         conn->has_sent_end = 1;
         connection_mark_for_close(conn);
       }
+      tor_assert(conn->state != AP_CONN_STATE_RENDDESC_WAIT); /* avoid loop */
     } else { /* 404, or fetch didn't get that far */
-      log_fn(LOG_NOTICE,"Failed to fetch service id '%s', and not in cache. Closing conn.", query);
+      log_fn(LOG_NOTICE,"Closing stream for '%s.onion': hidden service is unavailable (try again later).", query);
       conn->has_sent_end = 1;
       connection_mark_for_close(conn);
     }

Index: rendcommon.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/rendcommon.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- rendcommon.c	29 Nov 2004 22:25:30 -0000	1.43
+++ rendcommon.c	19 Jan 2005 23:15:59 -0000	1.44
@@ -242,7 +242,9 @@
 /** Parse *desc, calculate its service id, and store it in the cache.
  * If we have a newer descriptor with the same ID, ignore this one.
  * If we have an older descriptor with the same ID, replace it.
- * Returns -1 if it's malformed or otherwise rejected, else return 0.
+ * Return -1 if it's malformed or otherwise rejected; return 0 if
+ * it's the same or older than one we've already got; return 1 if
+ * it's novel.
  */
 int rend_cache_store(const char *desc, size_t desc_len)
 {
@@ -250,6 +252,7 @@
   rend_service_descriptor_t *parsed;
   char query[REND_SERVICE_ID_LEN+1];
   time_t now;
+
   tor_assert(rend_cache);
   parsed = rend_parse_service_descriptor(desc,desc_len);
   if (!parsed) {
@@ -298,7 +301,7 @@
   memcpy(e->desc, desc, desc_len);
 
   log_fn(LOG_INFO,"Successfully stored rend desc '%s', len %d", query, (int)desc_len);
-  return 0;
+  return 1;
 }
 
 /** Called when we get a rendezvous-related relay cell on circuit



More information about the tor-commits mailing list