[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] general cleanup and reabstraction, to prepare for tls



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

Modified Files:
	connection.c connection_or.c main.c or.h 
Log Message:
general cleanup and reabstraction, to prepare for tls


Index: connection.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection.c,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -d -r1.78 -r1.79
--- connection.c	25 Aug 2003 21:43:51 -0000	1.78
+++ connection.c	5 Sep 2003 06:04:03 -0000	1.79
@@ -92,6 +92,7 @@
   conn->timestamp_lastread = now.tv_sec;
   conn->timestamp_lastwritten = now.tv_sec;
 
+#ifndef TOR_TLS
   if (connection_speaks_cells(conn)) {
     conn->f_crypto = crypto_new_cipher_env(CONNECTION_CIPHER);
     if (!conn->f_crypto) {
@@ -105,6 +106,7 @@
       return NULL;
     }
   }
+#endif
   conn->done_sending = conn->done_receiving = 0;
   return conn;
 }
@@ -120,10 +122,16 @@
     free(conn->dest_addr);
 
   if(connection_speaks_cells(conn)) {
+    directory_set_dirty();
+#ifdef TOR_TLS
+    if (conn->SSL)
+      crypt_SSL_free(conn->SSL);
+#else
     if (conn->f_crypto)
       crypto_free_cipher_env(conn->f_crypto);
     if (conn->b_crypto)
       crypto_free_cipher_env(conn->b_crypto);
+#endif
   }
 
   if (conn->pkey)
@@ -133,9 +141,6 @@
     log_fn(LOG_INFO,"closing fd %d.",conn->s);
     close(conn->s);
   }
-  if(conn->type == CONN_TYPE_OR) {
-    directory_set_dirty();
-  }
   free(conn);
 }
 
@@ -279,22 +284,52 @@
   return 0;
 }
 
+int connection_handle_read(connection_t *conn) {
+  struct timeval now;
+
+  my_gettimeofday(&now);
+  conn->timestamp_lastread = now.tv_sec;
+
+  switch(conn->type) {
+    case CONN_TYPE_OR_LISTENER:
+      return connection_or_handle_listener_read(conn);
+    case CONN_TYPE_AP_LISTENER:
+      return connection_ap_handle_listener_read(conn);
+    case CONN_TYPE_DIR_LISTENER:
+      return connection_dir_handle_listener_read(conn);
+    default:
+
+      if(connection_read_to_buf(conn) < 0) {
+        if(conn->type == CONN_TYPE_DIR && conn->state == DIR_CONN_STATE_CONNECTING) {
+           /* it's a directory server and connecting failed: forget about this router */
+           /* XXX I suspect pollerr may make Windows not get to this point. :( */
+           router_forget_router(conn->addr,conn->port); 
+             /* FIXME i don't think router_forget_router works. */
+         }
+         return -1;
+      }
+      if(connection_process_inbuf(conn) < 0) {
+        //log_fn(LOG_DEBUG,"connection_process_inbuf returned %d.",retval);
+        return -1;
+      }
+      if(!connection_state_is_open(conn) && conn->receiver_bucket == 0) {
+        log_fn(LOG_DEBUG,"receiver bucket reached 0 before handshake finished. Closing.");
+        return -1;
+      }
+      return 0;
+  } /* end switch */
+}
+
 int connection_read_to_buf(connection_t *conn) {
   int read_result;
-  struct timeval now;
   int at_most = global_read_bucket;
 
   if(connection_speaks_cells(conn)) {
     assert(conn->receiver_bucket >= 0);
-  }
-  if(!connection_speaks_cells(conn)) {
+  } else {
     assert(conn->receiver_bucket < 0);
   }
 
-  my_gettimeofday(&now);
-
-  conn->timestamp_lastread = now.tv_sec;
-
   if(conn->receiver_bucket >= 0 && at_most > conn->receiver_bucket)
     at_most = conn->receiver_bucket;
 
@@ -338,13 +373,44 @@
 }
 
 int connection_flush_buf(connection_t *conn) {
-  return flush_buf(conn->s, &conn->outbuf, &conn->outbuflen, &conn->outbuf_flushlen, &conn->outbuf_datalen);
+  return flush_buf(conn->s, &conn->outbuf, &conn->outbuflen,
+                   &conn->outbuf_flushlen, &conn->outbuf_datalen);
 }
 
