Browse Source

Split channel_t into channel_t and channel_listener_t; get rid of that big union

Andrea Shepard 11 years ago
parent
commit
3f4b95b1a3
14 changed files with 911 additions and 637 deletions
  1. 423 235
      src/or/channel.c
  2. 242 177
      src/or/channel.h
  3. 127 114
      src/or/channeltls.c
  4. 2 2
      src/or/channeltls.h
  5. 11 20
      src/or/circuitbuild.c
  6. 6 13
      src/or/circuitlist.c
  7. 2 3
      src/or/circuituse.c
  8. 8 9
      src/or/command.c
  9. 1 1
      src/or/command.h
  10. 1 2
      src/or/connection_edge.c
  11. 4 10
      src/or/connection_or.c
  12. 2 0
      src/or/main.c
  13. 53 12
      src/or/or.h
  14. 29 39
      src/or/relay.c

File diff suppressed because it is too large
+ 423 - 235
src/or/channel.c


+ 242 - 177
src/or/channel.h

@@ -12,7 +12,7 @@
 #include "or.h"
 
 /* Channel handler function pointer typedefs */
-typedef void (*channel_listener_fn_ptr)(channel_t *, channel_t *);
+typedef void (*channel_listener_fn_ptr)(channel_listener_t *, channel_t *);
 typedef void (*channel_cell_handler_fn_ptr)(channel_t *, cell_t *);
 typedef void (*channel_var_cell_handler_fn_ptr)(channel_t *, var_cell_t *);
 
