[tor-commits] [tor/master] Split connection_about_to_close_connection into separate functions

nickm at torproject.org nickm at torproject.org
Mon Jul 11 20:16:17 UTC 2011


commit a2ad31a92b85158f0dfa0a219ae5270e03b2ef02
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Jun 22 13:57:19 2011 -0400

    Split connection_about_to_close_connection into separate functions
    
    This patch does NOTHING but:
      - move code
      - add declarations and includes as needed to make the new code
        work
      - declare the new functions.
---
 changes/split_about_to_close |    3 +
 src/or/connection.c          |  106 +++---------------------------------------
 src/or/connection_edge.c     |   65 +++++++++++++++++++++++++
 src/or/connection_edge.h     |    3 +
 src/or/connection_or.c       |   45 ++++++++++++++++++
 src/or/connection_or.h       |    1 +
 src/or/directory.c           |   22 +++++++++
 src/or/directory.h           |    1 +
 8 files changed, 147 insertions(+), 99 deletions(-)

diff --git a/changes/split_about_to_close b/changes/split_about_to_close
new file mode 100644
index 0000000..2f5a679
--- /dev/null
+++ b/changes/split_about_to_close
@@ -0,0 +1,3 @@
+  o Code simplification and refactoring:
+    - Split connection_about_to_close into separate functions for each
+      connection type.
diff --git a/src/or/connection.c b/src/or/connection.c
index 5dbf052..e8a17e7 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -563,7 +563,9 @@ connection_free_all(void)
   }
 }
 
-/** Do any cleanup needed:
+/**
+ * Called when we're about to finally unlink and free a connection:
+ * perform necessary accounting and cleanup
  *   - Directory conns that failed to fetch a rendezvous descriptor
  *     need to inform pending rendezvous streams.
  *   - OR conns need to call rep_hist_note_*() to record status.
@@ -576,114 +578,20 @@ connection_free_all(void)
 void
 connection_about_to_close_connection(connection_t *conn)
 {
-  circuit_t *circ;
-  dir_connection_t *dir_conn;
-  or_connection_t *or_conn;
-  edge_connection_t *edge_conn;
-  time_t now = time(NULL);
-
   tor_assert(conn->marked_for_close);
 
-  if (CONN_IS_EDGE(conn)) {
-    edge_conn = TO_EDGE_CONN(conn);
-    if (!edge_conn->edge_has_sent_end) {
-      log_warn(LD_BUG, "(Harmless.) Edge connection (marked at %s:%d) "
-               "hasn't sent end yet?",
-               conn->marked_for_close_file, conn->marked_for_close);
-      tor_fragile_assert();
-    }
-  }
-
   switch (conn->type) {
     case CONN_TYPE_DIR:
-      dir_conn = TO_DIR_CONN(conn);
-      if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
-        /* It's a directory connection and connecting or fetching
-         * failed: forget about this router, and maybe try again. */
-        connection_dir_request_failed(dir_conn);
-      }
-      /* If we were trying to fetch a v2 rend desc and did not succeed,
-       * retry as needed. (If a fetch is successful, the connection state
-       * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that
-       * refetching is unnecessary.) */
-      if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
-          dir_conn->rend_data &&
-          strlen(dir_conn->rend_data->onion_address) ==
-              REND_SERVICE_ID_LEN_BASE32)
-        rend_client_refetch_v2_renddesc(dir_conn->rend_data);
+      connection_dir_about_to_close(TO_DIR_CONN(conn));
       break;
     case CONN_TYPE_OR:
-      or_conn = TO_OR_CONN(conn);
-      /* Remember why we're closing this connection. */
-      if (conn->state != OR_CONN_STATE_OPEN) {
-        /* Inform any pending (not attached) circs that they should
-         * give up. */
-        circuit_n_conn_done(TO_OR_CONN(conn), 0);
-        /* now mark things down as needed */
-        if (connection_or_nonopen_was_started_here(or_conn)) {
-          const or_options_t *options = get_options();
-          rep_hist_note_connect_failed(or_conn->identity_digest, now);
-          entry_guard_register_connect_status(or_conn->identity_digest,0,
-                                              !options->HTTPSProxy, now);
-          if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) {
-            int reason = tls_error_to_orconn_end_reason(or_conn->tls_error);
-            control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
-                                         reason);
-            if (!authdir_mode_tests_reachability(options))
-              control_event_bootstrap_problem(
-                orconn_end_reason_to_control_string(reason), reason);
-          }
-        }
-      } else if (conn->hold_open_until_flushed) {
-        /* We only set hold_open_until_flushed when we're intentionally
-         * closing a connection. */
-        rep_hist_note_disconnect(or_conn->identity_digest, now);
-        control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
-                tls_error_to_orconn_end_reason(or_conn->tls_error));
-      } else if (!tor_digest_is_zero(or_conn->identity_digest)) {
-        rep_hist_note_connection_died(or_conn->identity_digest, now);
-        control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
-                tls_error_to_orconn_end_reason(or_conn->tls_error));
-      }
-      /* Now close all the attached circuits on it. */
-      circuit_unlink_all_from_or_conn(TO_OR_CONN(conn),
-                                      END_CIRC_REASON_OR_CONN_CLOSED);
+      connection_or_about_to_close(TO_OR_CONN(conn));
       break;
     case CONN_TYPE_AP:
-      edge_conn = TO_EDGE_CONN(conn);
-      if (edge_conn->socks_request->has_finished == 0) {
-        /* since conn gets removed right after this function finishes,
-         * there's no point trying to send back a reply at this point. */
-        log_warn(LD_BUG,"Closing stream (marked at %s:%d) without sending"
-                 " back a socks reply.",
-                 conn->marked_for_close_file, conn->marked_for_close);
-      }
-      if (!edge_conn->end_reason) {
-        log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
-                 " set end_reason.",
-                 conn->marked_for_close_file, conn->marked_for_close);
-      }
-      if (edge_conn->dns_server_request) {
-        log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
-                 " replied to DNS request.",
-                 conn->marked_for_close_file, conn->marked_for_close);
-        dnsserv_reject_request(edge_conn);
-      }
-      control_event_stream_bandwidth(edge_conn);
-      control_event_stream_status(edge_conn, STREAM_EVENT_CLOSED,
-                                  edge_conn->end_reason);
-      circ = circuit_get_by_edge_conn(edge_conn);
-      if (circ)
-        circuit_detach_stream(circ, edge_conn);
+      connection_ap_about_to_close(TO_EDGE_CONN(conn));
       break;
     case CONN_TYPE_EXIT:
-      edge_conn = TO_EDGE_CONN(conn);
-      circ = circuit_get_by_edge_conn(edge_conn);
-      if (circ)
-        circuit_detach_stream(circ, edge_conn);
-      if (conn->state == EXIT_CONN_STATE_RESOLVING) {
-        connection_dns_remove(edge_conn);
-      }
+      connection_exit_about_to_close(TO_EDGE_CONN(conn));
       break;
   }
 }
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 3f6e87c..7516716 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -408,6 +408,71 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn)
   return connection_edge_process_inbuf(edge_conn, 1);
 }
 