-int connection_write_to_buf(char *string, int len, connection_t *conn) {
+int connection_handle_write(connection_t *conn) {
   struct timeval now;
+  int retval;
+
+  if(connection_is_listener(conn)) {
+    log_fn(LOG_DEBUG,"Got a listener socket. Can't happen!");
+    return -1;
+  }
 
   my_gettimeofday(&now);
+  conn->timestamp_lastwritten = now.tv_sec;
+
+#ifdef TOR_TLS
+  if(connection_speaks_cells(conn)) {
+    retval = flush_buf_SSL(conn->SSL, &conn->outbuf, &conn->outbuflen,
+                           &conn->outbuf_flushlen, &conn->outbuf_datalen);
+    ...
+
+  } else
+#endif
+  {
+    retval = flush_buf(conn->s, &conn->outbuf, &conn->outbuflen,
+                       &conn->outbuf_flushlen, &conn->outbuf_datalen);
+        /* conns in CONNECTING state will fall through... */
+
+    if(retval == 0) { /* it's done flushing */
+      retval = connection_finished_flushing(conn); /* ...and get handled here. */
+    }
+  }
+
+  return retval;
+}
+
+int connection_write_to_buf(char *string, int len, connection_t *conn) {
 
   if(!len)
     return 0;
@@ -352,12 +418,10 @@
   if(conn->marked_for_close)
     return 0;
 
-  conn->timestamp_lastwritten = now.tv_sec;
-
   if( (!connection_speaks_cells(conn)) ||
       (!connection_state_is_open(conn)) ||
       (options.LinkPadding == 0) ) {
-    /* connection types other than or and op, or or/op not in 'open' state, should flush immediately */
+    /* connection types other than or, or or not in 'open' state, should flush immediately */
     /* also flush immediately if we're not doing LinkPadding, since otherwise it will never flush */
     connection_start_writing(conn);
     conn->outbuf_flushlen += len;
@@ -395,78 +459,6 @@
     return 1;
 
   return 0;
-}
-
-void connection_send_cell(connection_t *conn) {
-  cell_t cell;
-  int bytes_in_full_flushlen;
-
-  assert(0); /* this function has decayed. rewrite before using. */
-
-  /* this function only gets called if options.LinkPadding is 1 */
-  assert(options.LinkPadding == 1);
-
-  assert(conn);
-
-  if(!connection_speaks_cells(conn)) {
-    /* this conn doesn't speak cells. do nothing. */
-    return;
-  }
-
-  if(!connection_state_is_open(conn)) {
-    /* it's not in 'open' state, all data should already be waiting to be flushed */
-    assert(conn->outbuf_datalen == conn->outbuf_flushlen);
-    return;
-  }
-
-#if 0 /* use to send evenly spaced cells, but not padding */
-  if(conn->outbuf_datalen - conn->outbuf_flushlen >= sizeof(cell_t)) {
-    conn->outbuf_flushlen += sizeof(cell_t); /* instruct it to send a cell */
-    connection_start_writing(conn);
-  }
-#endif
-
-  connection_increment_send_timeval(conn); /* update when we'll send the next cell */
-
-  bytes_in_full_flushlen = conn->bandwidth / 100; /* 10ms worth */
-  if(bytes_in_full_flushlen < 10*sizeof(cell_t))
-    bytes_in_full_flushlen = 10*sizeof(cell_t); /* but at least 10 cells worth */
-
-  if(conn->outbuf_flushlen > bytes_in_full_flushlen - sizeof(cell_t)) {
-    /* if we would exceed bytes_in_full_flushlen by adding a new cell */
-    return;
-  }
-
-  if(conn->outbuf_datalen - conn->outbuf_flushlen < sizeof(cell_t)) {
-    /* we need to queue a padding cell first */
-    memset(&cell,0,sizeof(cell_t));
-    cell.command = CELL_PADDING;
-    connection_write_cell_to_buf(&cell, conn);
-  }
-
-  /* The connection_write_cell_to_buf() call doesn't increase the flushlen
-   * (if link padding is on). So if there isn't a whole cell waiting-but-
-   * not-yet-flushed, we add a padding cell. Thus in any case the gap between
-   * outbuf_datalen and outbuf_flushlen is at least sizeof(cell_t).
-   */
-  conn->outbuf_flushlen += sizeof(cell_t); /* instruct it to send a cell */
-  connection_start_writing(conn);
-}
-
-void connection_increment_send_timeval(connection_t *conn) {
-  /* add "1000000 * sizeof(cell_t) / conn->bandwidth" microseconds to conn->send_timeval */
-  /* FIXME should perhaps use ceil() of this. For now I simply add 1. */
-
-  tv_addms(&conn->send_timeval, 1+1000 * sizeof(cell_t) / conn->bandwidth);
-}
-
-void connection_init_timeval(connection_t *conn) {
-
-  assert(conn);
-
-  my_gettimeofday(&conn->send_timeval);
-
-  connection_increment_send_timeval(conn);
 }
 
 int connection_send_destroy(aci_t aci, connection_t *conn) {

Index: connection_or.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_or.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- connection_or.c	25 Aug 2003 08:28:34 -0000	1.40
+++ connection_or.c	5 Sep 2003 06:04:03 -0000	1.41
@@ -6,6 +6,7 @@
 
 extern or_options_t options; /* command-line and config-file options */
 
+#ifndef TOR_TLS
 static int or_handshake_op_send_keys(connection_t *conn);
 static int or_handshake_op_finished_sending_keys(connection_t *conn);
 
@@ -15,8 +16,9 @@
 static int or_handshake_server_process_auth(connection_t *conn);
 static int or_handshake_server_process_nonce(connection_t *conn);
 
-static void connection_or_set_open(connection_t *conn);
 static void conn_or_init_crypto(connection_t *conn);
+#endif
+static void connection_or_set_open(connection_t *conn);
 
 /*
  *
@@ -29,7 +31,6 @@
   assert(conn && conn->type == CONN_TYPE_OR);
 
   if(conn->inbuf_reached_eof) {
-    /* eof reached, kill it. */
     log_fn(LOG_DEBUG,"conn reached eof. Closing.");
     return -1;
   }
@@ -37,12 +38,14 @@
 //  log(LOG_DEBUG,"connection_or_process_inbuf(): state %d.",conn->state);
 
   switch(conn->state) {
+#ifndef TOR_TLS
     case OR_CONN_STATE_CLIENT_AUTH_WAIT:
       return or_handshake_client_process_auth(conn);
     case OR_CONN_STATE_SERVER_AUTH_WAIT:
       return or_handshake_server_process_auth(conn);
     case OR_CONN_STATE_SERVER_NONCE_WAIT:
       return or_handshake_server_process_nonce(conn);
+#endif
     case OR_CONN_STATE_OPEN:
       return connection_process_cell_from_inbuf(conn);
     default:
@@ -583,7 +586,6 @@
     crypto_cipher_decrypt_init_cipher(conn->f_crypto);
 
     conn->state = OR_CONN_STATE_OPEN;
-    connection_init_timeval(conn);
     connection_watch_events(conn, POLLIN);
 
     return connection_process_inbuf(conn); /* in case they sent some cells along with the keys */
@@ -654,10 +656,10 @@
 connection_or_set_open(connection_t *conn) {
   conn->state = OR_CONN_STATE_OPEN;
   directory_set_dirty();
-  connection_init_timeval(conn);
   connection_watch_events(conn, POLLIN);
 }
 
+#ifndef TOR_TLS
 static void 
 conn_or_init_crypto(connection_t *conn) {
   //int x;
@@ -673,6 +675,7 @@
   crypto_cipher_decrypt_init_cipher(conn->b_crypto);
     /* always encrypt with f, always decrypt with b */
 }
+#endif
 
 
 

Index: main.c
===================================================================
RCS file: /home/or/cvsroot/src/or/main.c,v
retrieving revision 1.86
retrieving revision 1.87
diff -u -d -r1.86 -r1.87
--- main.c	27 Aug 2003 22:42:10 -0000	1.86
+++ main.c	5 Sep 2003 06:04:03 -0000	1.87
@@ -244,83 +244,47 @@
 }
 
 static void conn_read(int i) {
-  int retval;
   connection_t *conn;
 
-  conn = connection_array[i];
-  assert(conn);
-//  log_fn(LOG_DEBUG,"socket %d has something to read.",conn->s);
-
-#ifdef MS_WINDOWS
-  if (poll_array[i].revents & POLLERR) {
-    retval = -1;
-    goto error;
-  }
-#endif
+  if(!(poll_array[i].revents & (POLLIN|POLLHUP|POLLERR)))
+    return; /* this conn doesn't want to read */
+    /* see http://www.greenend.org.uk/rjk/2001/06/poll.html for
+     * discussion of POLLIN vs POLLHUP */
 
-  if (conn->type == CONN_TYPE_OR_LISTENER) {
-    retval = connection_or_handle_listener_read(conn);
-  } else if (conn->type == CONN_TYPE_AP_LISTENER) {
-    retval = connection_ap_handle_listener_read(conn);
-  } else if (conn->type == CONN_TYPE_DIR_LISTENER) {
-    retval = connection_dir_handle_listener_read(conn);
-  } else {
-    retval = connection_read_to_buf(conn);
-    if (retval < 0 && conn->type == CONN_TYPE_DIR && conn->state == DIR_CONN_STATE_CONNECTING) {
-       /* it's a directory server and connecting failed: forget about this router */
-       router_forget_router(conn->addr,conn->port); /* FIXME i don't think this function works. */
-    }
-    if (retval >= 0) { /* all still well */
-      retval = connection_process_inbuf(conn);
-//    log_fn(LOG_DEBUG,"connection_process_inbuf returned %d.",retval);
-      if(retval >= 0 && !connection_state_is_open(conn) && conn->receiver_bucket == 0) {
-        log(LOG_DEBUG,"conn_read(): receiver bucket reached 0 before handshake finished. Closing.");
-        retval = -1;
-      }
-    }
-  }
+  conn = connection_array[i];
+  //log_fn(LOG_DEBUG,"socket %d has something to read.",conn->s);
 
+  if(
+      /* XXX does POLLHUP also mean it's definitely broken? */
 #ifdef MS_WINDOWS
- error:
+      (poll_array[i].revents & POLLERR) ||
 #endif
-  if(retval < 0) { /* this connection is broken. remove it */
-    log_fn(LOG_INFO,"%s connection broken, removing.", conn_type_to_string[conn->type]); 
-    connection_remove(conn);
-    connection_free(conn);
-    if(i<nfds) { /* we just replaced the one at i with a new one.
-                    process it too. */
-      if(poll_array[i].revents & (POLLIN|POLLHUP|POLLERR))
-        /* something to read */
+    connection_handle_read(conn) < 0)
+    {
+      /* this connection is broken. remove it */
+      log_fn(LOG_INFO,"%s connection broken, removing.", conn_type_to_string[conn->type]); 
+      connection_remove(conn);
+      connection_free(conn);
+      if(i<nfds) { /* we just replaced the one at i with a new one. process it too. */
         conn_read(i);
+      }
     }
-  }
 }
 
 static void conn_write(int i) {
-  int retval;
   connection_t *conn;
 
-  conn = connection_array[i];
-//  log_fn(LOG_DEBUG,"socket %d wants to write.",conn->s);
+  if(!(poll_array[i].revents & POLLOUT))
+    return; /* this conn doesn't want to write */
 
-  if(connection_is_listener(conn)) {
-    log_fn(LOG_DEBUG,"Got a listener socket. Can't happen!");
-    retval = -1;
-  } else {
-    /* else it's an OP, OR, or exit */
-    retval = connection_flush_buf(conn); /* conns in CONNECTING state will fall through... */
-    if(retval == 0) { /* it's done flushing */
-      retval = connection_finished_flushing(conn); /* ...and get handled here. */
-    }
-  }
+  conn = connection_array[i];
+  //log_fn(LOG_DEBUG,"socket %d wants to write.",conn->s);
 
-  if(retval < 0) { /* this connection is broken. remove it. */
+  if(connection_handle_write(conn) < 0) { /* this connection is broken. remove it. */
     log_fn(LOG_DEBUG,"%s connection broken, removing.", conn_type_to_string[conn->type]);
     connection_remove(conn);
     connection_free(conn);
-    if(i<nfds) { /* we just replaced the one at i with a new one.
-                    process it too. */
-      if(poll_array[i].revents & POLLOUT) /* something to write */
+    if(i<nfds) { /* we just replaced the one at i with a new one. process it too. */
         conn_write(i);
     }
   }
@@ -346,7 +310,7 @@
   }
 }
 
-static int prepare_for_poll(int *timeout) {
+static int prepare_for_poll(void) {
   int i;
 //  connection_t *conn = NULL;
   connection_t *tmpconn;
@@ -434,45 +398,9 @@
     current_second = now.tv_sec; /* remember which second it is, for next time */
   }
 
-  *timeout = 1000 - (now.tv_usec / 1000); /* how many milliseconds til the next second? */
-
-  return 0;
+  return (1000 - (now.tv_usec / 1000)); /* how many milliseconds til the next second? */
 }
 
-
-
-/* Link padding stuff left here for fun. Not used now. */
-#if 0
-  if(options.LinkPadding) {
-    /* now check which conn wants to speak soonest */
-    for(i=0;i<nfds;i++) {
-      tmpconn = connection_array[i];
-      if(!connection_speaks_cells(tmpconn))
-        continue; /* this conn type doesn't send cells */
-      if(!connection_state_is_open(tmpconn))
-        continue; /* only conns in state 'open' have a valid send_timeval */ 
-      while(tv_cmp(&tmpconn->send_timeval,&now) <= 0) { /* send_timeval has already passed, let it send a cell */
-        connection_send_cell(tmpconn);
-      }
-      if(!conn || tv_cmp(&tmpconn->send_timeval, &soonest) < 0) { /* this is the best choice so far */
-        conn = tmpconn;
-        soonest.tv_sec = conn->send_timeval.tv_sec;
-        soonest.tv_usec = conn->send_timeval.tv_usec;
-      }
-    }
-
-    if(conn) { /* we might want to set *timeout sooner */
-      ms_until_conn = (soonest.tv_sec - now.tv_sec)*1000 +
-                    (soonest.tv_usec - now.tv_usec)/1000;
-//      log(LOG_DEBUG,"prepare_for_poll(): conn %d times out in %d ms.",conn->s, ms_until_conn);
-      if(ms_until_conn < *timeout) { /* use the new one */
-//        log(LOG_DEBUG,"prepare_for_poll(): conn %d soonest, in %d ms.",conn->s,ms_until_conn);
-        *timeout = ms_until_conn;
-      }
-    }
-  }
-#endif
-
 static int do_main_loop(void) {
   int i;
   int timeout;
@@ -516,7 +444,7 @@
 
   /* start up the necessary connections based on which ports are
    * non-zero. This is where we try to connect to all the other ORs,
-   * and start the listeners
+   * and start the listeners.
    */
   retry_all_connections((uint16_t) options.ORPort,
                         (uint16_t) options.APPort,
@@ -543,17 +471,10 @@
       please_reap_children = 0;
     }
 #endif /* signal stuff */
-    if(prepare_for_poll(&timeout) < 0) {
-      log(LOG_DEBUG,"do_main_loop(): prepare_for_poll failed, exiting.");
-      return -1;
-    }
-    /* now timeout is the value we'll hand to poll. It's either -1, meaning
-     * don't timeout, else it indicates the soonest event (either the
-     * one-second rollover for refilling receiver buckets, or the soonest
-     * conn that needs to send a cell)
-     */
 
-    /* poll until we have an event, or it's time to do something */
+    timeout = prepare_for_poll();
+
+    /* poll until we have an event, or the second ends */
     poll_result = poll(poll_array, nfds, timeout);
 
 #if 0 /* let catch() handle things like ^c, and otherwise don't worry about it */
@@ -567,16 +488,11 @@
     if(poll_result > 0) { /* we have at least one connection to deal with */
       /* do all the reads and errors first, so we can detect closed sockets */
       for(i=0;i<nfds;i++)
-        if(poll_array[i].revents & (POLLIN|POLLHUP|POLLERR))
-          /* something to read, or an error. */
-          conn_read(i); /* this also blows away broken connections */
-/* see http://www.greenend.org.uk/rjk/2001/06/poll.html for discussion
- * of POLLIN vs POLLHUP */
+        conn_read(i); /* this also blows away broken connections */
 
       /* then do the writes */
       for(i=0;i<nfds;i++)
-        if(poll_array[i].revents & POLLOUT) /* something to write */
-          conn_write(i);
+        conn_write(i);
 
       /* any of the conns need to be closed now? */
       for(i=0;i<nfds;i++)

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.111
retrieving revision 1.112
diff -u -d -r1.111 -r1.112
--- or.h	4 Sep 2003 16:05:08 -0000	1.111
+++ or.h	5 Sep 2003 06:04:03 -0000	1.112
@@ -94,7 +94,7 @@
 #include "../common/log.h"
 #include "../common/util.h"
 
-#define RECOMMENDED_SOFTWARE_VERSIONS "0.0.2pre6,0.0.2pre7"
+#define RECOMMENDED_SOFTWARE_VERSIONS "0.0.2pre8"
 
 #define MAXCONNECTIONS 1000 /* upper bound on max connections.
                               can be lowered by config file */
@@ -131,6 +131,7 @@
 #define CPUWORKER_TASK_ONION CPUWORKER_STATE_BUSY_ONION
 #define CPUWORKER_TASK_HANDSHAKE CPUWORKER_STATE_BUSY_HANDSHAKE
 
+#ifndef TOR_TLS
 /* how to read these states:
  * foo_CONN_STATE_bar_baz:
  * "I am acting as a bar, currently in stage baz of talking with a foo."
@@ -145,6 +146,11 @@
 #define OR_CONN_STATE_SERVER_SENDING_AUTH 7 /* writing auth and nonce */
 #define OR_CONN_STATE_SERVER_NONCE_WAIT 8 /* waiting for confirmation of nonce */
 #define OR_CONN_STATE_OPEN 9 /* ready to send/receive cells. */
+#else
+#define OR_CONN_STATE_CONNECTING 0 /* waiting for connect() to finish */
+#define OR_CONN_STATE_HANDSHAKING 1 /* SSL is handshaking, not done yet */
+#define OR_CONN_STATE_OPEN 2 /* ready to send/receive cells. */
+#endif
 
 #define EXIT_CONN_STATE_RESOLVING 0 /* waiting for response from dns farm */
 #define EXIT_CONN_STATE_CONNECTING 1 /* waiting for connect() to finish */
@@ -272,73 +278,72 @@
 
 struct connection_t { 
 
-/* Used by all types: */
-
   uint8_t type;
-  int state;
-  uint8_t wants_to_read;
+  uint8_t state;
+  uint8_t wants_to_read; /* should we start reading again once
+                          * the bandwidth throttler allows it?
+                          */
   int s; /* our socket */
-  int poll_index;
-  int marked_for_close;
+  int poll_index; /* index of this conn into the poll_array */
+  int marked_for_close; /* should we close this conn on the next
+                         * iteration of the main loop?
+                         */
 
   char *inbuf;
-  int inbuflen;
-  int inbuf_datalen;
-  int inbuf_reached_eof;
-  long timestamp_lastread;
+  int inbuflen; /* how many bytes are alloc'ed for inbuf? */
+  int inbuf_datalen; /* how many bytes of data are on inbuf? */
+  int inbuf_reached_eof; /* did read() return 0 on this conn? */
+  long timestamp_lastread; /* when was the last time poll() said we could read? */
 
   char *outbuf;
   int outbuflen; /* how many bytes are allocated for the outbuf? */
   int outbuf_flushlen; /* how much data should we try to flush from the outbuf? */
   int outbuf_datalen; /* how much data is there total on the outbuf? */
-  long timestamp_lastwritten;
-
-  long timestamp_created;
+  long timestamp_lastwritten; /* when was the last time poll() said we could write? */
 
-/* used by OR and OP: */
+  long timestamp_created; /* when was this connection_t created? */
 
-  uint32_t bandwidth; /* connection bandwidth */
+  uint32_t bandwidth; /* connection bandwidth. Set to -1 for non-OR conns. */
   int receiver_bucket; /* when this hits 0, stop receiving. Every second we
                         * add 'bandwidth' to this, capping it at 10*bandwidth.
+			* Set to -1 for non-OR conns.
                         */
-  struct timeval send_timeval; /* for determining when to send the next cell */
+
+  uint32_t addr; /* these two uniquely identify a router. Both in host order. */
+  uint16_t port; /* if non-zero, they identify the guy on the other end
+                  * of the connection. */
+  char *address; /* FQDN (or IP) of the guy on the other end.
+                  * strdup into this, because free_connection frees it
+                  */
+  crypto_pk_env_t *pkey; /* public RSA key for the other side */
+
+#ifndef TOR_TLS
+/* Used only by OR connections: */
 
   /* link encryption */
   crypto_cipher_env_t *f_crypto;
   crypto_cipher_env_t *b_crypto;
 
-//  struct timeval lastsend; /* time of last transmission to the client */
-//  struct timeval interval; /* transmission interval */
-
-  uint32_t addr; /* these two uniquely identify a router. Both in host order. */
-  uint16_t port;
+  char nonce[8];
+#endif
 
-/* used by exit and ap: */
+/* Used only by edge connections: */
   char stream_id[STREAM_ID_SIZE];
-  struct connection_t *next_stream;
+  struct connection_t *next_stream; /* points to the next stream at this edge, if any */
   struct crypt_path_t *cpath_layer; /* a pointer to which node in the circ this conn exits at */
-  int package_window;
-  int deliver_window;
-  int done_sending;
-  int done_receiving;
+  int package_window; /* how many more relay cells can i send into the circuit? */
+  int deliver_window; /* how many more relay cells can end at me? */
 
-/* Used by ap: */
-  char socks_version; 
-  char read_username;
+  int done_sending; /* for half-open connections; not used currently */
+  int done_receiving;
 
-/* Used by exit and ap: */
-  char *dest_addr;
+/* Used only by AP connections: */
+  char socks_version; /* what socks version are they speaking at me? */
+  char read_username; /* have i read the username yet? */
+  char *dest_addr; /* what address and port are this stream's destination? */
   uint16_t dest_port; /* host order */
 
-/* Used by everyone */
-  char *address; /* strdup into this, because free_connection frees it */
-/* Used for cell connections */
-  crypto_pk_env_t *pkey; /* public RSA key for the other side */
-
-/* Used while negotiating OR/OR connections */
-  char nonce[8];
-
-/* Used by worker connections */
+/* Used only by worker connections: */
   int num_processed; /* statistics kept by dns worker */
   struct circuit_t *circ; /* by cpu worker to know who he's working for */
 };
@@ -392,7 +397,7 @@
   uint32_t addr;
   uint16_t port;
 
-  char state;
+  uint8_t state;
 #define CPATH_STATE_CLOSED 0
 #define CPATH_STATE_AWAITING_KEYS 1
 #define CPATH_STATE_OPEN 2
@@ -429,9 +434,9 @@
 
   char onionskin[DH_ONIONSKIN_LEN]; /* for storage while onionskin pending */
   long timestamp_created;
-  char dirty; /* whether this circuit has been used yet */
+  uint8_t dirty; /* whether this circuit has been used yet */
 
-  int state;
+  uint8_t state;
 
 //  unsigned char *onion; /* stores the onion when state is CONN_STATE_OPEN_WAIT */
 //  uint32_t onionlen; /* total onion length */
@@ -612,6 +617,7 @@
 /* start all connections that should be up but aren't */
 int retry_all_connections(uint16_t or_listenport, uint16_t ap_listenport, uint16_t dir_listenport);
 
+int connection_handle_read(connection_t *conn);
 int connection_read_to_buf(connection_t *conn);
 
 int connection_fetch_from_buf(char *string, int len, connection_t *conn);
@@ -620,6 +626,7 @@
 int connection_find_on_inbuf(char *string, int len, connection_t *conn);
 int connection_wants_to_flush(connection_t *conn);
 int connection_flush_buf(connection_t *conn);
+int connection_handle_write(connection_t *conn);
 
 int connection_write_to_buf(char *string, int len, connection_t *conn);
 void connection_send_cell(connection_t *conn);