[tor-commits] [obfsproxy/master] Tweak doubly linked list code

nickm at torproject.org nickm at torproject.org
Thu Jul 14 15:39:26 UTC 2011


commit 65aa57320522002fd4594636c4fdea7e7d3b58ce
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Jul 14 11:35:40 2011 -0400

    Tweak doubly linked list code
    
    It's not nice to have to do a linear search of the linked list every
    time we close a connection.  Thus, let's stick the dll_node_t inside
    the structure.  This also simplifies some of the code too.
    
    Also, rename "cl" and "ll" to something real.
---
 src/main.c    |   42 +---------------------------------
 src/network.c |   69 ++++++++++++++++++++++++++++++++++----------------------
 src/network.h |    5 ++-
 src/util.c    |   52 ++++++++++---------------------------------
 src/util.h    |   15 ++++++++++--
 5 files changed, 70 insertions(+), 113 deletions(-)

diff --git a/src/main.c b/src/main.c
index 621a3c9..b43e1e9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -35,9 +35,6 @@ extern int n_supported_protocols;
 
 static struct event_base *the_event_base=NULL;
 
-/** Doubly linked list holding all our listeners. */
-static dll_t *ll=NULL;
-
 /**
    Prints the obfsproxy usage instructions then exits.
 */
@@ -61,32 +58,6 @@ usage(void)
 }
 
 /**
-   Frees all active listeners.
-*/
-static void
-free_all_listeners(void)
-{
-  static int called_already=0;
-
-  if (called_already)
-    return;
-  if (!ll)
-    return;
-
-  log_info("Closing all listeners.");
-
-  /* Iterate listener doubly linked list and free them all. */ 
-  dll_node_t *ll_node = ll->head;
-  while (ll_node) {
-    listener_free(ll_node->data);
-    dll_remove(ll, ll_node);
-    ll_node = ll->head;
-  }
-
-  called_already++;
-}
-
-/**
    This is called when we receive a signal.
    It figures out the signal type and acts accordingly.
 
@@ -402,18 +373,9 @@ main(int argc, const char **argv)
 
     if (!temp_listener)
       continue;
-    
+
     log_info("Succesfully created listener %d.", h+1);
 
-    /* If we don't have a listener dll, create one now. */
-    if (!ll) {
-      ll = calloc(1, sizeof(dll_t));
-      if (!ll)
-        return 1;
-    }
-        
-    /* Append our new listener in the listener dll. */
-    dll_append(ll, temp_listener);
     n_listeners++;
   }
 
@@ -432,8 +394,6 @@ main(int argc, const char **argv)
     printf("Failed closing logfile!\n");
 
   free_all_listeners(); /* free all listeners in our listener dll */
-  if (ll) /* free listener dll */
-    free(ll);
 
   free(protocol_options);
   free(n_options_array);
diff --git a/src/network.c b/src/network.c
index b29e9dd..605e13d 100644
--- a/src/network.c
+++ b/src/network.c
@@ -21,13 +21,17 @@
 #include <WS2tcpip.h>
 #endif
 
+/** Doubly linked list holding all our listeners. */
+static dll_t listener_list = DLL_INIT();
+
 struct listener_t {
+  dll_node_t dll_node;
   struct evconnlistener *listener;
   protocol_params_t *proto_params;
 };
 
 /** Doubly linked list holding all connections. */
-static dll_t *cl=NULL;
+static dll_t conn_list = DLL_INIT();
 /** Active connection counter */
 static int n_connections=0;
 
@@ -67,8 +71,6 @@ start_shutdown(int barbaric)
     shutting_down=1;
 
   if (!n_connections) {
-    if (cl)
-      free(cl);
     finish_shutdown();
     return;
   }