+/** Common code to connection_(ap|exit)_about_to_close. */
+static void
+connection_edge_about_to_close(edge_connection_t *edge_conn)
+{
+  if (!edge_conn->edge_has_sent_end) {
+    connection_t *conn = TO_CONN(edge_conn);
+    log_warn(LD_BUG, "(Harmless.) Edge connection (marked at %s:%d) "
+             "hasn't sent end yet?",
+             conn->marked_for_close_file, conn->marked_for_close);
+    tor_fragile_assert();
+  }
+}
+
+/* Called when we're about to finally unlink and free an AP (client)
+ * connection: perform necessary accounting and cleanup */
+void
+connection_ap_about_to_close(edge_connection_t *edge_conn)
+{
+  circuit_t *circ;
+  connection_t *conn = TO_CONN(edge_conn);
+
+  if (edge_conn->socks_request->has_finished == 0) {
+    /* since conn gets removed right after this function finishes,
+     * there's no point trying to send back a reply at this point. */
+    log_warn(LD_BUG,"Closing stream (marked at %s:%d) without sending"
+             " back a socks reply.",
+             conn->marked_for_close_file, conn->marked_for_close);
+  }
+  if (!edge_conn->end_reason) {
+    log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
+             " set end_reason.",
+             conn->marked_for_close_file, conn->marked_for_close);
+  }
+  if (edge_conn->dns_server_request) {
+    log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
+             " replied to DNS request.",
+             conn->marked_for_close_file, conn->marked_for_close);
+    dnsserv_reject_request(edge_conn);
+  }
+  control_event_stream_bandwidth(edge_conn);
+  control_event_stream_status(edge_conn, STREAM_EVENT_CLOSED,
+                              edge_conn->end_reason);
+  circ = circuit_get_by_edge_conn(edge_conn);
+  if (circ)
+    circuit_detach_stream(circ, edge_conn);
+}
+
+/* Called when we're about to finally unlink and free an exit
+ * connection: perform necessary accounting and cleanup */
+void
+connection_exit_about_to_close(edge_connection_t *edge_conn)
+{
+  circuit_t *circ;
+  connection_t *conn = TO_CONN(edge_conn);
+
+  connection_edge_about_to_close(edge_conn);
+
+  circ = circuit_get_by_edge_conn(edge_conn);
+  if (circ)
+    circuit_detach_stream(circ, edge_conn);
+  if (conn->state == EXIT_CONN_STATE_RESOLVING) {
+    connection_dns_remove(edge_conn);
+  }
+}
+
 /** Define a schedule for how long to wait between retrying
  * application connections. Rather than waiting a fixed amount of
  * time between each retry, we wait 10 seconds each for the first
diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h
index a7fc12e..1cb1281 100644
--- a/src/or/connection_edge.h
+++ b/src/or/connection_edge.h
@@ -27,6 +27,9 @@ int connection_edge_flushed_some(edge_connection_t *conn);
 int connection_edge_finished_flushing(edge_connection_t *conn);
 int connection_edge_finished_connecting(edge_connection_t *conn);
 
+void connection_ap_about_to_close(edge_connection_t *edge_conn);
+void connection_exit_about_to_close(edge_connection_t *edge_conn);
+
 int connection_ap_handshake_send_begin(edge_connection_t *ap_conn);
 int connection_ap_handshake_send_resolve(edge_connection_t *ap_conn);
 
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 5092f63..fa86241 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -13,6 +13,7 @@
 #include "or.h"
 #include "buffers.h"
 #include "circuitbuild.h"
+#include "circuitlist.h"
 #include "command.h"
 #include "config.h"
 #include "connection.h"
@@ -347,6 +348,50 @@ connection_or_finished_connecting(or_connection_t *or_conn)
   return 0;
 }
 
+/* Called when we're about to finally unlink and free an OR connection:
+ * perform necessary accounting and cleanup */
+void
+connection_or_about_to_close(or_connection_t *or_conn)
+{
+  time_t now = time(NULL);
+  connection_t *conn = TO_CONN(or_conn);
+
+  /* Remember why we're closing this connection. */
+  if (conn->state != OR_CONN_STATE_OPEN) {
+    /* Inform any pending (not attached) circs that they should
+     * give up. */
+    circuit_n_conn_done(TO_OR_CONN(conn), 0);
+    /* now mark things down as needed */
+    if (connection_or_nonopen_was_started_here(or_conn)) {
+      const or_options_t *options = get_options();
+      rep_hist_note_connect_failed(or_conn->identity_digest, now);
+      entry_guard_register_connect_status(or_conn->identity_digest,0,
+                                          !options->HTTPSProxy, now);
+      if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) {
+        int reason = tls_error_to_orconn_end_reason(or_conn->tls_error);
+        control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
+                                     reason);
+        if (!authdir_mode_tests_reachability(options))
+          control_event_bootstrap_problem(
+                orconn_end_reason_to_control_string(reason), reason);
+      }
+    }
+  } else if (conn->hold_open_until_flushed) {
+    /* We only set hold_open_until_flushed when we're intentionally
+     * closing a connection. */
+    rep_hist_note_disconnect(or_conn->identity_digest, now);
+    control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
+                tls_error_to_orconn_end_reason(or_conn->tls_error));
+  } else if (!tor_digest_is_zero(or_conn->identity_digest)) {
+    rep_hist_note_connection_died(or_conn->identity_digest, now);
+    control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
+                tls_error_to_orconn_end_reason(or_conn->tls_error));
+  }
+  /* Now close all the attached circuits on it. */
+  circuit_unlink_all_from_or_conn(TO_OR_CONN(conn),
+                                  END_CIRC_REASON_OR_CONN_CLOSED);
+}
+
 /** Return 1 if identity digest <b>id_digest</b> is known to be a
  * currently or recently running relay. Otherwise return 0. */
 int