@@ -37,12 +37,6 @@ struct channel_s {
   /* Should we expect to see this channel in the channel lists? */
   unsigned char registered:1;
 
-  /** Set this if this channel is created in CHANNEL_STATE_LISTEN, so
-   * lower-layer close methods that see the channel in CHANNEL_STATE_CLOSING
-   * know.
-   */
-  unsigned int is_listener:1;
-
   /** Why did we close?
    */
   enum {
@@ -67,171 +61,210 @@ struct channel_s {
   /* Optional method to dump transport-specific statistics on the channel */
   void (*dumpstats)(channel_t *, int);
 
-  union {
-    struct {
-      /* Registered listen handler to call on incoming connection */
-      channel_listener_fn_ptr listener;
-
-      /* List of pending incoming connections */
-      smartlist_t *incoming_list;
-
-      /* Timestamps for listeners */
-      time_t timestamp_accepted;
-
-      /* Counters for listeners */
-      uint64_t n_accepted;
-    } listener;
-    struct {
-      /* Registered handlers for incoming cells */
-      channel_cell_handler_fn_ptr cell_handler;
-      channel_var_cell_handler_fn_ptr var_cell_handler;
-
-      /* Methods implemented by the lower layer */
-
-      /*
-       * Ask the underlying transport what the remote endpoint address is, in
-       * a tor_addr_t.  This is optional and subclasses may leave this NULL.
-       * If they implement it, they should write the address out to the
-       * provided tor_addr_t *, and return 1 if successful or 0 if no address
-       * available.
-       */
-      int (*get_remote_addr)(channel_t *, tor_addr_t *);
-      /*
-       * Get a text description of the remote endpoint; canonicalized if the
-       * arg is 0, or the one we originally connected to/received from if it's
-       * 1.
-       */
-      const char * (*get_remote_descr)(channel_t *, int);
-      /* Check if the lower layer has queued writes */
-      int (*has_queued_writes)(channel_t *);
-      /*
-       * If the second param is zero, ask the lower layer if this is
-       * 'canonical', for a transport-specific definition of canonical; if
-       * it is 1, ask if the answer to the preceding query is safe to rely
-       * on.
-       */
-      int (*is_canonical)(channel_t *, int);
-      /* Check if this channel matches a specified extend_info_t */
-      int (*matches_extend_info)(channel_t *, extend_info_t *);
-      /* Check if this channel matches a target address when extending */
-      int (*matches_target)(channel_t *, const tor_addr_t *);
-      /* Write a cell to an open channel */
-      int (*write_cell)(channel_t *, cell_t *);
-      /* Write a packed cell to an open channel */
-      int (*write_packed_cell)(channel_t *, packed_cell_t *);
-      /* Write a variable-length cell to an open channel */
-      int (*write_var_cell)(channel_t *, var_cell_t *);
-
-      /*
-       * Hash of the public RSA key for the other side's identity key, or
-       * zeroes if the other side hasn't shown us a valid identity key.
-       */
-      char identity_digest[DIGEST_LEN];
-      /* Nickname of the OR on the other side, or NULL if none. */
-      char *nickname;
-
-      /*
-       * Linked list of channels with the same identity digest, for the
-       * digest->channel map
-       */
-      channel_t *next_with_same_id, *prev_with_same_id;
-
-      /* List of incoming cells to handle */
-      smartlist_t *incoming_queue;
-
-      /* List of queued outgoing cells */
-      smartlist_t *outgoing_queue;
-
-      /* Circuit stuff for use by relay.c */
-
-      /*
-       * Double-linked ring of circuits with queued cells waiting for room to
-       * free up on this connection's outbuf.  Every time we pull cells from
-       * a circuit, we advance this pointer to the next circuit in the ring.
-       */
-      struct circuit_t *active_circuits;
-      /*
-       * Priority queue of cell_ewma_t for circuits with queued cells waiting
-       * for room to free up on this connection's outbuf.  Kept in heap order
-       * according to EWMA.
-       *
-       * This is redundant with active_circuits; if we ever decide only to use
-       * the cell_ewma algorithm for choosing circuits, we can remove
-       * active_circuits.
-       */
-      smartlist_t *active_circuit_pqueue;
-      /*
-       * The tick on which the cell_ewma_ts in active_circuit_pqueue last had
-       * their ewma values rescaled.
-       */
-      unsigned active_circuit_pqueue_last_recalibrated;
-
-      /* Circuit ID generation stuff for use by circuitbuild.c */
-
-      /*
-       * When we send CREATE cells along this connection, which half of the
-       * space should we use?
-       */
-      circ_id_type_t circ_id_type:2;
-      /*
-       * Which circ_id do we try to use next on this connection?  This is
-       * always in the range 0..1<<15-1.
-       */
-      circid_t next_circ_id;
-
-      /* How many circuits use this connection as p_chan or n_chan? */
-      int n_circuits;
-
-      /*
-       * True iff this channel shouldn't get any new circs attached to it,
-       * because the connection is too old, or because there's a better one.
-       * More generally, this flag is used to note an unhealthy connection;
-       * for example, if a bad connection fails we shouldn't assume that the
-       * router itself has a problem.
-       */
-      unsigned int is_bad_for_new_circs:1;
-
-      /** True iff we have decided that the other end of this connection
-       * is a client.  Channels with this flag set should never be used
-       * to satisfy an EXTEND request.  */
-      unsigned int is_client:1;
-
-      /** Set if the channel was initiated remotely (came from a listener) */
-      unsigned int is_incoming:1;
-
-      /** Set by lower layer if this is local; i.e., everything it communicates
-       * with for this channel returns true for is_local_addr().  This is used
-       * to decide whether to declare reachability when we receive something on
-       * this channel in circuitbuild.c
-       */
-      unsigned int is_local:1;
-
-      /** Channel timestamps for cell channels */
-      time_t timestamp_client; /* Client used this, according to relay.c */
-      time_t timestamp_drained; /* Output queue empty */
-      time_t timestamp_recv; /* Cell received from lower layer */
-      time_t timestamp_xmit; /* Cell sent to lower layer */
-
-      /* Timestamp for relay.c */
-      time_t timestamp_last_added_nonpadding;
-
-      /** Unique ID for measuring direct network status requests;vtunneled ones
-       * come over a circuit_t, which has a dirreq_id field as well, but is a
-       * distinct namespace. */
-      uint64_t dirreq_id;
-
-      /** Channel counters for cell channels */
-      uint64_t n_cells_recved;
-      uint64_t n_cells_xmitted;
-    } cell_chan;
-  } u;
+  /* Registered handlers for incoming cells */
+  channel_cell_handler_fn_ptr cell_handler;
+  channel_var_cell_handler_fn_ptr var_cell_handler;
+
+  /* Methods implemented by the lower layer */
+
+  /*
+   * Ask the underlying transport what the remote endpoint address is, in
+   * a tor_addr_t.  This is optional and subclasses may leave this NULL.
+   * If they implement it, they should write the address out to the
+   * provided tor_addr_t *, and return 1 if successful or 0 if no address
+   * available.
+   */
+  int (*get_remote_addr)(channel_t *, tor_addr_t *);
+  /*
+   * Get a text description of the remote endpoint; canonicalized if the
+   * arg is 0, or the one we originally connected to/received from if it's
+   * 1.
+   */
+  const char * (*get_remote_descr)(channel_t *, int);
+  /* Check if the lower layer has queued writes */
+  int (*has_queued_writes)(channel_t *);
+  /*
+   * If the second param is zero, ask the lower layer if this is
+   * 'canonical', for a transport-specific definition of canonical; if
+   * it is 1, ask if the answer to the preceding query is safe to rely
+   * on.
+   */
+  int (*is_canonical)(channel_t *, int);
+  /* Check if this channel matches a specified extend_info_t */
+  int (*matches_extend_info)(channel_t *, extend_info_t *);
+  /* Check if this channel matches a target address when extending */
+  int (*matches_target)(channel_t *, const tor_addr_t *);
+  /* Write a cell to an open channel */
+  int (*write_cell)(channel_t *, cell_t *);
+  /* Write a packed cell to an open channel */
+  int (*write_packed_cell)(channel_t *, packed_cell_t *);
+  /* Write a variable-length cell to an open channel */
+  int (*write_var_cell)(channel_t *, var_cell_t *);
+
+  /*
+   * Hash of the public RSA key for the other side's identity key, or
+   * zeroes if the other side hasn't shown us a valid identity key.
+   */
+  char identity_digest[DIGEST_LEN];
+  /* Nickname of the OR on the other side, or NULL if none. */
+  char *nickname;
+
+  /*
+   * Linked list of channels with the same identity digest, for the
+   * digest->channel map
+   */
+  channel_t *next_with_same_id, *prev_with_same_id;
+
+  /* List of incoming cells to handle */
+  smartlist_t *incoming_queue;
+
+  /* List of queued outgoing cells */
+  smartlist_t *outgoing_queue;
+
+  /* Circuit stuff for use by relay.c */
+
+  /*
+   * Double-linked ring of circuits with queued cells waiting for room to
+   * free up on this connection's outbuf.  Every time we pull cells from
+   * a circuit, we advance this pointer to the next circuit in the ring.
+   */
+  struct circuit_t *active_circuits;
+  /*
+   * Priority queue of cell_ewma_t for circuits with queued cells waiting
+   * for room to free up on this connection's outbuf.  Kept in heap order
+   * according to EWMA.
+   *
+   * This is redundant with active_circuits; if we ever decide only to use
+   * the cell_ewma algorithm for choosing circuits, we can remove
+   * active_circuits.
+   */
+  smartlist_t *active_circuit_pqueue;
+  /*
+   * The tick on which the cell_ewma_ts in active_circuit_pqueue last had
+   * their ewma values rescaled.
+   */
+  unsigned active_circuit_pqueue_last_recalibrated;
+
+  /* Circuit ID generation stuff for use by circuitbuild.c */
+
+  /*
+   * When we send CREATE cells along this connection, which half of the
+   * space should we use?
+   */
+  circ_id_type_t circ_id_type:2;
+  /*
+   * Which circ_id do we try to use next on this connection?  This is
+   * always in the range 0..1<<15-1.
+   */
+  circid_t next_circ_id;
+
+  /* How many circuits use this connection as p_chan or n_chan? */
+  int n_circuits;
+
+  /*
+   * True iff this channel shouldn't get any new circs attached to it,
+   * because the connection is too old, or because there's a better one.
+   * More generally, this flag is used to note an unhealthy connection;
+   * for example, if a bad connection fails we shouldn't assume that the
+   * router itself has a problem.
+   */
+  unsigned int is_bad_for_new_circs:1;
+
+  /** True iff we have decided that the other end of this connection
+   * is a client.  Channels with this flag set should never be used
+   * to satisfy an EXTEND request.  */
+  unsigned int is_client:1;
+
+  /** Set if the channel was initiated remotely (came from a listener) */
+  unsigned int is_incoming:1;
+
+  /** Set by lower layer if this is local; i.e., everything it communicates
+   * with for this channel returns true for is_local_addr().  This is used
+   * to decide whether to declare reachability when we receive something on
+   * this channel in circuitbuild.c
+   */
+  unsigned int is_local:1;
+
+  /** Channel timestamps for cell channels */
+  time_t timestamp_client; /* Client used this, according to relay.c */
+  time_t timestamp_drained; /* Output queue empty */
+  time_t timestamp_recv; /* Cell received from lower layer */
+  time_t timestamp_xmit; /* Cell sent to lower layer */
+
+  /* Timestamp for relay.c */
+  time_t timestamp_last_added_nonpadding;
+
+  /** Unique ID for measuring direct network status requests;vtunneled ones
+   * come over a circuit_t, which has a dirreq_id field as well, but is a
+   * distinct namespace. */
+  uint64_t dirreq_id;
+
+  /** Channel counters for cell channels */
+  uint64_t n_cells_recved;
+  uint64_t n_cells_xmitted;
+};
+
+struct channel_listener_s {
+  /* Current channel listener state */
+  channel_listener_state_t state;
+
+  /* Globally unique ID number for a channel over the lifetime of a Tor
+   * process.
+   */
+  uint64_t global_identifier;
+
+  /* Should we expect to see this channel in the channel lists? */
+  unsigned char registered:1;
+
+  /** Why did we close?
+   */
+  enum {
+    CHANNEL_LISTENER_NOT_CLOSING = 0,
+    CHANNEL_LISTENER_CLOSE_REQUESTED,
+    CHANNEL_LISTENER_CLOSE_FROM_BELOW,
+    CHANNEL_LISTENER_CLOSE_FOR_ERROR
+  } reason_for_closing;
+
+  /* Timestamps for both cell channels and listeners */
+  time_t timestamp_created; /* Channel created */
+  time_t timestamp_active; /* Any activity */
+
+  /* Methods implemented by the lower layer */
+
+  /* Free a channel */
+  void (*free)(channel_listener_t *);
+  /* Close an open channel */
+  void (*close)(channel_listener_t *);
+  /* Describe the transport subclass for this channel */
+  const char * (*describe_transport)(channel_listener_t *);
+  /* Optional method to dump transport-specific statistics on the channel */
+  void (*dumpstats)(channel_listener_t *, int);
+
+  /* Registered listen handler to call on incoming connection */
+  channel_listener_fn_ptr listener;
+
+  /* List of pending incoming connections */
+  smartlist_t *incoming_list;
+
+  /* Timestamps for listeners */
+  time_t timestamp_accepted;
+
+  /* Counters for listeners */
+  uint64_t n_accepted;
 };
 
 /* Channel state manipulations */
 
 int channel_state_is_valid(channel_state_t state);
+int channel_listener_state_is_valid(channel_listener_state_t state);
+
 int channel_state_can_transition(channel_state_t from, channel_state_t to);
+int channel_listener_state_can_transition(channel_listener_state_t from,
+                                          channel_listener_state_t to);
+
 const char * channel_state_to_string(channel_state_t state);
+const char *
+channel_listener_state_to_string(channel_listener_state_t state);
 
 /* Abstract channel operations */
 
@@ -240,12 +273,16 @@ void channel_write_cell(channel_t *chan, cell_t *cell);
 void channel_write_packed_cell(channel_t *chan, packed_cell_t *cell);
 void channel_write_var_cell(channel_t *chan, var_cell_t *cell);
 
+void channel_listener_mark_for_close(channel_listener_t *chan_l);
+
 /* Channel callback registrations */
 
 /* Listener callback */
-channel_listener_fn_ptr channel_get_listener_fn(channel_t *chan);
-void channel_set_listener_fn(channel_t *chan,
-                             channel_listener_fn_ptr listener);
+channel_listener_fn_ptr
+channel_listener_get_listener_fn(channel_listener_t *chan);
+
+void channel_listener_set_listener_fn(channel_listener_t *chan,
+                                      channel_listener_fn_ptr listener);
 
 /* Incoming cell callbacks */
 channel_cell_handler_fn_ptr channel_get_cell_handler(channel_t *chan);
@@ -258,16 +295,18 @@ void channel_set_cell_handlers(channel_t *chan,
                                channel_var_cell_handler_fn_ptr
                                  var_cell_handler);
 
-/* Clean up closed channels periodically; called from run_scheduled_events()
- * in main.c
+/* Clean up closed channels and channel listeners periodically; these are
+ * called from run_scheduled_events() in main.c.
  */
 void channel_run_cleanup(void);
+void channel_listener_run_cleanup(void);
 
 /* Close all channels and deallocate everything */
 void channel_free_all(void);
 
 /* Dump some statistics in the log */
 void channel_dumpstats(int severity);
+void channel_listener_dumpstats(int severity);
 
 #ifdef _TOR_CHANNEL_INTERNAL
 
@@ -277,20 +316,29 @@ void channel_dumpstats(int severity);
  * constructors.
  */
 
-void channel_init_for_cells(channel_t *chan);
-void channel_init_listener(channel_t *chan);
+void channel_init(channel_t *chan);
+void channel_init_listener(channel_listener_t *chan);
 
 /* Channel registration/unregistration */
 void channel_register(channel_t *chan);
 void channel_unregister(channel_t *chan);
 
+/* Channel listener registration/unregistration */
+void channel_listener_register(channel_listener_t *chan_l);
+void channel_listener_unregister(channel_listener_t *chan_l);
+
 /* Close from below */
 void channel_close_from_lower_layer(channel_t *chan);
 void channel_close_for_error(channel_t *chan);
 void channel_closed(channel_t *chan);
 
+void channel_listener_close_from_lower_layer(channel_listener_t *chan_l);
+void channel_listener_close_for_error(channel_listener_t *chan_l);
+void channel_listener_closed(channel_listener_t *chan_l);
+
 /* Free a channel */
 void channel_free(channel_t *chan);
+void channel_listener_free(channel_listener_t *chan_l);
 
 /* State/metadata setters */
 
@@ -306,17 +354,24 @@ void channel_set_remote_end(channel_t *chan,
                             const char *identity_digest,
                             const char *nickname);
 
+void channel_listener_change_state(channel_listener_t *chan_l,
+                                   channel_listener_state_t to_state);
+
 /* Timestamp updates */
 void channel_timestamp_created(channel_t *chan);
-void channel_timestamp_accepted(channel_t *chan);
 void channel_timestamp_active(channel_t *chan);
 void channel_timestamp_drained(channel_t *chan);
 void channel_timestamp_recv(channel_t *chan);
 void channel_timestamp_xmit(channel_t *chan);
 
+void channel_listener_timestamp_created(channel_listener_t *chan_l);
+void channel_listener_timestamp_active(channel_listener_t *chan_l);
+void channel_listener_timestamp_accepted(channel_listener_t *chan_l);
+
 /* Incoming channel handling */
-void channel_process_incoming(channel_t *listener);
-void channel_queue_incoming(channel_t *listener, channel_t *incoming);
+void channel_listener_process_incoming(channel_listener_t *listener);
+void channel_listener_queue_incoming(channel_listener_t *listener,
+                                     channel_t *incoming);
 
 /* Incoming cell handling */
 void channel_process_cells(channel_t *chan);
@@ -401,19 +456,29 @@ int channel_matches_target_addr_for_extend(channel_t *chan,
 void channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd);
 void channel_timestamp_client(channel_t *chan);
 
+const char * channel_listener_describe_transport(channel_listener_t *chan_l);
+void channel_listener_dump_statistics(channel_listener_t *chan_l,
+                                      int severity);
+void channel_listener_dump_transport_statistics(channel_listener_t *chan_l,
+                                                int severity);
+
 /* Timestamp queries */
 time_t channel_when_created(channel_t *chan);
-time_t channel_when_last_accepted(channel_t *chan);
 time_t channel_when_last_active(channel_t *chan);
 time_t channel_when_last_client(channel_t *chan);
 time_t channel_when_last_drained(channel_t *chan);
 time_t channel_when_last_recv(channel_t *chan);
 time_t channel_when_last_xmit(channel_t *chan);
 
+time_t channel_listener_when_created(channel_listener_t *chan_l);
+time_t channel_listener_when_last_active(channel_listener_t *chan_l);
+time_t channel_listener_when_last_accepted(channel_listener_t *chan_l);
+
 /* Counter queries */
-uint64_t channel_count_accepted(channel_t *chan);
 uint64_t channel_count_recved(channel_t *chan);
 uint64_t channel_count_xmitted(channel_t *chan);
 
+uint64_t channel_listener_count_accepted(channel_listener_t *chan_l);
+
 #endif
 

+ 127 - 114
src/or/channeltls.c

@@ -42,7 +42,7 @@ uint64_t stats_n_authenticate_cells_processed = 0;
 uint64_t stats_n_authorize_cells_processed = 0;
 
 /** Active listener, if any */
-channel_tls_t *channel_tls_listener = NULL;
+channel_listener_t *channel_tls_listener = NULL;
 
 /* channel_tls_t method declarations */
 
@@ -66,6 +66,12 @@ static int channel_tls_write_packed_cell_method(channel_t *chan,
 static int channel_tls_write_var_cell_method(channel_t *chan,
                                              var_cell_t *var_cell);
 
+/* channel_listener_tls_t method declarations */
+
+static void channel_tls_listener_close_method(channel_listener_t *chan_l);
+static const char *
+channel_tls_listener_describe_transport_method(channel_listener_t *chan_l);
+
 /** Handle incoming cells for the handshake stuff here rather than
  * passing them on up. */
 
@@ -97,20 +103,19 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
 {
   channel_tls_t *tlschan = tor_malloc_zero(sizeof(*tlschan));
   channel_t *chan = TLS_CHAN_TO_BASE(tlschan);
-  channel_init_for_cells(chan);
+  channel_init(chan);
   chan->state = CHANNEL_STATE_OPENING;
   chan->close = channel_tls_close_method;
   chan->describe_transport = channel_tls_describe_transport_method;
-  chan->u.cell_chan.get_remote_addr = channel_tls_get_remote_addr_method;
-  chan->u.cell_chan.get_remote_descr = channel_tls_get_remote_descr_method;
-  chan->u.cell_chan.has_queued_writes = channel_tls_has_queued_writes_method;
-  chan->u.cell_chan.is_canonical = channel_tls_is_canonical_method;
-  chan->u.cell_chan.matches_extend_info =
-    channel_tls_matches_extend_info_method;
-  chan->u.cell_chan.matches_target = channel_tls_matches_target_method;
-  chan->u.cell_chan.write_cell = channel_tls_write_cell_method;
-  chan->u.cell_chan.write_packed_cell = channel_tls_write_packed_cell_method;
-  chan->u.cell_chan.write_var_cell = channel_tls_write_var_cell_method;
+  chan->get_remote_addr = channel_tls_get_remote_addr_method;
+  chan->get_remote_descr = channel_tls_get_remote_descr_method;
+  chan->has_queued_writes = channel_tls_has_queued_writes_method;
+  chan->is_canonical = channel_tls_is_canonical_method;
+  chan->matches_extend_info = channel_tls_matches_extend_info_method;
+  chan->matches_target = channel_tls_matches_target_method;
+  chan->write_cell = channel_tls_write_cell_method;
+  chan->write_packed_cell = channel_tls_write_packed_cell_method;
+  chan->write_var_cell = channel_tls_write_var_cell_method;
 
   log_debug(LD_CHANNEL,
             "In channel_tls_connect() for channel %p "
@@ -121,9 +126,8 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
   if (is_local_addr(addr)) channel_mark_local(chan);
   channel_mark_outgoing(chan);
 
-  chan->u.cell_chan.active_circuit_pqueue = smartlist_new();
-  chan->u.cell_chan.active_circuit_pqueue_last_recalibrated =
-    cell_ewma_get_tick();
+  chan->active_circuit_pqueue = smartlist_new();
+  chan->active_circuit_pqueue_last_recalibrated = cell_ewma_get_tick();
 
   /* Set up or_connection stuff */
   tlschan->conn = connection_or_connect(addr, port, id_digest, tlschan);
@@ -140,7 +144,7 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
   goto done;
 
  err:
-  smartlist_free(chan->u.cell_chan.active_circuit_pqueue);
+  smartlist_free(chan->active_circuit_pqueue);
   tor_free(tlschan);
   chan = NULL;
 
@@ -154,14 +158,14 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
 /**
  * Return the current channel_tls_t listener
  *
- * Returns the current listening channel for incoming TLS connections, or
+ * Returns the current channel listener for incoming TLS connections, or
  * NULL if none has been established
  */
 
-channel_t *
+channel_listener_t *
 channel_tls_get_listener(void)
 {
-  return TLS_CHAN_TO_BASE(channel_tls_listener);
+  return channel_tls_listener;
 }
 
 /**
@@ -171,30 +175,29 @@ channel_tls_get_listener(void)
  * and return that.
  */
 
-channel_t *
+channel_listener_t *
 channel_tls_start_listener(void)
 {
-  channel_tls_t *listener;
-  channel_t *lchan;
+  channel_listener_t *listener;
 
   if (!channel_tls_listener) {
     listener = tor_malloc_zero(sizeof(*listener));
-    lchan = TLS_CHAN_TO_BASE(listener);
-    channel_init_listener(lchan);
-    lchan->state = CHANNEL_STATE_LISTENING;
-    lchan->close = channel_tls_close_method;
-    lchan->describe_transport = channel_tls_describe_transport_method;
+    channel_init_listener(listener);
+    listener->state = CHANNEL_LISTENER_STATE_LISTENING;
+    listener->close = channel_tls_listener_close_method;
+    listener->describe_transport =
+      channel_tls_listener_describe_transport_method;
 
     channel_tls_listener = listener;
 
     log_debug(LD_CHANNEL,
-              "Starting TLS listener channel %p with global id " U64_FORMAT,
-              lchan, U64_PRINTF_ARG(lchan->global_identifier));
+              "Starting TLS channel listener %p with global id " U64_FORMAT,
+              listener, U64_PRINTF_ARG(listener->global_identifier));
 
-    channel_register(lchan);
-  } else lchan = TLS_CHAN_TO_BASE(channel_tls_listener);
+    channel_listener_register(listener);
+  } else listener = channel_tls_listener;
 
-  return lchan;
+  return listener;
 }
 
 /**
@@ -207,16 +210,13 @@ channel_tls_start_listener(void)
 void
 channel_tls_free_all(void)
 {
-  channel_t *base = NULL;
-
   log_debug(LD_CHANNEL,
             "Shutting down TLS channels...");
 
   if (channel_tls_listener) {
-    base = TLS_CHAN_TO_BASE(channel_tls_listener);
-    channel_unregister(base);
-    channel_mark_for_close(base);
-    channel_free(base);
+    channel_listener_unregister(channel_tls_listener);
+    channel_listener_mark_for_close(channel_tls_listener);
+    channel_listener_free(channel_tls_listener);
     channel_tls_listener = NULL;
   }
 
@@ -237,19 +237,18 @@ channel_tls_handle_incoming(or_connection_t *orconn)
   tor_assert(orconn);
   tor_assert(!(orconn->chan));
 
-  channel_init_for_cells(chan);
+  channel_init(chan);
   chan->state = CHANNEL_STATE_OPENING;
   chan->close = channel_tls_close_method;
   chan->describe_transport = channel_tls_describe_transport_method;
-  chan->u.cell_chan.get_remote_descr = channel_tls_get_remote_descr_method;
-  chan->u.cell_chan.has_queued_writes = channel_tls_has_queued_writes_method;
-  chan->u.cell_chan.is_canonical = channel_tls_is_canonical_method;
-  chan->u.cell_chan.matches_extend_info =
-    channel_tls_matches_extend_info_method;
-  chan->u.cell_chan.matches_target = channel_tls_matches_target_method;
-  chan->u.cell_chan.write_cell = channel_tls_write_cell_method;
-  chan->u.cell_chan.write_packed_cell = channel_tls_write_packed_cell_method;
-  chan->u.cell_chan.write_var_cell = channel_tls_write_var_cell_method;
+  chan->get_remote_descr = channel_tls_get_remote_descr_method;
+  chan->has_queued_writes = channel_tls_has_queued_writes_method;
+  chan->is_canonical = channel_tls_is_canonical_method;
+  chan->matches_extend_info = channel_tls_matches_extend_info_method;
+  chan->matches_target = channel_tls_matches_target_method;
+  chan->write_cell = channel_tls_write_cell_method;
+  chan->write_packed_cell = channel_tls_write_packed_cell_method;
+  chan->write_var_cell = channel_tls_write_var_cell_method;
 
   /* Link the channel and orconn to each other */
   tlschan->conn = orconn;
@@ -258,9 +257,8 @@ channel_tls_handle_incoming(or_connection_t *orconn)
   if (is_local_addr(&(TO_CONN(orconn)->addr))) channel_mark_local(chan);
   channel_mark_incoming(chan);
 
-  chan->u.cell_chan.active_circuit_pqueue = smartlist_new();
-  chan->u.cell_chan.active_circuit_pqueue_last_recalibrated =
-    cell_ewma_get_tick();
+  chan->active_circuit_pqueue = smartlist_new();
+  chan->active_circuit_pqueue_last_recalibrated = cell_ewma_get_tick();
 
   /* If we got one, we should register it */
   if (chan) channel_register(chan);
@@ -285,43 +283,13 @@ channel_tls_close_method(channel_t *chan)
 
   tor_assert(tlschan);
 
-  if (chan->is_listener) {
-    /*
-     * Listeners we just go ahead and change state through to CLOSED, but
-     * make sure to check if they're channel_tls_listener to NULL it out.
-     */
-    if (chan == TLS_CHAN_TO_BASE(channel_tls_listener))
-      channel_tls_listener = NULL;
-
-    if (!(chan->state == CHANNEL_STATE_CLOSING ||
-          chan->state == CHANNEL_STATE_CLOSED ||
-          chan->state == CHANNEL_STATE_ERROR)) {
-      channel_change_state(chan, CHANNEL_STATE_CLOSING);
-    }
-
-    if (chan->u.listener.incoming_list) {
-      SMARTLIST_FOREACH_BEGIN(chan->u.listener.incoming_list,
-                              channel_t *, ichan) {
-        channel_mark_for_close(ichan);
-      } SMARTLIST_FOREACH_END(ichan);
-
-      smartlist_free(chan->u.listener.incoming_list);
-      chan->u.listener.incoming_list = NULL;
-    }
-
-    if (!(chan->state == CHANNEL_STATE_CLOSED ||
-          chan->state == CHANNEL_STATE_ERROR)) {
-      channel_change_state(chan, CHANNEL_STATE_CLOSED);
-    }
-  } else {
-    if (tlschan->conn) connection_or_close_normally(tlschan->conn, 1);
-    else {
-      /* Weird - we'll have to change the state ourselves, I guess */
-      log_info(LD_CHANNEL,
-               "Tried to close channel_tls_t %p with NULL conn",
-               tlschan);
-      channel_change_state(chan, CHANNEL_STATE_ERROR);
-    }
+  if (tlschan->conn) connection_or_close_normally(tlschan->conn, 1);
+  else {
+    /* Weird - we'll have to change the state ourselves, I guess */
+    log_info(LD_CHANNEL,
+             "Tried to close channel_tls_t %p with NULL conn",
+             tlschan);
+    channel_change_state(chan, CHANNEL_STATE_ERROR);
   }
 }
 
@@ -342,23 +310,19 @@ channel_tls_describe_transport_method(channel_t *chan)
 
   tor_assert(chan);
 
-  if (chan->is_listener) {
-    rv = "TLS channel (listening)";
-  } else {
-    tlschan = BASE_CHAN_TO_TLS(chan);
+   tlschan = BASE_CHAN_TO_TLS(chan);
 
-    if (tlschan->conn) {
-      id = TO_CONN(tlschan->conn)->global_identifier;
+  if (tlschan->conn) {
+    id = TO_CONN(tlschan->conn)->global_identifier;
 
-      if (buf) tor_free(buf);
-      tor_asprintf(&buf,
-                   "TLS channel (connection " U64_FORMAT ")",
-                   U64_PRINTF_ARG(id));
+    if (buf) tor_free(buf);
+    tor_asprintf(&buf,
+                 "TLS channel (connection " U64_FORMAT ")",
+                 U64_PRINTF_ARG(id));
 
-      rv = buf;
-    } else {
-      rv = "TLS channel (no connection)";
-    }
+    rv = buf;
+  } else {
+    rv = "TLS channel (no connection)";
   }
 
   return rv;
@@ -603,6 +567,65 @@ channel_tls_write_var_cell_method(channel_t *chan, var_cell_t *var_cell)
   return 1;
 }
 
+/*************************************************
+ * Method implementations for channel_listener_t *
+ ************************************************/
+
+/**
+ * Close a channel_listener_t
+ *
+ * This implements the close method for channel_listener_t
+ */
+
+static void
+channel_tls_listener_close_method(channel_listener_t *chan_l)
+{
+  tor_assert(chan_l);
+
+  /*
+   * Listeners we just go ahead and change state through to CLOSED, but
+   * make sure to check if they're channel_tls_listener to NULL it out.
+   */
+  if (chan_l == channel_tls_listener)
+    channel_tls_listener = NULL;
+
+  if (!(chan_l->state == CHANNEL_LISTENER_STATE_CLOSING ||
+        chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
+        chan_l->state == CHANNEL_LISTENER_STATE_ERROR)) {
+    channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSING);
+  }
+
+  if (chan_l->incoming_list) {
+    SMARTLIST_FOREACH_BEGIN(chan_l->incoming_list,
+                            channel_t *, ichan) {
+      channel_mark_for_close(ichan);
+    } SMARTLIST_FOREACH_END(ichan);
+
+    smartlist_free(chan_l->incoming_list);
+    chan_l->incoming_list = NULL;
+  }
+
+  if (!(chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
+        chan_l->state == CHANNEL_LISTENER_STATE_ERROR)) {
+    channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSED);
+  }
+}
+
+/**
+ * Describe the transport for a channel_listener_t
+ *
+ * This returns the string "TLS channel (listening)" to the upper
+ * layer.
+ */
+
+static const char *
+channel_tls_listener_describe_transport_method(channel_listener_t *chan_l)
+{
+  tor_assert(chan_l);
+
+  return "TLS channel (listening)";
+}
+
 /*******************************************************
  * Functions for handling events on an or_connection_t *
  ******************************************************/
@@ -782,8 +805,6 @@ channel_tls_handle_cell(cell_t *cell, or_connection_t *conn)
    return;
   }
 