@@ -87,17 +89,13 @@ static void
 close_all_connections(void)
 {
   /** Traverse the dll and close all connections */
-  dll_node_t *cl_node = cl->head;
-  while (cl_node) {
-    conn_free(cl_node->data);
-
-    if (cl) { /* last conn_free() wipes the cl. */
-      cl_node = cl->head; /* move to next connection */
-    } else {
-      assert(!n_connections);
-      return; /* connections are now all closed. */  
-    }
-  }    
+  while (conn_list.head) {
+    conn_t *conn = UPCAST(conn_t, dll_node, conn_list.head);
+    conn_free(conn); /* removes it */
+
+    return; /* connections are now all closed. */
+  }
+  assert(!n_connections);
 }
   
 /**
@@ -121,14 +119,8 @@ listener_new(struct event_base *base,
   }
 
   /** If we don't have a connection dll, create one now. */
-  if (!cl) {
-    cl = calloc(1, sizeof(dll_t));
-    if (!cl)
-      return NULL;
-  }
-
   lsn->proto_params = proto_params;
-  
+
   lsn->listener = evconnlistener_new_bind(base, simple_listener_cb, lsn,
                                           flags,
                                           -1,
@@ -141,6 +133,8 @@ listener_new(struct event_base *base,
     return NULL;
   }
 
+  dll_append(&listener_list, &lsn->dll_node);
+
   return lsn;
 }
 
@@ -151,10 +145,35 @@ listener_free(listener_t *lsn)
     evconnlistener_free(lsn->listener);
   if (lsn->proto_params)
     proto_params_free(lsn->proto_params);
+
+  dll_remove(&listener_list, &lsn->dll_node);
+
   memset(lsn, 0xb0, sizeof(listener_t));
   free(lsn);
 }
 
+/**
+   Frees all active listeners.
+*/
+void
+free_all_listeners(void)
+{
+  static int called_already=0;
+
+  if (called_already)
+    return;
+
+  log_info("Closing all listeners.");
+
+  /* Iterate listener doubly linked list and free them all. */
+  while (listener_list.head) {
+    listener_t *listener = UPCAST(listener_t, dll_node, listener_list.head);
+    listener_free(listener);
+  }
+
+  called_already++;
+}
+
 static void
 simple_listener_cb(struct evconnlistener *evcl,
     evutil_socket_t fd, struct sockaddr *sourceaddr, int socklen, void *arg)
@@ -239,7 +258,7 @@ simple_listener_cb(struct evconnlistener *evcl,
   }
 
   /* add conn to the linked list of connections */
-  if (dll_append(cl, conn)<0)
+  if (dll_append(&conn_list, &conn->dll_node)<0)
     goto err;
   n_connections++;
 
@@ -267,7 +286,7 @@ conn_free(conn_t *conn)
     bufferevent_free(conn->output);
 
   /* remove conn from the linked list of connections */
-  dll_remove_with_data(cl, conn);
+  dll_remove(&conn_list, &conn->dll_node);
   n_connections--;
 
   memset(conn, 0x99, sizeof(conn_t));
@@ -280,10 +299,6 @@ conn_free(conn_t *conn)
   /** If this was the last connection AND we are shutting down,
       finish shutdown. */
   if (!n_connections && shutting_down) {
-    if (cl) { /* free connection dll */ 
-      free(cl);
-      cl = NULL;
-    }
     finish_shutdown();
   }
 }
diff --git a/src/network.h b/src/network.h
index 28a0d7d..dc6b583 100644
--- a/src/network.h
+++ b/src/network.h
@@ -12,8 +12,7 @@
 #include <event2/listener.h>
 #include <event2/event.h>
 
-
-typedef struct listener_t *listener;
+#include "util.h"
 
 struct sockaddr;
 struct event_base;
@@ -46,11 +45,13 @@ struct addrinfo;
 listener_t *listener_new(struct event_base *base,
                          struct protocol_params_t *params);
 void listener_free(listener_t *listener);
