[tor-commits] [obfsproxy/master] Move socks_state, is_open, and flushing fields from conn_t to circuit_t.

nickm at torproject.org nickm at torproject.org
Fri Sep 9 17:08:58 UTC 2011


commit c76bd29587ed0be50125f3ac2cd37a0e89710415
Author: Zack Weinberg <zackw at panix.com>
Date:   Wed Aug 3 11:43:13 2011 -0700

    Move socks_state, is_open, and flushing fields from conn_t to circuit_t.
---
 src/network.c |   89 +++++++++++++++++++++++++++++++++++++--------------------
 src/network.h |   27 +++++++++++++----
 2 files changed, 78 insertions(+), 38 deletions(-)

diff --git a/src/network.c b/src/network.c
index 08ce696..cc5b633 100644
--- a/src/network.c
+++ b/src/network.c
@@ -82,7 +82,9 @@ static void conn_free(conn_t *conn);
 static void conn_free_all(void);
 static void conn_free_on_flush(struct bufferevent *bev, void *arg);
 
-static int circuit_create(conn_t *upstream, conn_t *downstream);
+static int circuit_create(conn_t *up, conn_t *down);
+static void circuit_create_socks(conn_t *up);
+static int circuit_add_down(circuit_t *circuit, conn_t *down);
 static void circuit_free(circuit_t *circuit);
 static conn_t *open_outbound(conn_t *conn, bufferevent_data_cb readcb);
 
@@ -293,7 +295,7 @@ socks_client_listener_cb(conn_t *conn)
   obfs_assert(conn->mode == LSN_SOCKS_CLIENT);
   log_debug("%s: socks client connection", conn->peername);
 
-  conn->socks_state = socks_state_new();
+  circuit_create_socks(conn);
 
   bufferevent_setcb(conn->buffer, socks_read_cb, NULL, error_cb, conn);
   bufferevent_enable(conn->buffer, EV_READ|EV_WRITE);
@@ -341,8 +343,6 @@ conn_free(conn_t *conn)
     }
     if (conn->peername)
       free(conn->peername);
-    if (conn->socks_state)
-      socks_state_free(conn->socks_state);
     if (conn->buffer)
       bufferevent_free(conn->buffer);
     proto_conn_free(conn);
@@ -386,13 +386,38 @@ circuit_create(conn_t *up, conn_t *down)
 }
 
 static void
+circuit_create_socks(conn_t *up)
+{
+  obfs_assert(up);
+
+  circuit_t *r = xzalloc(sizeof(circuit_t));
+  r->upstream = up;
+  r->socks_state = socks_state_new();
+  up->circuit = r;
+}
+
+static int
+circuit_add_down(circuit_t *circuit, conn_t *down)
+{
+  if (!down)
+    return -1;
+  circuit->downstream = down;
+  down->circuit = circuit;
+  return 0;
+}
+
+static void
 circuit_free(circuit_t *circuit)
 {
   /* break the circular references before deallocating each side */
   circuit->upstream->circuit = NULL;
-  circuit->downstream->circuit = NULL;
   conn_free(circuit->upstream);
-  conn_free(circuit->downstream);
+  if (circuit->downstream) {
+    circuit->downstream->circuit = NULL;
+    conn_free(circuit->downstream);
+  }
+  if (circuit->socks_state)
+    socks_state_free(circuit->socks_state);
   free(circuit);
 }
 