-  tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
-
   handshaking = (TO_CONN(conn)->state != OR_CONN_STATE_OPEN);
 
   if (conn->_base.marked_for_close)
@@ -892,8 +913,6 @@ channel_tls_handle_var_cell(var_cell_t *var_cell, or_connection_t *conn)
     return;
   }
 
-  tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
-
   handshaking = (TO_CONN(conn)->state != OR_CONN_STATE_OPEN);
 
   if (TO_CONN(conn)->marked_for_close)
@@ -1049,7 +1068,6 @@ enter_v3_handshake_with_cell(var_cell_t *cell, channel_tls_t *chan)
 
   tor_assert(cell);
   tor_assert(chan);
-  tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
   tor_assert(chan->conn);
 
   started_here = connection_or_nonopen_was_started_here(chan->conn);
@@ -1091,7 +1109,6 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
 
   tor_assert(cell);
   tor_assert(chan);
-  tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
   tor_assert(chan->conn);
 
   started_here = connection_or_nonopen_was_started_here(chan->conn);
@@ -1247,7 +1264,6 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
 
   tor_assert(cell);
   tor_assert(chan);
-  tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
   tor_assert(chan->conn);
 
   if (chan->conn->link_proto < 2) {
@@ -1386,7 +1402,7 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
              safe_str_client(chan->conn->_base.address),
              chan->conn->_base.port,
              (int)(chan->conn->link_proto),
-             hex_str(TLS_CHAN_TO_BASE(chan)->u.cell_chan.identity_digest,
+             hex_str(TLS_CHAN_TO_BASE(chan)->identity_digest,
                      DIGEST_LEN),
              tor_addr_is_null(&my_apparent_addr) ?
              "<none>" : fmt_and_decorate_addr(&my_apparent_addr));
@@ -1422,7 +1438,6 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
 
   tor_assert(cell);
   tor_assert(chan);
-  tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
   tor_assert(chan->conn);
 
 #define ERR(s)                                                  \
@@ -1515,7 +1530,7 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
     * _trying_ to connect to an authority, not necessarily if we _did_ connect
     * to one. */
     if (router_digest_is_trusted_dir(
-          TLS_CHAN_TO_BASE(chan)->u.cell_chan.identity_digest))
+          TLS_CHAN_TO_BASE(chan)->identity_digest))
       severity = LOG_WARN;
     else
       severity = LOG_PROTOCOL_WARN;