+void free_all_listeners(void);
 
 void start_shutdown(int barbaric);
 
 #ifdef NETWORK_PRIVATE
 typedef struct conn_t {
+  dll_node_t dll_node;
   struct socks_state_t *socks_state;
   struct protocol_t *proto; /* ASN Do we like this here? We probably don't.
                                But it's so convenient!! So convenient! */
diff --git a/src/util.c b/src/util.c
index 1ee7bcb..06e89b9 100644
--- a/src/util.c
+++ b/src/util.c
@@ -152,7 +152,7 @@ obfs_vsnprintf(char *str, size_t size, const char *format, va_list args)
 
 /**
    Insert 'new_node' after 'node' in the doubly linked list 'list'.
-*/ 
+*/
 static void
 dll_insert_after(dll_t *list, dll_node_t *node, dll_node_t *new_node)
 {
@@ -191,6 +191,13 @@ dll_insert_before(dll_t *list, dll_node_t *node, dll_node_t *new_node)
     node->prev->next = new_node;
   node->prev = new_node;
 }
+
+/** Initialize <b>list</b> as an empty list. */
+void
+dll_init(dll_t *list)
+{
+  list->head = list->tail = NULL;
+}
   
 /**
    Insert 'node' in the beginning of the doubly linked 'list'.
@@ -218,25 +225,16 @@ dll_insert_beginning(dll_t *list, dll_node_t *node)
     Returns 1 on success, -1 on fail.
 */
 int
-dll_append(dll_t *list, void *data)
+dll_append(dll_t *list, dll_node_t *node)
 {
-  assert(data);
-
-  if (!list)
-    return -1;
+  assert(list);
+  assert(node);
 
-  dll_node_t *node;
-  
-  node = calloc(1, sizeof(dll_node_t));
-  if (!node)
-    return -1;
-  node->data = data;
-  
   if (!list->tail)
     dll_insert_beginning(list, node);
   else
     dll_insert_after(list, list->tail, node);
-      
+
   return 1;
 }
 
@@ -260,32 +258,6 @@ dll_remove(dll_t *list, dll_node_t *node)
     list->tail = node->prev;
   else
     node->next->prev = node->prev;
-
-  free(node);
-}
-
-/**
-   Removes node carrying 'data' from the doubly linked list 'list'.
-   It frees the list node, but leaves 'data' intact.
-*/
-void
-dll_remove_with_data(dll_t *list, void *data)
-{
-  assert(data);
-  
-  if (!list)
-    return;
-
-  dll_node_t *node = list->head;
-  while (node) {
-    if (node->data == data) {
-      dll_remove(list, node);
-      return;
-    } else {
-      node = node->next;
-    }
-  }
-  assert(0); /*too brutal?*/
 }
 
 /************************ Logging Subsystem *************************/
diff --git a/src/util.h b/src/util.h
index 999c5df..7e73cee 100644
--- a/src/util.h
+++ b/src/util.h
@@ -52,11 +52,19 @@ int obfs_snprintf(char *str, size_t size,
 
 /***** Doubly Linked List stuff. *****/
 
+#define OFFSETOF(container_type, element) \
+  (((char*)&((container_type*)0)->element) - ((char*) ((container_type*)0)))
+
+#define UPCAST(container_type, element, ptr) \
+  (container_type*) (                                                   \
+         ((char*)ptr) - OFFSETOF(container_type, element)   \
+                    )
+
+
 /** A doubly linked list node.
     [algorithms ripped off Wikipedia (Doubly_linked_list) ] */
 typedef struct dll_node_t {
   struct dll_node_t *next, *prev;
-  void *data;
 } dll_node_t;
 
 /** A doubly linked list. */
@@ -65,9 +73,10 @@ typedef struct dll_t {
   struct dll_node_t *tail;
 } dll_t;
 
-int dll_append(dll_t *list, void *data);
+void dll_init(dll_t *list);
+int dll_append(dll_t *list, dll_node_t *node);
 void dll_remove(dll_t *list, dll_node_t *node);
-void dll_remove_with_data(dll_t *list, void *data);
+#define DLL_INIT() { NULL, NULL }
 
 /***** Logging subsystem stuff. *****/
 





More information about the tor-commits mailing list