@@ -504,22 +529,28 @@ static void
 socks_read_cb(struct bufferevent *bev, void *arg)
 {
   conn_t *conn = arg;
+  socks_state_t *socks;
   enum socks_ret socks_ret;
+
   log_debug("%s: %s", conn->peername, __func__);
+  obfs_assert(conn->circuit);
+  obfs_assert(conn->circuit->socks_state);
+  socks = conn->circuit->socks_state;
 
   do {
-    enum socks_status_t status = socks_state_get_status(conn->socks_state);
+    enum socks_status_t status = socks_state_get_status(socks);
     if (status == ST_SENT_REPLY) {
       /* We shouldn't be here. */
       obfs_abort();
     } else if (status == ST_HAVE_ADDR) {
       int af, r, port;
       const char *addr=NULL;
-      r = socks_state_get_address(conn->socks_state, &af, &addr, &port);
+      r = socks_state_get_address(socks, &af, &addr, &port);
       obfs_assert(r==0);
       log_info("%s: socks: trying to connect to %s:%u",
                conn->peername, addr, port);
-      if (circuit_create(conn, open_outbound_hostname(conn, af, addr, port))) {
+      if (circuit_add_down(conn->circuit,
+                           open_outbound_hostname(conn, af, addr, port))) {
         /* XXXX send socks reply */
         conn_free(conn);
         return;
@@ -532,7 +563,7 @@ socks_read_cb(struct bufferevent *bev, void *arg)
 
     socks_ret = handle_socks(bufferevent_get_input(bev),
                              bufferevent_get_output(bev),
-                             conn->socks_state);
+                             socks);
   } while (socks_ret == SOCKS_GOOD);
 
   if (socks_ret == SOCKS_INCOMPLETE)
@@ -542,7 +573,7 @@ socks_read_cb(struct bufferevent *bev, void *arg)
   else if (socks_ret == SOCKS_CMD_NOT_CONNECT) {
     bufferevent_enable(bev, EV_WRITE);
     bufferevent_disable(bev, EV_READ);
-    socks5_send_reply(bufferevent_get_output(bev), conn->socks_state,
+    socks5_send_reply(bufferevent_get_output(bev), socks,
                       SOCKS5_FAILED_UNSUPPORTED);
     bufferevent_setcb(bev, NULL,
                       conn_free_on_flush, flush_error_cb, conn);
@@ -564,10 +595,10 @@ upstream_read_cb(struct bufferevent *bev, void *arg)
             (unsigned long)evbuffer_get_length(bufferevent_get_input(bev)));
 
   obfs_assert(up->buffer == bev);
-  obfs_assert(!up->flushing);
-  obfs_assert(up->is_open);
   obfs_assert(up->circuit);
   obfs_assert(up->circuit->downstream);
+  obfs_assert(up->circuit->is_open);
+  obfs_assert(!up->circuit->is_flushing);
 
   down = up->circuit->downstream;
   if (proto_send(up,
@@ -597,10 +628,10 @@ downstream_read_cb(struct bufferevent *bev, void *arg)
             (unsigned long)evbuffer_get_length(bufferevent_get_input(bev)));
 
   obfs_assert(down->buffer == bev);
-  obfs_assert(!down->flushing);
-  obfs_assert(down->is_open);
   obfs_assert(down->circuit);
   obfs_assert(down->circuit->upstream);
+  obfs_assert(down->circuit->is_open);
+  obfs_assert(!down->circuit->is_flushing);
   up = down->circuit->upstream;
 
 
@@ -644,7 +675,8 @@ error_or_eof(conn_t *conn)
   struct bufferevent *bev_flush;
 
   log_debug("%s for %s", __func__, conn->peername);
-  if (!circ || conn->flushing || !conn->is_open) {
+  if (!circ || !circ->upstream || !circ->downstream || !circ->is_open
+      || circ->is_flushing) {
     conn_free(conn);
     return;
   }
@@ -656,9 +688,7 @@ error_or_eof(conn_t *conn)
     return;
   }
 
-  /* XXX move ->flushing and ->is_open to circuit_t */
-  circ->upstream->flushing = 1;
-  circ->downstream->flushing = 1;
+  circ->is_flushing = 1;
 
   /* Stop reading and writing; wait for the other side to flush if it has
    * data. */
@@ -717,7 +747,8 @@ flush_error_cb(struct bufferevent *bev, short what, void *arg)
   obfs_assert(what & (BEV_EVENT_EOF|BEV_EVENT_ERROR|BEV_EVENT_TIMEOUT));
   obfs_assert(!(what & BEV_EVENT_CONNECTED));
 
-  obfs_assert(conn->flushing);
+  obfs_assert(conn->circuit);
+  obfs_assert(conn->circuit->is_flushing);
 
   log_warn("Error during flush of connection with %s: %s",
            conn->peername,
@@ -743,11 +774,9 @@ pending_conn_cb(struct bufferevent *bev, short what, void *arg)
   if (what & BEV_EVENT_CONNECTED) {
     circuit_t *circ = conn->circuit;
     obfs_assert(circ);
-    obfs_assert(!circ->upstream->flushing);
-    obfs_assert(!circ->downstream->flushing);
+    obfs_assert(!circ->is_flushing);
 
-    circ->upstream->is_open = 1;
-    circ->downstream->is_open = 1;
+    circ->is_open = 1;
 
     log_debug("%s: Successful connection", conn->peername);
 
@@ -790,11 +819,11 @@ pending_socks_cb(struct bufferevent *bev, short what, void *arg)
 
   obfs_assert(circ);
   obfs_assert(circ->upstream);
-  obfs_assert(circ->upstream->socks_state);
+  obfs_assert(circ->socks_state);
   obfs_assert(circ->downstream == down);
 
   up = circ->upstream;
-  socks = circ->upstream->socks_state;
+  socks = circ->socks_state;
 
   /* If we got an error while in the ST_HAVE_ADDR state, chances are
      that we failed connecting to the host requested by the CONNECT
@@ -820,8 +849,7 @@ pending_socks_cb(struct bufferevent *bev, short what, void *arg)
     struct sockaddr *sa = (struct sockaddr*)&ss;
     socklen_t slen = sizeof(&ss);
 
-    obfs_assert(!up->flushing);
-    obfs_assert(!down->flushing);
+    obfs_assert(!circ->is_flushing);
 
     /* Figure out where we actually connected to, and tell the socks client */
     if (getpeername(bufferevent_getfd(bev), sa, &slen) == 0) {
@@ -833,9 +861,8 @@ pending_socks_cb(struct bufferevent *bev, short what, void *arg)
 
     /* Switch to regular upstream behavior. */
     socks_state_free(socks);
-    up->socks_state = NULL;
-    up->is_open = 1;
-    down->is_open = 1;
+    circ->socks_state = NULL;
+    circ->is_open = 1;
     log_debug("%s: Successful outbound connection to %s",
               up->peername, down->peername);
 
diff --git a/src/network.h b/src/network.h
index 72df32c..fa15f48 100644
--- a/src/network.h
+++ b/src/network.h
@@ -26,23 +26,36 @@ void start_shutdown(int barbaric);
 struct conn_t {
   config_t           *cfg;
   char               *peername;
-  socks_state_t      *socks_state;
   circuit_t          *circuit;
   struct bufferevent *buffer;
-  enum listen_mode    mode     : 30;
-  unsigned int        flushing : 1;
-  unsigned int        is_open  : 1;
+  enum listen_mode    mode;
 };
 
 /**
-   This struct defines a pair of established connections.  The "upstream"
-   connection is to the higher-level client or server that we are proxying
-   traffic for.  The "downstream" connection is to the remote peer.
+   This struct defines a pair of established connections.
+
+   The "upstream" connection is to the higher-level client or server
+   that we are proxying traffic for.  The "downstream" connection is
+   to the remote peer.  Circuits always have an upstream connection,
+   and normally also have a downstream connection; however, a circuit
+   that's waiting for SOCKS directives from its upstream will have a
+   non-null socks_state field instead.
+
+   A circuit is "open" if both its upstream and downstream connections
+   have been established (not just if both conn_t objects exist).
+   It is "flushing" if one of the two connections has hit either EOF
+   or an error, and we are clearing out the other side's pending
+   transmissions before closing it.  Both of these flags are used
+   near-exclusively for assertion checks; the actual behavior is
+   controlled by changing bufferevent callbacks on the connections.
  */
 
 struct circuit_t {
   conn_t             *upstream;
   conn_t             *downstream;
+  socks_state_t      *socks_state;
+  unsigned int        is_open : 1;
+  unsigned int        is_flushing : 1;
 };
 
 #endif





More information about the tor-commits mailing list