@@ -1616,7 +1631,6 @@ channel_tls_process_auth_challenge_cell(var_cell_t *cell, channel_tls_t *chan)
 
   tor_assert(cell);
   tor_assert(chan);
-  tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
   tor_assert(chan->conn);
 
 #define ERR(s)                                                  \
@@ -1714,7 +1728,6 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
 
   tor_assert(cell);
   tor_assert(chan);
-  tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
   tor_assert(chan->conn);
 
 #define ERR(s)                                                  \

+ 2 - 2
src/or/channeltls.h

@@ -28,8 +28,8 @@ struct channel_tls_s {
 
 channel_t * channel_tls_connect(const tor_addr_t *addr, uint16_t port,
                                 const char *id_digest);
-channel_t * channel_tls_get_listener(void);
-channel_t * channel_tls_start_listener(void);
+channel_listener_t * channel_tls_get_listener(void);
+channel_listener_t * channel_tls_start_listener(void);
 channel_t * channel_tls_handle_incoming(or_connection_t *orconn);
 
 /* Things for connection_or.c to call back into */

+ 11 - 20
src/or/circuitbuild.c

@@ -1711,23 +1711,22 @@ get_unique_circ_id_by_chan(channel_t *chan)
   circid_t high_bit;
 
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
 
-  if (chan->u.cell_chan.circ_id_type == CIRC_ID_TYPE_NEITHER) {
+  if (chan->circ_id_type == CIRC_ID_TYPE_NEITHER) {
     log_warn(LD_BUG,
              "Trying to pick a circuit ID for a connection from "
              "a client with no identity.");
     return 0;
   }
   high_bit =
-    (chan->u.cell_chan.circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0;
+    (chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0;
   do {
     /* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a
      * circID such that (high_bit|test_circ_id) is not already used. */
-    test_circ_id = chan->u.cell_chan.next_circ_id++;
+    test_circ_id = chan->next_circ_id++;
     if (test_circ_id == 0 || test_circ_id >= 1<<15) {
       test_circ_id = 1;
-      chan->u.cell_chan.next_circ_id = 2;
+      chan->next_circ_id = 2;
     }
     if (++attempts > 1<<15) {
       /* Make sure we don't loop forever if all circ_id's are used. This
@@ -2039,11 +2038,9 @@ circuit_n_chan_done(channel_t *chan, int status)
   int err_reason = 0;
 
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
 
   log_debug(LD_CIRC,"chan to %s/%s, status=%d",
-            chan->u.cell_chan.nickname ?
-              chan->u.cell_chan.nickname : "NULL",
+            chan->nickname ? chan->nickname : "NULL",
             channel_get_canonical_remote_descr(chan), status);
 
   pending_circs = smartlist_new();
@@ -2064,7 +2061,7 @@ circuit_n_chan_done(channel_t *chan, int status)
           continue;
       } else {
         /* We expected a key. See if it's the right one. */
-        if (tor_memneq(chan->u.cell_chan.identity_digest,
+        if (tor_memneq(chan->identity_digest,
                    circ->n_hop->identity_digest, DIGEST_LEN))
           continue;
       }
@@ -2247,8 +2244,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
     else
       control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0);
 
-    tor_assert(!(circ->_base.n_chan->is_listener));
-    node = node_get_by_id(circ->_base.n_chan->u.cell_chan.identity_digest);
+    node = node_get_by_id(circ->_base.n_chan->identity_digest);
     fast = should_use_create_fast_for_circuit(circ);
     if (!fast) {
       /* We are an OR and we know the right onion key: we should
@@ -2487,10 +2483,8 @@ circuit_extend(cell_t *cell, circuit_t *circ)
   /* Next, check if we're being asked to connect to the hop that the
    * extend cell came from. There isn't any reason for that, and it can
    * assist circular-path attacks. */
-  tor_assert(!(TO_OR_CIRCUIT(circ)->p_chan->is_listener));
   if (tor_memeq(id_digest,
-                TO_OR_CIRCUIT(circ)->p_chan->
-                  u.cell_chan.identity_digest,
+                TO_OR_CIRCUIT(circ)->p_chan->identity_digest,
                 DIGEST_LEN)) {
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Client asked me to extend back to the previous hop.");
@@ -2733,9 +2727,8 @@ pathbias_count_first_hop(origin_circuit_t *circ)
     if (!circ->has_opened) {
       entry_guard_t *guard;
 
-      tor_assert(!(circ->_base.n_chan->is_listener));
-      guard = entry_guard_get_by_id_digest(
-                circ->_base.n_chan->u.cell_chan.identity_digest);
+      guard =
+        entry_guard_get_by_id_digest(circ->_base.n_chan->identity_digest);
       if (guard) {
         if (circ->path_state == PATH_STATE_NEW_CIRC) {
           circ->path_state = PATH_STATE_DID_FIRST_HOP;
@@ -2840,10 +2833,8 @@ pathbias_count_success(origin_circuit_t *circ)
 
   /* Don't count cannibalized/reused circs for path bias */
   if (!circ->has_opened) {
-    tor_assert(!(circ->_base.n_chan->is_listener));
     guard =
-      entry_guard_get_by_id_digest(circ->_base.n_chan->
-                                     u.cell_chan.identity_digest);
+      entry_guard_get_by_id_digest(circ->_base.n_chan->identity_digest);
 
     if (guard) {
       if (circ->path_state == PATH_STATE_DID_FIRST_HOP) {

+ 6 - 13
src/or/circuitlist.c

@@ -102,8 +102,6 @@ circuit_set_circid_chan_helper(circuit_t *circ, int direction,
   circid_t old_id, *circid_ptr;
   int was_active, make_active;
 
-  if (chan) tor_assert(!(chan->is_listener));
-
   if (direction == CELL_DIRECTION_OUT) {
     chan_ptr = &circ->n_chan;
     circid_ptr = &circ->n_circ_id;
@@ -131,13 +129,12 @@ circuit_set_circid_chan_helper(circuit_t *circ, int direction,
   }
 
   if (old_chan) { /* we may need to remove it from the conn-circid map */
-    tor_assert(!(old_chan->is_listener));
     search.circ_id = old_id;
     search.chan = old_chan;
     found = HT_REMOVE(chan_circid_map, &chan_circid_map, &search);
     if (found) {
       tor_free(found);
-      --old_chan->u.cell_chan.n_circuits;
+      --old_chan->n_circuits;
     }
     if (was_active && old_chan != chan)
       make_circuit_inactive_on_chan(circ, old_chan);
@@ -167,7 +164,7 @@ circuit_set_circid_chan_helper(circuit_t *circ, int direction,
   if (make_active && old_chan != chan)
     make_circuit_active_on_chan(circ,chan);
 
-  ++chan->u.cell_chan.n_circuits;
+  ++chan->n_circuits;
 }
 
 /** Set the p_conn field of a circuit <b>circ</b>, along
@@ -242,7 +239,6 @@ circuit_get_all_pending_on_channel(smartlist_t *out, channel_t *chan)
 {
   tor_assert(out);
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
 
   if (!circuits_pending_chans)
     return;
@@ -259,8 +255,8 @@ circuit_get_all_pending_on_channel(smartlist_t *out, channel_t *chan)
         continue;
     } else {
       /* We expected a key. See if it's the right one. */
-      if (tor_memneq(chan->u.cell_chan.identity_digest,
-                 circ->n_hop->identity_digest, DIGEST_LEN))
+      if (tor_memneq(chan->identity_digest,
+                     circ->n_hop->identity_digest, DIGEST_LEN))
         continue;
     }
     smartlist_add(out, circ);
@@ -276,14 +272,12 @@ circuit_count_pending_on_channel(channel_t *chan)
   smartlist_t *sl = smartlist_new();
 
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
 
   circuit_get_all_pending_on_channel(sl, chan);
   cnt = smartlist_len(sl);
   smartlist_free(sl);
   log_debug(LD_CIRC,"or_conn to %s at %s, %d pending circs",
-            chan->u.cell_chan.nickname ?
-              chan->u.cell_chan.nickname : "NULL",
+            chan->nickname ? chan->nickname : "NULL",
             channel_get_canonical_remote_descr(chan),
             cnt);
   return cnt;
@@ -839,7 +833,6 @@ circuit_dump_by_chan(channel_t *chan, int severity)
   circuit_t *circ;
 
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
 
   for (circ = global_circuitlist; circ; circ = circ->next) {
     circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0;
@@ -865,7 +858,7 @@ circuit_dump_by_chan(channel_t *chan, int severity)
 
     if (!circ->n_chan && circ->n_hop &&
         channel_matches_extend_info(chan, circ->n_hop) &&
-        tor_memeq(chan->u.cell_chan.identity_digest,
+        tor_memeq(chan->identity_digest,
                   circ->n_hop->identity_digest, DIGEST_LEN)) {
       circuit_dump_chan_details(severity, circ, chan,
                                 (circ->state == CIRCUIT_STATE_OPEN &&

+ 2 - 3
src/or/circuituse.c

@@ -1185,9 +1185,8 @@ circuit_build_failed(origin_circuit_t *circ)
     int already_marked = 0;
     if (circ->_base.n_chan) {
       n_chan = circ->_base.n_chan;
-      tor_assert(!(n_chan->is_listener));
 
-      if (n_chan->u.cell_chan.is_bad_for_new_circs) {
+      if (n_chan->is_bad_for_new_circs) {
         /* We only want to blame this router when a fresh healthy
          * connection fails. So don't mark this router as newly failed,
          * since maybe this was just an old circuit attempt that's
@@ -1201,7 +1200,7 @@ circuit_build_failed(origin_circuit_t *circ)
                "Our circuit failed to get a response from the first hop "
                "(%s). I'm going to try to rotate to a better connection.",
                channel_get_canonical_remote_descr(n_chan));
-      n_chan->u.cell_chan.is_bad_for_new_circs = 1;
+      n_chan->is_bad_for_new_circs = 1;
     } else {
       log_info(LD_OR,
                "Our circuit died before the first hop with no connection");

+ 8 - 9
src/or/command.c

@@ -44,7 +44,7 @@ uint64_t stats_n_relay_cells_processed = 0;
 uint64_t stats_n_destroy_cells_processed = 0;
 
 /* Handle an incoming channel */
-static void command_handle_incoming_channel(channel_t *listener,
+static void command_handle_incoming_channel(channel_listener_t *listener,
                                             channel_t *chan);
 
 /* These are the main functions for processing cells */
@@ -190,7 +190,6 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
 
   tor_assert(cell);
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
 
   log_debug(LD_OR,
             "Got a CREATE cell for circ_id %d on channel " U64_FORMAT
@@ -223,9 +222,9 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
    * circ. */
   id_is_high = cell->circ_id & (1<<15);
   if ((id_is_high &&
-       chan->u.cell_chan.circ_id_type == CIRC_ID_TYPE_HIGHER) ||
+       chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ||
       (!id_is_high &&
-       chan->u.cell_chan.circ_id_type == CIRC_ID_TYPE_LOWER)) {
+       chan->circ_id_type == CIRC_ID_TYPE_LOWER)) {
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Received create cell with unexpected circ_id %d. Closing.",
            cell->circ_id);
@@ -235,7 +234,7 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
   }
 
   if (circuit_id_in_use_on_channel(cell->circ_id, chan)) {
-    const node_t *node = node_get_by_id(chan->u.cell_chan.identity_digest);
+    const node_t *node = node_get_by_id(chan->identity_digest);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Received CREATE cell (circID %d) for known circ. "
            "Dropping (age %d).",
@@ -473,7 +472,7 @@ command_process_destroy_cell(cell_t *cell, channel_t *chan)
  */
 
 static void
-command_handle_incoming_channel(channel_t *listener, channel_t *chan)
+command_handle_incoming_channel(channel_listener_t *listener, channel_t *chan)
 {
   tor_assert(listener);
   tor_assert(chan);
@@ -500,11 +499,11 @@ command_setup_channel(channel_t *chan)
  */
 
 void
-command_setup_listener(channel_t *listener)
+command_setup_listener(channel_listener_t *listener)
 {
   tor_assert(listener);
-  tor_assert(listener->state == CHANNEL_STATE_LISTENING);
+  tor_assert(listener->state == CHANNEL_LISTENER_STATE_LISTENING);
 
-  channel_set_listener_fn(listener, command_handle_incoming_channel);
+  channel_listener_set_listener_fn(listener, command_handle_incoming_channel);
 }
 

+ 1 - 1
src/or/command.h

@@ -17,7 +17,7 @@
 void command_process_cell(channel_t *chan, cell_t *cell);
 void command_process_var_cell(channel_t *chan, var_cell_t *cell);
 void command_setup_channel(channel_t *chan);
-void command_setup_listener(channel_t *chan);
+void command_setup_listener(channel_listener_t *chan_l);
 
 extern uint64_t stats_n_padding_cells_processed;
 extern uint64_t stats_n_create_cells_processed;

+ 1 - 2
src/or/connection_edge.c

@@ -3070,11 +3070,10 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
       return 0;
     }
     if (or_circ && or_circ->p_chan) {
-      tor_assert(!(or_circ->p_chan->is_listener));
       if (!options->AllowSingleHopExits &&
            (or_circ->is_first_hop ||
             (!connection_or_digest_is_known_relay(
-                or_circ->p_chan->u.cell_chan.identity_digest) &&
+                or_circ->p_chan->identity_digest) &&
           should_refuse_unknown_exits(options)))) {
         /* Don't let clients use us as a single-hop proxy, unless the user
          * has explicitly allowed that in the config. It attracts attackers

+ 4 - 10
src/or/connection_or.c

@@ -336,8 +336,7 @@ connection_or_get_num_circuits(or_connection_t *conn)
   tor_assert(conn);
 
   if (conn->chan) {
-    tor_assert(!(TLS_CHAN_TO_BASE(conn->chan)->is_listener));
-    return TLS_CHAN_TO_BASE(conn->chan)->u.cell_chan.n_circuits;
+    return TLS_CHAN_TO_BASE(conn->chan)->n_circuits;
   } else return 0;
 }
 
@@ -1001,8 +1000,6 @@ connection_or_notify_error(or_connection_t *conn,
   /* Tell the controlling channel if we have one */
   if (conn->chan) {
     chan = TLS_CHAN_TO_BASE(conn->chan);
-    /* This shouldn't ever happen in the listening state */
-    tor_assert(chan->state != CHANNEL_STATE_LISTENING);
     /* Don't transition if we're already in closing, closed or error */
     if (!(chan->state == CHANNEL_STATE_CLOSING ||
           chan->state == CHANNEL_STATE_CLOSED ||
@@ -1148,8 +1145,6 @@ connection_or_close_normally(or_connection_t *orconn, int flush)
   else connection_mark_for_close(TO_CONN(orconn));
   if (orconn->chan) {
     chan = TLS_CHAN_TO_BASE(orconn->chan);
-    /* This shouldn't ever happen in the listening state */
-    tor_assert(chan->state != CHANNEL_STATE_LISTENING);
     /* Don't transition if we're already in closing, closed or error */
     if (!(chan->state == CHANNEL_STATE_CLOSING ||
           chan->state == CHANNEL_STATE_CLOSED ||
@@ -1173,8 +1168,6 @@ connection_or_close_for_error(or_connection_t *orconn, int flush)
   else connection_mark_for_close(TO_CONN(orconn));
   if (orconn->chan) {
     chan = TLS_CHAN_TO_BASE(orconn->chan);
-    /* This shouldn't ever happen in the listening state */
-    tor_assert(chan->state != CHANNEL_STATE_LISTENING);
     /* Don't transition if we're already in closing, closed or error */
     if (!(chan->state == CHANNEL_STATE_CLOSING ||
           chan->state == CHANNEL_STATE_CLOSED ||
@@ -1195,7 +1188,8 @@ connection_or_close_for_error(or_connection_t *orconn, int flush)
 int
 connection_tls_start_handshake(or_connection_t *conn, int receiving)
 {
-  channel_t *chan_listener, *chan;
+  channel_listener_t *chan_listener;
+  channel_t *chan;
 
   /* Incoming connections will need a new channel passed to the
    * channel_tls_listener */
@@ -1208,7 +1202,7 @@ connection_tls_start_handshake(or_connection_t *conn, int receiving)
       command_setup_listener(chan_listener);
     }
     chan = channel_tls_handle_incoming(conn);
-    channel_queue_incoming(chan_listener, chan);
+    channel_listener_queue_incoming(chan_listener, chan);
   }
 
   connection_or_change_state(conn, OR_CONN_STATE_TLS_HANDSHAKING);

+ 2 - 0
src/or/main.c

@@ -1539,6 +1539,7 @@ run_scheduled_events(time_t now)
 
   /** 8c. Do channel cleanup just like for connections */
   channel_run_cleanup();
+  channel_listener_run_cleanup();
 
   /** 9. and if we're a server, check whether our DNS is telling stories to
    * us. */
@@ -2172,6 +2173,7 @@ dumpstats(int severity)
   } SMARTLIST_FOREACH_END(conn);
 
   channel_dumpstats(severity);
+  channel_listener_dumpstats(severity);
 
   log(severity, LD_NET,
       "Cells processed: "U64_FORMAT" padding\n"

+ 53 - 12
src/or/or.h

@@ -883,6 +883,10 @@ typedef uint16_t streamid_t;
 
 typedef struct channel_s channel_t;
 
+/* channel_listener_t typedef; struct channel_listener_s is in channel.h */
+
+typedef struct channel_listener_s channel_listener_t;
+
 /* channel states for channel_t */
 
 typedef enum {
@@ -892,20 +896,9 @@ typedef enum {
    * Permitted transitions from:
    *   - CHANNEL_STATE_CLOSING
    * Permitted transitions to:
-   *   - CHANNEL_STATE_LISTENING
    *   - CHANNEL_STATE_OPENING
    */
   CHANNEL_STATE_CLOSED = 0,
-  /*
-   * Listening state - channel is listening for incoming connections
-   *
-   * Permitted transitions from:
-   *   - CHANNEL_STATE_CLOSED
-   * Permitted transitions to:
-   *   - CHANNEL_STATE_CLOSING
-   *   - CHANNEL_STATE_ERROR
-   */
-  CHANNEL_STATE_LISTENING,
   /*
    * Opening state - channel is trying to connect
    *
@@ -957,7 +950,6 @@ typedef enum {
    *
    * Permitted transitions from:
    *   - CHANNEL_STATE_CLOSING
-   *   - CHANNEL_STATE_LISTENING
    *   - CHANNEL_STATE_MAINT
    *   - CHANNEL_STATE_OPENING
    *   - CHANNEL_STATE_OPEN
@@ -971,6 +963,55 @@ typedef enum {
   CHANNEL_STATE_LAST
 } channel_state_t;
 
+/* channel listener states for channel_listener_t */
+
+typedef enum {
+  /*
+   * Closed state - channel listener is inactive
+   *
+   * Permitted transitions from:
+   *   - CHANNEL_LISTENER_STATE_CLOSING
+   * Permitted transitions to:
+   *   - CHANNEL_LISTENER_STATE_LISTENING
+   */
+  CHANNEL_LISTENER_STATE_CLOSED = 0,
+  /*
+   * Listening state - channel listener is listening for incoming
+   * connections
+   *
+   * Permitted transitions from:
+   *   - CHANNEL_LISTENER_STATE_CLOSED
+   * Permitted transitions to:
+   *   - CHANNEL_LISTENER_STATE_CLOSING
+   *   - CHANNEL_LISTENER_STATE_ERROR
+   */
+  CHANNEL_LISTENER_STATE_LISTENING,
+  /*
+   * Closing state - channel listener is shutting down
+   *
+   * Permitted transitions from:
+   *   - CHANNEL_LISTENER_STATE_LISTENING
+   * Permitted transitions to:
+   *   - CHANNEL_LISTENER_STATE_CLOSED,
+   *   - CHANNEL_LISTENER_STATE_ERROR
+   */
+  CHANNEL_LISTENER_STATE_CLOSING,
+  /*
+   * Error state - channel listener has experienced a permanent error
+   *
+   * Permitted transitions from:
+   *   - CHANNEL_STATE_CLOSING
+   *   - CHANNEL_STATE_LISTENING
+   * Permitted transitions to:
+   *   - None
+   */
+  CHANNEL_LISTENER_STATE_ERROR,
+  /*
+   * Placeholder for maximum state value
+   */
+  CHANNEL_LISTENER_STATE_LAST
+} channel_listener_state_t;
+
 /* TLS channel stuff */
 
 typedef struct channel_tls_s channel_tls_t;

+ 29 - 39
src/or/relay.c

@@ -1096,8 +1096,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
          * and linked. */
         static uint64_t next_id = 0;
         circ->dirreq_id = ++next_id;
-        tor_assert(!(TO_OR_CIRCUIT(circ)->p_chan->is_listener));
-        TO_OR_CIRCUIT(circ)->p_chan->u.cell_chan.dirreq_id = circ->dirreq_id;
+        TO_OR_CIRCUIT(circ)->p_chan->dirreq_id = circ->dirreq_id;
       }
 
       return connection_exit_begin_conn(cell, circ);
@@ -2179,23 +2178,22 @@ scale_active_circuits(channel_t *chan, unsigned cur_tick)
   double factor;
 
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
 
   factor =
     get_scale_factor(
-      chan->u.cell_chan.active_circuit_pqueue_last_recalibrated,
+      chan->active_circuit_pqueue_last_recalibrated,
       cur_tick);
   /** Ordinarily it isn't okay to change the value of an element in a heap,
    * but it's okay here, since we are preserving the order. */
   SMARTLIST_FOREACH_BEGIN(
-      chan->u.cell_chan.active_circuit_pqueue,
+      chan->active_circuit_pqueue,
       cell_ewma_t *, e) {
       tor_assert(e->last_adjusted_tick ==
-                 chan->u.cell_chan.active_circuit_pqueue_last_recalibrated);
+                 chan->active_circuit_pqueue_last_recalibrated);
       e->cell_count *= factor;
       e->last_adjusted_tick = cur_tick;
   } SMARTLIST_FOREACH_END(e);
-  chan->u.cell_chan.active_circuit_pqueue_last_recalibrated = cur_tick;
+  chan->active_circuit_pqueue_last_recalibrated = cur_tick;
 }
 
 /** Rescale <b>ewma</b> to the same scale as <b>chan</b>, and add it to
@@ -2204,15 +2202,14 @@ static void
 add_cell_ewma_to_chan(channel_t *chan, cell_ewma_t *ewma)
 {
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
   tor_assert(ewma);
   tor_assert(ewma->heap_index == -1);
 
   scale_single_cell_ewma(
       ewma,
-      chan->u.cell_chan.active_circuit_pqueue_last_recalibrated);
+      chan->active_circuit_pqueue_last_recalibrated);
 
-  smartlist_pqueue_add(chan->u.cell_chan.active_circuit_pqueue,
+  smartlist_pqueue_add(chan->active_circuit_pqueue,
                        compare_cell_ewma_counts,
                        STRUCT_OFFSET(cell_ewma_t, heap_index),
                        ewma);
@@ -2223,11 +2220,10 @@ static void
 remove_cell_ewma_from_chan(channel_t *chan, cell_ewma_t *ewma)
 {
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
   tor_assert(ewma);
   tor_assert(ewma->heap_index != -1);
 
-  smartlist_pqueue_remove(chan->u.cell_chan.active_circuit_pqueue,
+  smartlist_pqueue_remove(chan->active_circuit_pqueue,
                           compare_cell_ewma_counts,
                           STRUCT_OFFSET(cell_ewma_t, heap_index),
                           ewma);
@@ -2239,9 +2235,8 @@ static cell_ewma_t *
 pop_first_cell_ewma_from_chan(channel_t *chan)
 {
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
 
-  return smartlist_pqueue_pop(chan->u.cell_chan.active_circuit_pqueue,
+  return smartlist_pqueue_pop(chan->active_circuit_pqueue,
                               compare_cell_ewma_counts,
                               STRUCT_OFFSET(cell_ewma_t, heap_index));
 }
@@ -2254,7 +2249,6 @@ make_circuit_active_on_chan(circuit_t *circ, channel_t *chan)
   circuit_t **nextp = NULL, **prevp = NULL;
 
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
   tor_assert(circ);
 
   nextp = next_circ_on_chan_p(circ, chan);
@@ -2267,11 +2261,11 @@ make_circuit_active_on_chan(circuit_t *circ, channel_t *chan)
 
   assert_active_circuits_ok_paranoid(chan);
 
-  if (!(chan->u.cell_chan.active_circuits)) {
-    chan->u.cell_chan.active_circuits = circ;
+  if (!(chan->active_circuits)) {
+    chan->active_circuits = circ;
     *prevp = *nextp = circ;
   } else {
-    circuit_t *head = chan->u.cell_chan.active_circuits;
+    circuit_t *head = chan->active_circuits;
     circuit_t *old_tail = *prev_circ_on_chan_p(head, chan);
     *next_circ_on_chan_p(old_tail, chan) = circ;
     *nextp = head;
@@ -2299,7 +2293,6 @@ make_circuit_inactive_on_chan(circuit_t *circ, channel_t *chan)
   circuit_t *next = NULL, *prev = NULL;
 
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
   tor_assert(circ);
 
   nextp = next_circ_on_chan_p(circ, chan);
@@ -2319,12 +2312,12 @@ make_circuit_inactive_on_chan(circuit_t *circ, channel_t *chan)
   tor_assert(*next_circ_on_chan_p(prev, chan) == circ);
 
   if (next == circ) {
-    chan->u.cell_chan.active_circuits = NULL;
+    chan->active_circuits = NULL;
   } else {
     *prev_circ_on_chan_p(next, chan) = prev;
     *next_circ_on_chan_p(prev, chan) = next;
-    if (chan->u.cell_chan.active_circuits == circ)
-      chan->u.cell_chan.active_circuits = next;
+    if (chan->active_circuits == circ)
+      chan->active_circuits = next;
   }
   *prevp = *nextp = NULL;
 
@@ -2347,9 +2340,8 @@ channel_unlink_all_active_circs(channel_t *chan)
   circuit_t *head = NULL, *cur = NULL;
 
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
 
-  cur = head = chan->u.cell_chan.active_circuits;
+  cur = head = chan->active_circuits;
   if (! head)
     return;
   do {
@@ -2358,12 +2350,12 @@ channel_unlink_all_active_circs(channel_t *chan)
     *next_circ_on_chan_p(cur, chan) = NULL;
     cur = next;
   } while (cur != head);
-  chan->u.cell_chan.active_circuits = NULL;
+  chan->active_circuits = NULL;
 
-  SMARTLIST_FOREACH(chan->u.cell_chan.active_circuit_pqueue,
+  SMARTLIST_FOREACH(chan->active_circuit_pqueue,
                     cell_ewma_t *, e,
                     e->heap_index = -1);
-  smartlist_clear(chan->u.cell_chan.active_circuit_pqueue);
+  smartlist_clear(chan->active_circuit_pqueue);
 }
 
 /** Block (if <b>block</b> is true) or unblock (if <b>block</b> is false)
@@ -2440,9 +2432,8 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
   double ewma_increment = -1;
 
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
 
-  circ = chan->u.cell_chan.active_circuits;
+  circ = chan->active_circuits;
   if (!circ) return 0;
   assert_active_circuits_ok_paranoid(chan);
 
@@ -2453,13 +2444,13 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
     tor_gettimeofday_cached(&now_hires);
     tick = cell_ewma_tick_from_timeval(&now_hires, &fractional_tick);
 
-    if (tick != chan->u.cell_chan.active_circuit_pqueue_last_recalibrated) {
+    if (tick != chan->active_circuit_pqueue_last_recalibrated) {
       scale_active_circuits(chan, tick);
     }
 
     ewma_increment = pow(ewma_scale_factor, -fractional_tick);
 
-    cell_ewma = smartlist_get(chan->u.cell_chan.active_circuit_pqueue, 0);
+    cell_ewma = smartlist_get(chan->active_circuit_pqueue, 0);
     circ = cell_ewma_to_circuit(cell_ewma);
   }
 
@@ -2511,8 +2502,8 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
 
     /* If we just flushed our queue and this circuit is used for a
      * tunneled directory request, possibly advance its state. */
-    if (queue->n == 0 && chan->u.cell_chan.dirreq_id)
-      geoip_change_dirreq_state(chan->u.cell_chan.dirreq_id,
+    if (queue->n == 0 && chan->dirreq_id)
+      geoip_change_dirreq_state(chan->dirreq_id,
                                 DIRREQ_TUNNELED,
                                 DIRREQ_CIRC_QUEUE_FLUSHED);
 
@@ -2534,7 +2525,7 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
       tor_assert(tmp == cell_ewma);
       add_cell_ewma_to_chan(chan, cell_ewma);
     }
-    if (!ewma_enabled && circ != chan->u.cell_chan.active_circuits) {
+    if (!ewma_enabled && circ != chan->active_circuits) {
       /* If this happens, the current circuit just got made inactive by
        * a call in connection_write_to_buf().  That's nothing to worry about:
        * circuit_make_inactive_on_conn() already advanced chan->active_circuits
@@ -2546,7 +2537,7 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
   }
   tor_assert(*next_circ_on_chan_p(circ, chan));
   assert_active_circuits_ok_paranoid(chan);
-  chan->u.cell_chan.active_circuits = *next_circ_on_chan_p(circ, chan);
+  chan->active_circuits = *next_circ_on_chan_p(circ, chan);
 
   /* Is the cell queue low enough to unblock all the streams that are waiting
    * to write to this circuit? */
@@ -2701,9 +2692,8 @@ assert_active_circuits_ok(channel_t *chan)
   int n = 0;
 
   tor_assert(chan);
-  tor_assert(!(chan->is_listener));
 
-  cur = head = chan->u.cell_chan.active_circuits;
+  cur = head = chan->active_circuits;
 
   if (! head)
     return;
@@ -2723,13 +2713,13 @@ assert_active_circuits_ok(channel_t *chan)
       tor_assert(ewma->is_for_p_chan);
     }
     tor_assert(ewma->heap_index != -1);
-    tor_assert(ewma == smartlist_get(chan->u.cell_chan.active_circuit_pqueue,
+    tor_assert(ewma == smartlist_get(chan->active_circuit_pqueue,
                                      ewma->heap_index));
     n++;
     cur = next;
   } while (cur != head);
 
-  tor_assert(n == smartlist_len(chan->u.cell_chan.active_circuit_pqueue));
+  tor_assert(n == smartlist_len(chan->active_circuit_pqueue));
 }
 
 /** Return 1 if we shouldn't restart reading on this circuit, even if

Some files were not shown because too many files changed in this diff