diff --git a/src/or/connection_or.h b/src/or/connection_or.h
index 4a374ca..f1acfd1 100644
--- a/src/or/connection_or.h
+++ b/src/or/connection_or.h
@@ -25,6 +25,7 @@ int connection_or_process_inbuf(or_connection_t *conn);
 int connection_or_flushed_some(or_connection_t *conn);
 int connection_or_finished_flushing(or_connection_t *conn);
 int connection_or_finished_connecting(or_connection_t *conn);
+void connection_or_about_to_close(or_connection_t *conn);
 int connection_or_digest_is_known_relay(const char *id_digest);
 void connection_or_update_token_buckets(smartlist_t *conns,
                                         const or_options_t *options);
diff --git a/src/or/directory.c b/src/or/directory.c
index 17413ed..c0d4c22 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -2301,6 +2301,28 @@ connection_dir_process_inbuf(dir_connection_t *conn)
   return 0;
 }
 
+/** Called when we're about to finally unlink and free a directory connection:
+ * perform necessary accounting and cleanup */
+void
+connection_dir_about_to_close(dir_connection_t *dir_conn)
+{
+  connection_t *conn = TO_CONN(dir_conn);
+
+  if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
+    /* It's a directory connection and connecting or fetching
+     * failed: forget about this router, and maybe try again. */
+    connection_dir_request_failed(dir_conn);
+  }
+  /* If we were trying to fetch a v2 rend desc and did not succeed,
+   * retry as needed. (If a fetch is successful, the connection state
+   * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that
+   * refetching is unnecessary.) */
+  if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
+      dir_conn->rend_data &&
+      strlen(dir_conn->rend_data->onion_address) == REND_SERVICE_ID_LEN_BASE32)
+    rend_client_refetch_v2_renddesc(dir_conn->rend_data);
+}
+
 /** Create an http response for the client <b>conn</b> out of
  * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
  */
diff --git a/src/or/directory.h b/src/or/directory.h
index caff938..b2c2220 100644
--- a/src/or/directory.h
+++ b/src/or/directory.h
@@ -48,6 +48,7 @@ int connection_dir_reached_eof(dir_connection_t *conn);
 int connection_dir_process_inbuf(dir_connection_t *conn);
 int connection_dir_finished_flushing(dir_connection_t *conn);
 int connection_dir_finished_connecting(dir_connection_t *conn);
+void connection_dir_about_to_close(dir_connection_t *dir_conn);
 void connection_dir_request_failed(dir_connection_t *conn);
 void directory_initiate_command(const char *address, const tor_addr_t *addr,
                                 uint16_t or_port, uint16_t dir_port,





More information about the tor-commits mailing list