Back to index

tor  0.2.3.18-rc
Defines | Functions
connection.h File Reference

Header file for connection.c. More...

#include "buffers.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define connection_mark_for_close(c)   _connection_mark_for_close((c), __LINE__, _SHORT_FILE_)
#define _connection_mark_and_flush(c, line, file)
 Mark 'c' for close, but try to hold it open until all the data is written.
#define connection_mark_and_flush(c)   _connection_mark_and_flush((c), __LINE__, _SHORT_FILE_)
#define connection_speaks_cells(conn)   ((conn)->type == CONN_TYPE_OR)
#define connection_type_uses_bufferevent(c)   (0)

Functions

const char * conn_type_to_string (int type)
 Return the human-readable name for the connection type type
const char * conn_state_to_string (int type, int state)
 Return the human-readable name for the connection state state for the connection type type
dir_connection_tdir_connection_new (int socket_family)
 Allocate and return a new dir_connection_t, initialized as by connection_init().
or_connection_tor_connection_new (int socket_family)
 Allocate and return a new or_connection_t, initialized as by connection_init().
edge_connection_tedge_connection_new (int type, int socket_family)
 Allocate and return a new edge_connection_t, initialized as by connection_init().
entry_connection_tentry_connection_new (int type, int socket_family)
 Allocate and return a new entry_connection_t, initialized as by connection_init().
control_connection_tcontrol_connection_new (int socket_family)
 Allocate and return a new control_connection_t, initialized as by connection_init().
listener_connection_tlistener_connection_new (int type, int socket_family)
 Allocate and return a new listener_connection_t, initialized as by connection_init().
connection_tconnection_new (int type, int socket_family)
 Allocate, initialize, and return a new connection_t subtype of type to make or receive connections of address family socket_family.
void connection_link_connections (connection_t *conn_a, connection_t *conn_b)
 Create a link between conn_a and conn_b.
void connection_free (connection_t *conn)
 Make sure conn isn't in any of the global conn lists; then free it.
void connection_free_all (void)
 Call _connection_free() on every connection in our array, and release all storage held by connection.c.
void connection_about_to_close_connection (connection_t *conn)
 Called when we're about to finally unlink and free a connection: perform necessary accounting and cleanup.
void connection_close_immediate (connection_t *conn)
 Close the underlying socket for conn, so we don't try to flush it.
void _connection_mark_for_close (connection_t *conn, int line, const char *file)
 Mark conn to be closed next time we loop through conn_close_if_marked() in main.c.
void connection_expire_held_open (void)
 Find each connection that has hold_open_until_flushed set to 1 but hasn't written in the past 15 seconds, and set hold_open_until_flushed to 0.
int connection_connect (connection_t *conn, const char *address, const tor_addr_t *addr, uint16_t port, int *socket_error)
 Take conn, make a nonblocking socket; try to connect to addr:port (they arrive in host order).
int connection_proxy_connect (connection_t *conn, int type)
 Write a proxy request of type (socks4, socks5, https) to conn for conn->addr:conn->port, authenticating with the auth details given in the configuration (if available).
int connection_read_proxy_handshake (connection_t *conn)
 Call this from connection_*_process_inbuf() to advance the proxy handshake.
void log_failed_proxy_connection (connection_t *conn)
 Log a failed connection to a proxy server.
int get_proxy_addrport (tor_addr_t *addr, uint16_t *port, int *proxy_type, const connection_t *conn)
 Fills addr and port with the details of the global proxy server we are using.
int retry_all_listeners (smartlist_t *replaced_conns, smartlist_t *new_conns, int close_all_noncontrol)
 Launch listeners for each port you should have open.
void connection_mark_all_noncontrol_listeners (void)
 Mark every listener of type other than CONTROL_LISTENER to be closed.
void connection_mark_all_noncontrol_connections (void)
 Mark every external connection not used for controllers for close.
ssize_t connection_bucket_write_limit (connection_t *conn, time_t now)
 How many bytes at most can we write onto this connection?
int global_write_bucket_low (connection_t *conn, size_t attempt, int priority)
 Return 1 if the global write buckets are low enough that we shouldn't send attempt bytes of low-priority directory stuff out to conn.
void connection_bucket_init (void)
 Initialize the global read bucket to options->BandwidthBurst.
void connection_bucket_refill (int seconds_elapsed, time_t now)
 Time has passed; increment buckets appropriately.
int connection_handle_read (connection_t *conn)
int connection_fetch_from_buf (char *string, size_t len, connection_t *conn)
 A pass-through to fetch_from_buf.
int connection_fetch_from_buf_line (connection_t *conn, char *data, size_t *data_len)
 As fetch_from_buf_line(), but read from a connection's input buffer.
int connection_fetch_from_buf_http (connection_t *conn, char **headers_out, size_t max_headerlen, char **body_out, size_t *body_used, size_t max_bodylen, int force_complete)
 As fetch_from_buf_http, but fetches from a conncetion's input buffer_t or its bufferevent as appropriate.
int connection_wants_to_flush (connection_t *conn)
 Return conn->outbuf_flushlen: how many bytes conn wants to flush from its outbuf.
int connection_outbuf_too_full (connection_t *conn)
 Are there too many bytes on edge connection conn's outbuf to send back a relay-level sendme yet? Return 1 if so, 0 if not.
int connection_handle_write (connection_t *conn, int force)
int connection_flush (connection_t *conn)
 Try to flush data that's waiting for a write on conn.
void _connection_write_to_buf_impl (const char *string, size_t len, connection_t *conn, int zlib)
 Append len bytes of string onto conn's outbuf, and ask it to start writing.
static void connection_write_to_buf (const char *string, size_t len, connection_t *conn)
static void connection_write_to_buf_zlib (const char *string, size_t len, dir_connection_t *conn, int done)
static size_t connection_get_inbuf_len (connection_t *conn)
static size_t connection_get_outbuf_len (connection_t *conn)
connection_tconnection_get_by_global_id (uint64_t id)
 Return the stream with id id if it is not already marked for close.
connection_tconnection_get_by_type (int type)
 Return a connection of type type that is not marked for close.
connection_tconnection_get_by_type_purpose (int type, int purpose)
 Return an open, non-marked connection of a given type and purpose, or NULL if no such connection exists.
connection_tconnection_get_by_type_addr_port_purpose (int type, const tor_addr_t *addr, uint16_t port, int purpose)
 Return a connection with given type, address, port, and purpose; or NULL if no such connection exists.
connection_tconnection_get_by_type_state (int type, int state)
 Return a connection of type type that is in state state, and that is not marked for close.
connection_tconnection_get_by_type_state_rendquery (int type, int state, const char *rendquery)
 Return a connection of type type that has rendquery equal to rendquery, and that is not marked for close.
dir_connection_tconnection_dir_get_by_purpose_and_resource (int state, const char *resource)
 Return a directory connection (if any one exists) that is fetching the item described by state/resource
int connection_is_listener (connection_t *conn)
 Return 1 if conn is a listener conn, else return 0.
int connection_state_is_open (connection_t *conn)
 Return 1 if conn is in state "open" and is not marked for close, else return 0.
int connection_state_is_connecting (connection_t *conn)
 Return 1 if conn is in 'connecting' state, else return 0.
char * alloc_http_authenticator (const char *authenticator)
 Allocates a base64'ed authenticator for use in http or https auth, based on the input string authenticator.
void assert_connection_ok (connection_t *conn, time_t now)
 Verify that connection conn has all of its invariants correct.
int connection_or_nonopen_was_started_here (or_connection_t *conn)
 Return 1 if we initiated this connection, or 0 if it started out as an incoming connection.
void connection_dump_buffer_mem_stats (int severity)
 Log how many bytes are used by buffers of different kinds and sizes.
void remove_file_if_very_old (const char *fname, time_t now)
 Given a file name check to see whether the file exists but has not been modified for a very long time.

Detailed Description

Header file for connection.c.

Definition in file connection.h.


Define Documentation

#define _connection_mark_and_flush (   c,
  line,
  file 
)
Value:
do {                                                                  \
    connection_t *tmp_conn_ = (c);                                      \
    _connection_mark_for_close(tmp_conn_, (line), (file));              \
    tmp_conn_->hold_open_until_flushed = 1;                             \
    IF_HAS_BUFFEREVENT(tmp_conn_,                                       \
                       connection_start_writing(tmp_conn_));            \
  } while (0)

Mark 'c' for close, but try to hold it open until all the data is written.

Definition at line 42 of file connection.h.

#define connection_mark_and_flush (   c)    _connection_mark_and_flush((c), __LINE__, _SHORT_FILE_)

Definition at line 51 of file connection.h.

#define connection_mark_for_close (   c)    _connection_mark_for_close((c), __LINE__, _SHORT_FILE_)

Definition at line 36 of file connection.h.

#define connection_speaks_cells (   conn)    ((conn)->type == CONN_TYPE_OR)

Definition at line 151 of file connection.h.

#define connection_type_uses_bufferevent (   c)    (0)

Definition at line 174 of file connection.h.


Function Documentation

void _connection_mark_for_close ( connection_t conn,
int  line,
const char *  file 
)

Mark conn to be closed next time we loop through conn_close_if_marked() in main.c.

Definition at line 671 of file connection.c.

{
  assert_connection_ok(conn,0);
  tor_assert(line);
  tor_assert(line < 1<<16); /* marked_for_close can only fit a uint16_t. */
  tor_assert(file);

  if (conn->marked_for_close) {
    log(LOG_WARN,LD_BUG,"Duplicate call to connection_mark_for_close at %s:%d"
        " (first at %s:%d)", file, line, conn->marked_for_close_file,
        conn->marked_for_close);
    tor_fragile_assert();
    return;
  }

  conn->marked_for_close = line;
  conn->marked_for_close_file = file;
  add_connection_to_closeable_list(conn);

  /* in case we're going to be held-open-til-flushed, reset
   * the number of seconds since last successful write, so
   * we get our whole 15 seconds */
  conn->timestamp_lastwritten = time(NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void _connection_write_to_buf_impl ( const char *  string,
size_t  len,
connection_t conn,
int  zlib 
)

Append len bytes of string onto conn's outbuf, and ask it to start writing.

If zlib is nonzero, this is a directory connection that should get its contents compressed or decompressed as they're written. If zlib is negative, this is the last data to be compressed, and the connection's zlib state should be flushed.

If it's an OR conn and an entire TLS record is ready, then try to flush the record now. Similarly, if it's a local control connection and a 64k chunk is ready, try to flush it all, so we don't end up with many megabytes of controller info queued at once.

Definition at line 3386 of file connection.c.

{
  /* XXXX This function really needs to return -1 on failure. */
  int r;
  size_t old_datalen;
  if (!len && !(zlib<0))
    return;
  /* if it's marked for close, only allow write if we mean to flush it */
  if (conn->marked_for_close && !conn->hold_open_until_flushed)
    return;

  IF_HAS_BUFFEREVENT(conn, {
    if (zlib) {
      int done = zlib < 0;
      r = write_to_evbuffer_zlib(bufferevent_get_output(conn->bufev),
                                 TO_DIR_CONN(conn)->zlib_state,
                                 string, len, done);
    } else {
      r = bufferevent_write(conn->bufev, string, len);
    }
    if (r < 0) {
      /* XXXX mark for close? */
      log_warn(LD_NET, "bufferevent_write failed! That shouldn't happen.");
    }
    return;
  });

  old_datalen = buf_datalen(conn->outbuf);
  if (zlib) {
    dir_connection_t *dir_conn = TO_DIR_CONN(conn);
    int done = zlib < 0;
    CONN_LOG_PROTECT(conn, r = write_to_buf_zlib(conn->outbuf,
                                                 dir_conn->zlib_state,
                                                 string, len, done));
  } else {
    CONN_LOG_PROTECT(conn, r = write_to_buf(string, len, conn->outbuf));
  }
  if (r < 0) {
    if (CONN_IS_EDGE(conn)) {
      /* if it failed, it means we have our package/delivery windows set
         wrong compared to our max outbuf size. close the whole circuit. */
      log_warn(LD_NET,
               "write_to_buf failed. Closing circuit (fd %d).", (int)conn->s);
      circuit_mark_for_close(circuit_get_by_edge_conn(TO_EDGE_CONN(conn)),
                             END_CIRC_REASON_INTERNAL);
    } else {
      log_warn(LD_NET,
               "write_to_buf failed. Closing connection (fd %d).",
               (int)conn->s);
      connection_mark_for_close(conn);
    }
    return;
  }

  /* If we receive optimistic data in the EXIT_CONN_STATE_RESOLVING
   * state, we don't want to try to write it right away, since
   * conn->write_event won't be set yet.  Otherwise, write data from
   * this conn as the socket is available. */
  if (conn->write_event) {
    connection_start_writing(conn);
  }
  if (zlib) {
    conn->outbuf_flushlen += buf_datalen(conn->outbuf) - old_datalen;
  } else {
    ssize_t extra = 0;
    conn->outbuf_flushlen += len;

    /* Should we try flushing the outbuf now? */
    if (conn->in_flushed_some) {
      /* Don't flush the outbuf when the reason we're writing more stuff is
       * _because_ we flushed the outbuf.  That's unfair. */
      return;
    }

    if (conn->type == CONN_TYPE_OR &&
        conn->outbuf_flushlen-len < MIN_TLS_FLUSHLEN &&
        conn->outbuf_flushlen >= MIN_TLS_FLUSHLEN) {
      /* We just pushed outbuf_flushlen to MIN_TLS_FLUSHLEN or above;
       * we can send out a full TLS frame now if we like. */
      extra = conn->outbuf_flushlen - MIN_TLS_FLUSHLEN;
      conn->outbuf_flushlen = MIN_TLS_FLUSHLEN;
    } else if (conn->type == CONN_TYPE_CONTROL &&
               !connection_is_rate_limited(conn) &&
               conn->outbuf_flushlen-len < 1<<16 &&
               conn->outbuf_flushlen >= 1<<16) {
      /* just try to flush all of it */
    } else
      return; /* no need to try flushing */

    if (connection_handle_write(conn, 0) < 0) {
      if (!conn->marked_for_close) {
        /* this connection is broken. remove it. */
        log_warn(LD_BUG, "unhandled error on write for "
                 "conn (type %d, fd %d); removing",
                 conn->type, (int)conn->s);
        tor_fragile_assert();
        /* do a close-immediate here, so we don't try to flush */
        connection_close_immediate(conn);
      }
      return;
    }
    if (extra) {
      conn->outbuf_flushlen += extra;
      connection_start_writing(conn);
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* alloc_http_authenticator ( const char *  authenticator)

Allocates a base64'ed authenticator for use in http or https auth, based on the input string authenticator.

Returns it if success, else returns NULL.

Definition at line 3695 of file connection.c.

{
  /* an authenticator in Basic authentication
   * is just the string "username:password" */
  const size_t authenticator_length = strlen(authenticator);
  /* The base64_encode function needs a minimum buffer length
   * of 66 bytes. */
  const size_t base64_authenticator_length = (authenticator_length/48+1)*66;
  char *base64_authenticator = tor_malloc(base64_authenticator_length);
  if (base64_encode(base64_authenticator, base64_authenticator_length,
                    authenticator, authenticator_length) < 0) {
    tor_free(base64_authenticator); /* free and set to null */
  } else {
    int i = 0, j = 0;
    ssize_t len = strlen(base64_authenticator);

    /* remove all newline occurrences within the string */
    for (i=0; i < len; ++i) {
      if ('\n' != base64_authenticator[i]) {
        base64_authenticator[j] = base64_authenticator[i];
        ++j;
      }
    }
    base64_authenticator[j]='\0';
  }
  return base64_authenticator;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void assert_connection_ok ( connection_t conn,
time_t  now 
)

Verify that connection conn has all of its invariants correct.

Trigger an assert if anything is invalid.

Definition at line 4013 of file connection.c.

{
  (void) now; /* XXXX unused. */
  tor_assert(conn);
  tor_assert(conn->type >= _CONN_TYPE_MIN);
  tor_assert(conn->type <= _CONN_TYPE_MAX);

#ifdef USE_BUFFEREVENTS
  if (conn->bufev) {
    tor_assert(conn->read_event == NULL);
    tor_assert(conn->write_event == NULL);
    tor_assert(conn->inbuf == NULL);
    tor_assert(conn->outbuf == NULL);
  }
#endif

  switch (conn->type) {
    case CONN_TYPE_OR:
      tor_assert(conn->magic == OR_CONNECTION_MAGIC);
      break;
    case CONN_TYPE_AP:
      tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC);
      break;
    case CONN_TYPE_EXIT:
      tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
      break;
    case CONN_TYPE_DIR:
      tor_assert(conn->magic == DIR_CONNECTION_MAGIC);
      break;
    case CONN_TYPE_CONTROL:
      tor_assert(conn->magic == CONTROL_CONNECTION_MAGIC);
      break;
    CASE_ANY_LISTENER_TYPE:
      tor_assert(conn->magic == LISTENER_CONNECTION_MAGIC);
      break;
    default:
      tor_assert(conn->magic == BASE_CONNECTION_MAGIC);
      break;
  }

  if (conn->linked_conn) {
    tor_assert(conn->linked_conn->linked_conn == conn);
    tor_assert(conn->linked);
  }
  if (conn->linked)
    tor_assert(!SOCKET_OK(conn->s));

  if (conn->outbuf_flushlen > 0) {
    /* With optimistic data, we may have queued data in
     * EXIT_CONN_STATE_RESOLVING while the conn is not yet marked to writing.
     * */
    tor_assert((conn->type == CONN_TYPE_EXIT &&
                conn->state == EXIT_CONN_STATE_RESOLVING) ||
               connection_is_writing(conn) ||
               conn->write_blocked_on_bw ||
               (CONN_IS_EDGE(conn) &&
                TO_EDGE_CONN(conn)->edge_blocked_on_circ));
  }

  if (conn->hold_open_until_flushed)
    tor_assert(conn->marked_for_close);

  /* XXXX check: read_blocked_on_bw, write_blocked_on_bw, s, conn_array_index,
   * marked_for_close. */

  /* buffers */
  if (conn->inbuf)
    assert_buf_ok(conn->inbuf);
  if (conn->outbuf)
    assert_buf_ok(conn->outbuf);

  if (conn->type == CONN_TYPE_OR) {
    or_connection_t *or_conn = TO_OR_CONN(conn);
    if (conn->state == OR_CONN_STATE_OPEN) {
      /* tor_assert(conn->bandwidth > 0); */
      /* the above isn't necessarily true: if we just did a TLS
       * handshake but we didn't recognize the other peer, or it
       * gave a bad cert/etc, then we won't have assigned bandwidth,
       * yet it will be open. -RD
       */
//      tor_assert(conn->read_bucket >= 0);
    }
//    tor_assert(conn->addr && conn->port);
    tor_assert(conn->address);
    if (conn->state > OR_CONN_STATE_PROXY_HANDSHAKING)
      tor_assert(or_conn->tls);
  }

  if (CONN_IS_EDGE(conn)) {
    /* XXX unchecked: package window, deliver window. */
    if (conn->type == CONN_TYPE_AP) {
      entry_connection_t *entry_conn = TO_ENTRY_CONN(conn);
      if (entry_conn->chosen_exit_optional || entry_conn->chosen_exit_retries)
        tor_assert(entry_conn->chosen_exit_name);

      tor_assert(entry_conn->socks_request);
      if (conn->state == AP_CONN_STATE_OPEN) {
        tor_assert(entry_conn->socks_request->has_finished);
        if (!conn->marked_for_close) {
          tor_assert(ENTRY_TO_EDGE_CONN(entry_conn)->cpath_layer);
          assert_cpath_layer_ok(ENTRY_TO_EDGE_CONN(entry_conn)->cpath_layer);
        }
      }
    }
    if (conn->type == CONN_TYPE_EXIT) {
      tor_assert(conn->purpose == EXIT_PURPOSE_CONNECT ||
                 conn->purpose == EXIT_PURPOSE_RESOLVE);
    }
  } else if (conn->type == CONN_TYPE_DIR) {
  } else {
    /* Purpose is only used for dir and exit types currently */
    tor_assert(!conn->purpose);
  }

  switch (conn->type)
    {
    CASE_ANY_LISTENER_TYPE:
      tor_assert(conn->state == LISTENER_STATE_READY);
      break;
    case CONN_TYPE_OR:
      tor_assert(conn->state >= _OR_CONN_STATE_MIN);
      tor_assert(conn->state <= _OR_CONN_STATE_MAX);
      tor_assert(TO_OR_CONN(conn)->n_circuits >= 0);
      break;
    case CONN_TYPE_EXIT:
      tor_assert(conn->state >= _EXIT_CONN_STATE_MIN);
      tor_assert(conn->state <= _EXIT_CONN_STATE_MAX);
      tor_assert(conn->purpose >= _EXIT_PURPOSE_MIN);
      tor_assert(conn->purpose <= _EXIT_PURPOSE_MAX);
      break;
    case CONN_TYPE_AP:
      tor_assert(conn->state >= _AP_CONN_STATE_MIN);
      tor_assert(conn->state <= _AP_CONN_STATE_MAX);
      tor_assert(TO_ENTRY_CONN(conn)->socks_request);
      break;
    case CONN_TYPE_DIR:
      tor_assert(conn->state >= _DIR_CONN_STATE_MIN);
      tor_assert(conn->state <= _DIR_CONN_STATE_MAX);
      tor_assert(conn->purpose >= _DIR_PURPOSE_MIN);
      tor_assert(conn->purpose <= _DIR_PURPOSE_MAX);
      break;
    case CONN_TYPE_CPUWORKER:
      tor_assert(conn->state >= _CPUWORKER_STATE_MIN);
      tor_assert(conn->state <= _CPUWORKER_STATE_MAX);
      break;
    case CONN_TYPE_CONTROL:
      tor_assert(conn->state >= _CONTROL_CONN_STATE_MIN);
      tor_assert(conn->state <= _CONTROL_CONN_STATE_MAX);
      break;
    default:
      tor_assert(0);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* conn_state_to_string ( int  type,
int  state 
)

Return the human-readable name for the connection state state for the connection type type

Definition at line 134 of file connection.c.

{
  static char buf[96];
  switch (type) {
    CASE_ANY_LISTENER_TYPE:
      if (state == LISTENER_STATE_READY)
        return "ready";
      break;
    case CONN_TYPE_OR:
      switch (state) {
        case OR_CONN_STATE_CONNECTING: return "connect()ing";
        case OR_CONN_STATE_PROXY_HANDSHAKING: return "handshaking (proxy)";
        case OR_CONN_STATE_TLS_HANDSHAKING: return "handshaking (TLS)";
        case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING:
          return "renegotiating (TLS, v2 handshake)";
        case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
          return "waiting for renegotiation or V3 handshake";
        case OR_CONN_STATE_OR_HANDSHAKING_V2:
          return "handshaking (Tor, v2 handshake)";
        case OR_CONN_STATE_OR_HANDSHAKING_V3:
          return "handshaking (Tor, v3 handshake)";
        case OR_CONN_STATE_OPEN: return "open";
      }
      break;
    case CONN_TYPE_EXIT:
      switch (state) {
        case EXIT_CONN_STATE_RESOLVING: return "waiting for dest info";
        case EXIT_CONN_STATE_CONNECTING: return "connecting";
        case EXIT_CONN_STATE_OPEN: return "open";
        case EXIT_CONN_STATE_RESOLVEFAILED: return "resolve failed";
      }
      break;
    case CONN_TYPE_AP:
      switch (state) {
        case AP_CONN_STATE_SOCKS_WAIT: return "waiting for socks info";
        case AP_CONN_STATE_NATD_WAIT: return "waiting for natd dest info";
        case AP_CONN_STATE_RENDDESC_WAIT: return "waiting for rendezvous desc";
        case AP_CONN_STATE_CONTROLLER_WAIT: return "waiting for controller";
        case AP_CONN_STATE_CIRCUIT_WAIT: return "waiting for circuit";
        case AP_CONN_STATE_CONNECT_WAIT: return "waiting for connect response";
        case AP_CONN_STATE_RESOLVE_WAIT: return "waiting for resolve response";
        case AP_CONN_STATE_OPEN: return "open";
      }
      break;
    case CONN_TYPE_DIR:
      switch (state) {
        case DIR_CONN_STATE_CONNECTING: return "connecting";
        case DIR_CONN_STATE_CLIENT_SENDING: return "client sending";
        case DIR_CONN_STATE_CLIENT_READING: return "client reading";
        case DIR_CONN_STATE_CLIENT_FINISHED: return "client finished";
        case DIR_CONN_STATE_SERVER_COMMAND_WAIT: return "waiting for command";
        case DIR_CONN_STATE_SERVER_WRITING: return "writing";
      }
      break;
    case CONN_TYPE_CPUWORKER:
      switch (state) {
        case CPUWORKER_STATE_IDLE: return "idle";
        case CPUWORKER_STATE_BUSY_ONION: return "busy with onion";
      }
      break;
    case CONN_TYPE_CONTROL:
      switch (state) {
        case CONTROL_CONN_STATE_OPEN: return "open (protocol v1)";
        case CONTROL_CONN_STATE_NEEDAUTH:
          return "waiting for authentication (protocol v1)";
      }
      break;
  }

  log_warn(LD_BUG, "unknown connection state %d (type %d)", state, type);
  tor_snprintf(buf, sizeof(buf),
               "unknown state [%d] on unknown [%s] connection",
               state, conn_type_to_string(type));
  return buf;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* conn_type_to_string ( int  type)

Return the human-readable name for the connection type type

Definition at line 104 of file connection.c.

{
  static char buf[64];
  switch (type) {
    case CONN_TYPE_OR_LISTENER: return "OR listener";
    case CONN_TYPE_OR: return "OR";
    case CONN_TYPE_EXIT: return "Exit";
    case CONN_TYPE_AP_LISTENER: return "Socks listener";
    case CONN_TYPE_AP_TRANS_LISTENER:
      return "Transparent pf/netfilter listener";
    case CONN_TYPE_AP_NATD_LISTENER: return "Transparent natd listener";
    case CONN_TYPE_AP_DNS_LISTENER: return "DNS listener";
    case CONN_TYPE_AP: return "Socks";
    case CONN_TYPE_DIR_LISTENER: return "Directory listener";
    case CONN_TYPE_DIR: return "Directory";
    case CONN_TYPE_CPUWORKER: return "CPU worker";
    case CONN_TYPE_CONTROL_LISTENER: return "Control listener";
    case CONN_TYPE_CONTROL: return "Control";
    default:
      log_warn(LD_BUG, "unknown connection type %d", type);
      tor_snprintf(buf, sizeof(buf), "unknown [%d]", type);
      return buf;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Called when we're about to finally unlink and free a connection: perform necessary accounting and cleanup.

  • Directory conns that failed to fetch a rendezvous descriptor need to inform pending rendezvous streams.
  • OR conns need to call rep_hist_note_*() to record status.
  • AP conns need to send a socks reject if necessary.
  • Exit conns need to call connection_dns_remove() if necessary.
  • AP and Exit conns need to send an end cell if they can.
  • DNS conns need to fail any resolves that are pending on them.
  • OR and edge connections need to be unlinked from circuits.

Definition at line 611 of file connection.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void connection_bucket_init ( void  )

Initialize the global read bucket to options->BandwidthBurst.

Definition at line 2393 of file connection.c.

{
  const or_options_t *options = get_options();
  /* start it at max traffic */
  global_read_bucket = (int)options->BandwidthBurst;
  global_write_bucket = (int)options->BandwidthBurst;
  if (options->RelayBandwidthRate) {
    global_relayed_read_bucket = (int)options->RelayBandwidthBurst;
    global_relayed_write_bucket = (int)options->RelayBandwidthBurst;
  } else {
    global_relayed_read_bucket = (int)options->BandwidthBurst;
    global_relayed_write_bucket = (int)options->BandwidthBurst;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void connection_bucket_refill ( int  milliseconds_elapsed,
time_t  now 
)

Time has passed; increment buckets appropriately.

Definition at line 2439 of file connection.c.

{
  const or_options_t *options = get_options();
  smartlist_t *conns = get_connection_array();
  int bandwidthrate, bandwidthburst, relayrate, relayburst;

  bandwidthrate = (int)options->BandwidthRate;
  bandwidthburst = (int)options->BandwidthBurst;

  if (options->RelayBandwidthRate) {
    relayrate = (int)options->RelayBandwidthRate;
    relayburst = (int)options->RelayBandwidthBurst;
  } else {
    relayrate = bandwidthrate;
    relayburst = bandwidthburst;
  }

  tor_assert(milliseconds_elapsed >= 0);

  write_buckets_empty_last_second =
    global_relayed_write_bucket <= 0 || global_write_bucket <= 0;

  /* refill the global buckets */
  connection_bucket_refill_helper(&global_read_bucket,
                                  bandwidthrate, bandwidthburst,
                                  milliseconds_elapsed,
                                  "global_read_bucket");
  connection_bucket_refill_helper(&global_write_bucket,
                                  bandwidthrate, bandwidthburst,
                                  milliseconds_elapsed,
                                  "global_write_bucket");
  connection_bucket_refill_helper(&global_relayed_read_bucket,
                                  relayrate, relayburst,
                                  milliseconds_elapsed,
                                  "global_relayed_read_bucket");
  connection_bucket_refill_helper(&global_relayed_write_bucket,
                                  relayrate, relayburst,
                                  milliseconds_elapsed,
                                  "global_relayed_write_bucket");

  /* refill the per-connection buckets */
  SMARTLIST_FOREACH(conns, connection_t *, conn,
  {
    if (connection_speaks_cells(conn)) {
      or_connection_t *or_conn = TO_OR_CONN(conn);
      int orbandwidthrate = or_conn->bandwidthrate;
      int orbandwidthburst = or_conn->bandwidthburst;
      if (connection_bucket_should_increase(or_conn->read_bucket, or_conn)) {
        connection_bucket_refill_helper(&or_conn->read_bucket,
                                        orbandwidthrate,
                                        orbandwidthburst,
                                        milliseconds_elapsed,
                                        "or_conn->read_bucket");
      }
      if (connection_bucket_should_increase(or_conn->write_bucket, or_conn)) {
        connection_bucket_refill_helper(&or_conn->write_bucket,
                                        orbandwidthrate,
                                        orbandwidthburst,
                                        milliseconds_elapsed,
                                        "or_conn->write_bucket");
      }
    }

    if (conn->read_blocked_on_bw == 1 /* marked to turn reading back on now */
        && global_read_bucket > 0 /* and we're allowed to read */
        && (!connection_counts_as_relayed_traffic(conn, now) ||
            global_relayed_read_bucket > 0) /* even if we're relayed traffic */
        && (!connection_speaks_cells(conn) ||
            conn->state != OR_CONN_STATE_OPEN ||
            TO_OR_CONN(conn)->read_bucket > 0)) {
        /* and either a non-cell conn or a cell conn with non-empty bucket */
      LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET,
                         "waking up conn (fd %d) for read", (int)conn->s));
      conn->read_blocked_on_bw = 0;
      connection_start_reading(conn);
    }

    if (conn->write_blocked_on_bw == 1
        && global_write_bucket > 0 /* and we're allowed to write */
        && (!connection_counts_as_relayed_traffic(conn, now) ||
            global_relayed_write_bucket > 0) /* even if it's relayed traffic */
        && (!connection_speaks_cells(conn) ||
            conn->state != OR_CONN_STATE_OPEN ||
            TO_OR_CONN(conn)->write_bucket > 0)) {
      LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET,
                         "waking up conn (fd %d) for write", (int)conn->s));
      conn->write_blocked_on_bw = 0;
      connection_start_writing(conn);
    }
  });
}

Here is the call graph for this function:

Here is the caller graph for this function:

ssize_t connection_bucket_write_limit ( connection_t conn,
time_t  now 
)

How many bytes at most can we write onto this connection?

Definition at line 2151 of file connection.c.

{
  int base = connection_speaks_cells(conn) ?
               CELL_NETWORK_SIZE : RELAY_PAYLOAD_SIZE;
  int priority = conn->type != CONN_TYPE_DIR;
  int conn_bucket = (int)conn->outbuf_flushlen;
  int global_bucket = global_write_bucket;

  if (!connection_is_rate_limited(conn)) {
    /* be willing to write to local conns even if our buckets are empty */
    return conn->outbuf_flushlen;
  }

  if (connection_speaks_cells(conn)) {
    /* use the per-conn write limit if it's lower, but if it's less
     * than zero just use zero */
    or_connection_t *or_conn = TO_OR_CONN(conn);
    if (conn->state == OR_CONN_STATE_OPEN)
      if (or_conn->write_bucket < conn_bucket)
        conn_bucket = or_conn->write_bucket >= 0 ?
                        or_conn->write_bucket : 0;
  }

  if (connection_counts_as_relayed_traffic(conn, now) &&
      global_relayed_write_bucket <= global_write_bucket)
    global_bucket = global_relayed_write_bucket;

  return connection_bucket_round_robin(base, priority,
                                       global_bucket, conn_bucket);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Close the underlying socket for conn, so we don't try to flush it.

Must be used in conjunction with (right before) connection_mark_for_close().

Definition at line 641 of file connection.c.

{
  assert_connection_ok(conn,0);
  if (CONN_IS_CLOSED(conn)) {
    log_err(LD_BUG,"Attempt to close already-closed connection.");
    tor_fragile_assert();
    return;
  }
  if (conn->outbuf_flushlen) {
    log_info(LD_NET,"fd %d, type %s, state %s, %d bytes on outbuf.",
             (int)conn->s, conn_type_to_string(conn->type),
             conn_state_to_string(conn->type, conn->state),
             (int)conn->outbuf_flushlen);
  }

  connection_unregister_events(conn);

  if (SOCKET_OK(conn->s))
    tor_close_socket(conn->s);
  conn->s = TOR_INVALID_SOCKET;
  if (conn->linked)
    conn->linked_conn_is_closed = 1;
  if (conn->outbuf)
    buf_clear(conn->outbuf);
  conn->outbuf_flushlen = 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int connection_connect ( connection_t conn,
const char *  address,
const tor_addr_t addr,
uint16_t  port,
int *  socket_error 
)

Take conn, make a nonblocking socket; try to connect to addr:port (they arrive in host order).

If fail, return -1 and if applicable put your best guess about errno into *socket_error. Else assign s to conn->s: if connected return 1, if EAGAIN return 0.

address is used to make the logs useful.

On success, add conn to the list of polled connections.

Definition at line 1326 of file connection.c.

{
  tor_socket_t s;
  int inprogress = 0;
  struct sockaddr_storage addrbuf;
  struct sockaddr *dest_addr;
  int dest_addr_len;
  const or_options_t *options = get_options();
  int protocol_family;

  if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
    warn_too_many_conns();
    *socket_error = ENOBUFS;
    return -1;
  }

  if (tor_addr_family(addr) == AF_INET6)
    protocol_family = PF_INET6;
  else
    protocol_family = PF_INET;

  if (get_options()->DisableNetwork) {
    /* We should never even try to connect anyplace if DisableNetwork is set.
     * Warn if we do, and refuse to make the connection. */
    static ratelim_t disablenet_violated = RATELIM_INIT(30*60);
    char *m;
#ifdef _WIN32
    *socket_error = WSAENETUNREACH;
#else
    *socket_error = ENETUNREACH;
#endif
    if ((m = rate_limit_log(&disablenet_violated, approx_time()))) {
      log_warn(LD_BUG, "Tried to open a socket with DisableNetwork set.%s", m);
      tor_free(m);
    }
    tor_fragile_assert();
    return -1;
  }

  s = tor_open_socket(protocol_family,SOCK_STREAM,IPPROTO_TCP);
  if (! SOCKET_OK(s)) {
    *socket_error = tor_socket_errno(-1);
    log_warn(LD_NET,"Error creating network socket: %s",
             tor_socket_strerror(*socket_error));
    return -1;
  }

  make_socket_reuseable(s);

  if (options->OutboundBindAddress && !tor_addr_is_loopback(addr)) {
    struct sockaddr_in ext_addr;

    memset(&ext_addr, 0, sizeof(ext_addr));
    ext_addr.sin_family = AF_INET;
    ext_addr.sin_port = 0;
    if (!tor_inet_aton(options->OutboundBindAddress, &ext_addr.sin_addr)) {
      log_warn(LD_CONFIG,"Outbound bind address '%s' didn't parse. Ignoring.",
               options->OutboundBindAddress);
    } else {
      if (bind(s, (struct sockaddr*)&ext_addr,
               (socklen_t)sizeof(ext_addr)) < 0) {
        *socket_error = tor_socket_errno(s);
        log_warn(LD_NET,"Error binding network socket: %s",
                 tor_socket_strerror(*socket_error));
        tor_close_socket(s);
        return -1;
      }
    }
  }

  set_socket_nonblocking(s);

  if (options->ConstrainedSockets)
    set_constrained_socket_buffers(s, (int)options->ConstrainedSockSize);

  memset(&addrbuf,0,sizeof(addrbuf));
  dest_addr = (struct sockaddr*) &addrbuf;
  dest_addr_len = tor_addr_to_sockaddr(addr, port, dest_addr, sizeof(addrbuf));
  tor_assert(dest_addr_len > 0);

  log_debug(LD_NET, "Connecting to %s:%u.",
            escaped_safe_str_client(address), port);

  if (connect(s, dest_addr, (socklen_t)dest_addr_len) < 0) {
    int e = tor_socket_errno(s);
    if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
      /* yuck. kill it. */
      *socket_error = e;
      log_info(LD_NET,
               "connect() to %s:%u failed: %s",
               escaped_safe_str_client(address),
               port, tor_socket_strerror(e));
      tor_close_socket(s);
      return -1;
    } else {
      inprogress = 1;
    }
  }

  /* it succeeded. we're connected. */
  log_fn(inprogress?LOG_DEBUG:LOG_INFO, LD_NET,
         "Connection to %s:%u %s (sock %d).",
         escaped_safe_str_client(address),
         port, inprogress?"in progress":"established", s);
  conn->s = s;
  if (connection_add_connecting(conn) < 0) {
    /* no space, forget it */
    *socket_error = ENOBUFS;
    return -1;
  }
  return inprogress ? 0 : 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

dir_connection_t* connection_dir_get_by_purpose_and_resource ( int  state,
const char *  resource 
)

Return a directory connection (if any one exists) that is fetching the item described by state/resource

Definition at line 3595 of file connection.c.

{
  smartlist_t *conns = get_connection_array();

  SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
    dir_connection_t *dirconn;
    if (conn->type != CONN_TYPE_DIR || conn->marked_for_close ||
        conn->purpose != purpose)
      continue;
    dirconn = TO_DIR_CONN(conn);
    if (dirconn->requested_resource == NULL) {
      if (resource == NULL)
        return dirconn;
    } else if (resource) {
      if (0 == strcmp(resource, dirconn->requested_resource))
        return dirconn;
    }
  } SMARTLIST_FOREACH_END(conn);

  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void connection_dump_buffer_mem_stats ( int  severity)

Log how many bytes are used by buffers of different kinds and sizes.

Definition at line 3963 of file connection.c.

{
  uint64_t used_by_type[_CONN_TYPE_MAX+1];
  uint64_t alloc_by_type[_CONN_TYPE_MAX+1];
  int n_conns_by_type[_CONN_TYPE_MAX+1];
  uint64_t total_alloc = 0;
  uint64_t total_used = 0;
  int i;
  smartlist_t *conns = get_connection_array();

  memset(used_by_type, 0, sizeof(used_by_type));
  memset(alloc_by_type, 0, sizeof(alloc_by_type));
  memset(n_conns_by_type, 0, sizeof(n_conns_by_type));

  SMARTLIST_FOREACH(conns, connection_t *, c,
  {
    int tp = c->type;
    ++n_conns_by_type[tp];
    if (c->inbuf) {
      used_by_type[tp] += buf_datalen(c->inbuf);
      alloc_by_type[tp] += buf_allocation(c->inbuf);
    }
    if (c->outbuf) {
      used_by_type[tp] += buf_datalen(c->outbuf);
      alloc_by_type[tp] += buf_allocation(c->outbuf);
    }
  });
  for (i=0; i <= _CONN_TYPE_MAX; ++i) {
    total_used += used_by_type[i];
    total_alloc += alloc_by_type[i];
  }

  log(severity, LD_GENERAL,
     "In buffers for %d connections: "U64_FORMAT" used/"U64_FORMAT" allocated",
      smartlist_len(conns),
      U64_PRINTF_ARG(total_used), U64_PRINTF_ARG(total_alloc));
  for (i=_CONN_TYPE_MIN; i <= _CONN_TYPE_MAX; ++i) {
    if (!n_conns_by_type[i])
      continue;
    log(severity, LD_GENERAL,
        "  For %d %s connections: "U64_FORMAT" used/"U64_FORMAT" allocated",
        n_conns_by_type[i], conn_type_to_string(i),
        U64_PRINTF_ARG(used_by_type[i]), U64_PRINTF_ARG(alloc_by_type[i]));
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void connection_expire_held_open ( void  )

Find each connection that has hold_open_until_flushed set to 1 but hasn't written in the past 15 seconds, and set hold_open_until_flushed to 0.

This means it will get cleaned up in the next loop through close_if_marked() in main.c.

Definition at line 702 of file connection.c.

{
  time_t now;
  smartlist_t *conns = get_connection_array();

  now = time(NULL);

  SMARTLIST_FOREACH(conns, connection_t *, conn,
  {
    /* If we've been holding the connection open, but we haven't written
     * for 15 seconds...
     */
    if (conn->hold_open_until_flushed) {
      tor_assert(conn->marked_for_close);
      if (now - conn->timestamp_lastwritten >= 15) {
        int severity;
        if (conn->type == CONN_TYPE_EXIT ||
            (conn->type == CONN_TYPE_DIR &&
             conn->purpose == DIR_PURPOSE_SERVER))
          severity = LOG_INFO;
        else
          severity = LOG_NOTICE;
        log_fn(severity, LD_NET,
               "Giving up on marked_for_close conn that's been flushing "
               "for 15s (fd %d, type %s, state %s).",
               (int)conn->s, conn_type_to_string(conn->type),
               conn_state_to_string(conn->type, conn->state));
        conn->hold_open_until_flushed = 0;
      }
    }
  });
}

Here is the call graph for this function:

Here is the caller graph for this function:

int connection_fetch_from_buf ( char *  string,
size_t  len,
connection_t conn 
)

A pass-through to fetch_from_buf.

Definition at line 3074 of file connection.c.

{
  IF_HAS_BUFFEREVENT(conn, {
    /* XXX overflow -seb */
    return (int)bufferevent_read(conn->bufev, string, len);
  }) ELSE_IF_NO_BUFFEREVENT {
    return fetch_from_buf(string, len, conn->inbuf);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int connection_fetch_from_buf_http ( connection_t conn,
char **  headers_out,
size_t  max_headerlen,
char **  body_out,
size_t *  body_used,
size_t  max_bodylen,
int  force_complete 
)

As fetch_from_buf_http, but fetches from a conncetion's input buffer_t or its bufferevent as appropriate.

Definition at line 3113 of file connection.c.

{
  IF_HAS_BUFFEREVENT(conn, {
    struct evbuffer *input = bufferevent_get_input(conn->bufev);
    return fetch_from_evbuffer_http(input, headers_out, max_headerlen,
                            body_out, body_used, max_bodylen, force_complete);
  }) ELSE_IF_NO_BUFFEREVENT {
    return fetch_from_buf_http(conn->inbuf, headers_out, max_headerlen,
                            body_out, body_used, max_bodylen, force_complete);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int connection_fetch_from_buf_line ( connection_t conn,
char *  data,
size_t *  data_len 
)

As fetch_from_buf_line(), but read from a connection's input buffer.

Definition at line 3086 of file connection.c.

{
  IF_HAS_BUFFEREVENT(conn, {
    int r;
    size_t eol_len=0;
    struct evbuffer *input = bufferevent_get_input(conn->bufev);
    struct evbuffer_ptr ptr =
      evbuffer_search_eol(input, NULL, &eol_len, EVBUFFER_EOL_LF);
    if (ptr.pos == -1)
      return 0; /* No EOL found. */
    if ((size_t)ptr.pos+eol_len >= *data_len) {
      return -1; /* Too long */
    }
    *data_len = ptr.pos+eol_len;
    r = evbuffer_remove(input, data, ptr.pos+eol_len);
    tor_assert(r >= 0);
    data[ptr.pos+eol_len] = '\0';
    return 1;
  }) ELSE_IF_NO_BUFFEREVENT {
    return fetch_from_buf_line(conn->inbuf, data, data_len);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int connection_flush ( connection_t conn)

Try to flush data that's waiting for a write on conn.

Return -1 on failure, 0 on success.

Don't use this function for regular writing; the buffers/bufferevents system should be good enough at scheduling writes there. Instead, this function is for cases when we're about to exit or something and we want to report it right away.

Definition at line 3356 of file connection.c.

{
  IF_HAS_BUFFEREVENT(conn, {
      int r = bufferevent_flush(conn->bufev, EV_WRITE, BEV_FLUSH);
      return (r < 0) ? -1 : 0;
  });
  return connection_handle_write(conn, 1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void connection_free ( connection_t conn)

Make sure conn isn't in any of the global conn lists; then free it.

Definition at line 571 of file connection.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void connection_free_all ( void  )

Call _connection_free() on every connection in our array, and release all storage held by connection.c.

This is used by cpuworkers and dnsworkers when they fork, so they don't keep resources held open (especially sockets).

Don't do the checks in connection_free(), because they will fail.

Definition at line 4274 of file connection.c.

{
  smartlist_t *conns = get_connection_array();

  /* We don't want to log any messages to controllers. */
  SMARTLIST_FOREACH(conns, connection_t *, conn,
    if (conn->type == CONN_TYPE_CONTROL)
      TO_CONTROL_CONN(conn)->event_mask = 0);

  control_update_global_event_mask();

  /* Unlink everything from the identity map. */
  connection_or_clear_identity_map();

  /* Clear out our list of broken connections */
  clear_broken_connection_map(0);

  SMARTLIST_FOREACH(conns, connection_t *, conn, _connection_free(conn));

  if (outgoing_addrs) {
    SMARTLIST_FOREACH(outgoing_addrs, tor_addr_t *, addr, tor_free(addr));
    smartlist_free(outgoing_addrs);
    outgoing_addrs = NULL;
  }

#ifdef USE_BUFFEREVENTS
  if (global_rate_limit)
    bufferevent_rate_limit_group_free(global_rate_limit);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return the stream with id id if it is not already marked for close.

Definition at line 3519 of file connection.c.

{
  smartlist_t *conns = get_connection_array();
  SMARTLIST_FOREACH(conns, connection_t *, conn,
  {
    if (conn->global_identifier == id)
      return conn;
  });
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return a connection of type type that is not marked for close.

Definition at line 3533 of file connection.c.

{
  smartlist_t *conns = get_connection_array();
  SMARTLIST_FOREACH(conns, connection_t *, conn,
  {
    if (conn->type == type && !conn->marked_for_close)
      return conn;
  });
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

connection_t* connection_get_by_type_addr_port_purpose ( int  type,
const tor_addr_t addr,
uint16_t  port,
int  purpose 
)

Return a connection with given type, address, port, and purpose; or NULL if no such connection exists.

Definition at line 3498 of file connection.c.

{
  smartlist_t *conns = get_connection_array();
  SMARTLIST_FOREACH(conns, connection_t *, conn,
  {
    if (conn->type == type &&
        tor_addr_eq(&conn->addr, addr) &&
        conn->port == port &&
        conn->purpose == purpose &&
        !conn->marked_for_close)
      return conn;
  });
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

connection_t* connection_get_by_type_purpose ( int  type,
int  purpose 
)

Return an open, non-marked connection of a given type and purpose, or NULL if no such connection exists.

Definition at line 3621 of file connection.c.

{
  smartlist_t *conns = get_connection_array();
  SMARTLIST_FOREACH(conns, connection_t *, conn,
  {
    if (conn->type == type &&
        !conn->marked_for_close &&
        (purpose == conn->purpose))
      return conn;
  });
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

connection_t* connection_get_by_type_state ( int  type,
int  state 
)

Return a connection of type type that is in state state, and that is not marked for close.

Definition at line 3548 of file connection.c.

{
  smartlist_t *conns = get_connection_array();
  SMARTLIST_FOREACH(conns, connection_t *, conn,
  {
    if (conn->type == type && conn->state == state && !conn->marked_for_close)
      return conn;
  });
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

connection_t* connection_get_by_type_state_rendquery ( int  type,
int  state,
const char *  rendquery 
)

Return a connection of type type that has rendquery equal to rendquery, and that is not marked for close.

If state is non-zero, conn must be of that state too.

Definition at line 3564 of file connection.c.

{
  smartlist_t *conns = get_connection_array();

  tor_assert(type == CONN_TYPE_DIR ||
             type == CONN_TYPE_AP || type == CONN_TYPE_EXIT);
  tor_assert(rendquery);

  SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
    if (conn->type == type &&
        !conn->marked_for_close &&
        (!state || state == conn->state)) {
      if (type == CONN_TYPE_DIR &&
          TO_DIR_CONN(conn)->rend_data &&
          !rend_cmp_service_ids(rendquery,
                                TO_DIR_CONN(conn)->rend_data->onion_address))
        return conn;
      else if (CONN_IS_EDGE(conn) &&
               TO_EDGE_CONN(conn)->rend_data &&
               !rend_cmp_service_ids(rendquery,
                            TO_EDGE_CONN(conn)->rend_data->onion_address))
        return conn;
    }
  } SMARTLIST_FOREACH_END(conn);
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static INLINE size_t connection_get_inbuf_len ( connection_t conn) [static]

Definition at line 119 of file connection.h.

{
  IF_HAS_BUFFEREVENT(conn, {
    return evbuffer_get_length(bufferevent_get_input(conn->bufev));
  }) ELSE_IF_NO_BUFFEREVENT {
    return conn->inbuf ? buf_datalen(conn->inbuf) : 0;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static INLINE size_t connection_get_outbuf_len ( connection_t conn) [static]

Definition at line 129 of file connection.h.

{
  IF_HAS_BUFFEREVENT(conn, {
    return evbuffer_get_length(bufferevent_get_output(conn->bufev));
  }) ELSE_IF_NO_BUFFEREVENT {
    return conn->outbuf ? buf_datalen(conn->outbuf) : 0;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2745 of file connection.c.

{
  int res;

  tor_gettimeofday_cache_clear();
  res = connection_handle_read_impl(conn);
  return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int connection_handle_write ( connection_t conn,
int  force 
)

Definition at line 3338 of file connection.c.

{
    int res;
    tor_gettimeofday_cache_clear();
    res = connection_handle_write_impl(conn, force);
    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return 1 if conn is a listener conn, else return 0.

Definition at line 3636 of file connection.c.

Here is the caller graph for this function:

void connection_link_connections ( connection_t conn_a,
connection_t conn_b 
)

Create a link between conn_a and conn_b.

Definition at line 401 of file connection.c.

{
  tor_assert(! SOCKET_OK(conn_a->s));
  tor_assert(! SOCKET_OK(conn_b->s));

  conn_a->linked = 1;
  conn_b->linked = 1;
  conn_a->linked_conn = conn_b;
  conn_b->linked_conn = conn_a;
}

Here is the caller graph for this function:

Mark every external connection not used for controllers for close.

Definition at line 2013 of file connection.c.

{
  SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
    if (conn->marked_for_close)
      continue;
    switch (conn->type) {
      case CONN_TYPE_CPUWORKER:
      case CONN_TYPE_CONTROL_LISTENER:
      case CONN_TYPE_CONTROL:
        break;
      case CONN_TYPE_AP:
        connection_mark_unattached_ap(TO_ENTRY_CONN(conn),
                                      END_STREAM_REASON_HIBERNATING);
        break;
      default:
        connection_mark_for_close(conn);
        break;
    }
  } SMARTLIST_FOREACH_END(conn);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Mark every listener of type other than CONTROL_LISTENER to be closed.

Definition at line 1999 of file connection.c.

{
  SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
    if (conn->marked_for_close)
      continue;
    if (conn->type == CONN_TYPE_CONTROL_LISTENER)
      continue;
    if (connection_is_listener(conn))
      connection_mark_for_close(conn);
  } SMARTLIST_FOREACH_END(conn);
}

Here is the call graph for this function:

Here is the caller graph for this function:

connection_t* connection_new ( int  type,
int  socket_family 
)

Allocate, initialize, and return a new connection_t subtype of type to make or receive connections of address family socket_family.

The type should be one of the CONN_TYPE_* constants.

Definition at line 309 of file connection.c.

{
  switch (type) {
    case CONN_TYPE_OR:
      return TO_CONN(or_connection_new(socket_family));

    case CONN_TYPE_EXIT:
      return TO_CONN(edge_connection_new(type, socket_family));

    case CONN_TYPE_AP:
      return ENTRY_TO_CONN(entry_connection_new(type, socket_family));

    case CONN_TYPE_DIR:
      return TO_CONN(dir_connection_new(socket_family));

    case CONN_TYPE_CONTROL:
      return TO_CONN(control_connection_new(socket_family));

    CASE_ANY_LISTENER_TYPE:
      return TO_CONN(listener_connection_new(type, socket_family));

    default: {
      connection_t *conn = tor_malloc_zero(sizeof(connection_t));
      connection_init(time(NULL), conn, type, socket_family);
      return conn;
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return 1 if we initiated this connection, or 0 if it started out as an incoming connection.

Definition at line 1363 of file connection_or.c.

{
  tor_assert(conn->_base.type == CONN_TYPE_OR);
  if (!conn->tls)
    return 1; /* it's still in proxy states or something */
  if (conn->handshake_state)
    return conn->handshake_state->started_here;
  return !tor_tls_is_server(conn->tls);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Are there too many bytes on edge connection conn's outbuf to send back a relay-level sendme yet? Return 1 if so, 0 if not.

Used by connection_edge_consider_sending_sendme().

Definition at line 3141 of file connection.c.

{
  return (conn->outbuf_flushlen > 10*CELL_PAYLOAD_SIZE);
}

Here is the caller graph for this function:

int connection_proxy_connect ( connection_t conn,
int  type 
)

Write a proxy request of type (socks4, socks5, https) to conn for conn->addr:conn->port, authenticating with the auth details given in the configuration (if available).

SOCKS 5 and HTTP CONNECT proxies support authentication.

Returns -1 if conn->addr is incompatible with the proxy protocol, and 0 otherwise.

Use connection_read_proxy_handshake() to complete the handshake.

Definition at line 1475 of file connection.c.

{
  const or_options_t *options;

  tor_assert(conn);

  options = get_options();

  switch (type) {
    case PROXY_CONNECT: {
      char buf[1024];
      char *base64_authenticator=NULL;
      const char *authenticator = options->HTTPSProxyAuthenticator;

      /* Send HTTP CONNECT and authentication (if available) in
       * one request */

      if (authenticator) {
        base64_authenticator = alloc_http_authenticator(authenticator);
        if (!base64_authenticator)
          log_warn(LD_OR, "Encoding https authenticator failed");
      }

      if (base64_authenticator) {
        const char *addr = fmt_addr(&conn->addr);
        tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1\r\n"
                     "Host: %s:%d\r\n"
                     "Proxy-Authorization: Basic %s\r\n\r\n",
                     addr, conn->port,
                     addr, conn->port,
                     base64_authenticator);
        tor_free(base64_authenticator);
      } else {
        tor_snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n\r\n",
                     fmt_addr(&conn->addr), conn->port);
      }

      connection_write_to_buf(buf, strlen(buf), conn);
      conn->proxy_state = PROXY_HTTPS_WANT_CONNECT_OK;
      break;
    }

    case PROXY_SOCKS4: {
      unsigned char buf[9];
      uint16_t portn;
      uint32_t ip4addr;

      /* Send a SOCKS4 connect request with empty user id */

      if (tor_addr_family(&conn->addr) != AF_INET) {
        log_warn(LD_NET, "SOCKS4 client is incompatible with IPv6");
        return -1;
      }

      ip4addr = tor_addr_to_ipv4n(&conn->addr);
      portn = htons(conn->port);

      buf[0] = 4; /* version */
      buf[1] = SOCKS_COMMAND_CONNECT; /* command */
      memcpy(buf + 2, &portn, 2); /* port */
      memcpy(buf + 4, &ip4addr, 4); /* addr */
      buf[8] = 0; /* userid (empty) */

      connection_write_to_buf((char *)buf, sizeof(buf), conn);
      conn->proxy_state = PROXY_SOCKS4_WANT_CONNECT_OK;
      break;
    }

    case PROXY_SOCKS5: {
      unsigned char buf[4]; /* fields: vers, num methods, method list */

      /* Send a SOCKS5 greeting (connect request must wait) */

      buf[0] = 5; /* version */

      /* number of auth methods */
      if (options->Socks5ProxyUsername) {
        buf[1] = 2;
        buf[2] = 0x00; /* no authentication */
        buf[3] = 0x02; /* rfc1929 Username/Passwd auth */
        conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929;
      } else {
        buf[1] = 1;
        buf[2] = 0x00; /* no authentication */
        conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_NONE;
      }

      connection_write_to_buf((char *)buf, 2 + buf[1], conn);
      break;
    }

    default:
      log_err(LD_BUG, "Invalid proxy protocol, %d", type);
      tor_fragile_assert();
      return -1;
  }

  log_debug(LD_NET, "set state %s",
            connection_proxy_state_to_string(conn->proxy_state));

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Call this from connection_*_process_inbuf() to advance the proxy handshake.

No matter what proxy protocol is used, if this function returns 1, the handshake is complete, and the data remaining on inbuf may contain the start of the communication with the requested server.

Returns 0 if the current buffer contains an incomplete response, and -1 on error.

Definition at line 1697 of file connection.c.

{
  int ret = 0;
  char *reason = NULL;

  log_debug(LD_NET, "enter state %s",
            connection_proxy_state_to_string(conn->proxy_state));

  switch (conn->proxy_state) {
    case PROXY_HTTPS_WANT_CONNECT_OK:
      ret = connection_read_https_proxy_response(conn);
      if (ret == 1)
        conn->proxy_state = PROXY_CONNECTED;
      break;

    case PROXY_SOCKS4_WANT_CONNECT_OK:
      ret = connection_fetch_from_buf_socks_client(conn,
                                                   conn->proxy_state,
                                                   &reason);
      if (ret == 1)
        conn->proxy_state = PROXY_CONNECTED;
      break;

    case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
      ret = connection_fetch_from_buf_socks_client(conn,
                                                   conn->proxy_state,
                                                   &reason);
      /* no auth needed, do connect */
      if (ret == 1) {
        connection_send_socks5_connect(conn);
        ret = 0;
      }
      break;

    case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
      ret = connection_fetch_from_buf_socks_client(conn,
                                                   conn->proxy_state,
                                                   &reason);

      /* send auth if needed, otherwise do connect */
      if (ret == 1) {
        connection_send_socks5_connect(conn);
        ret = 0;
      } else if (ret == 2) {
        unsigned char buf[1024];
        size_t reqsize, usize, psize;
        const char *user, *pass;

        user = get_options()->Socks5ProxyUsername;
        pass = get_options()->Socks5ProxyPassword;
        tor_assert(user && pass);

        /* XXX len of user and pass must be <= 255 !!! */
        usize = strlen(user);
        psize = strlen(pass);
        tor_assert(usize <= 255 && psize <= 255);
        reqsize = 3 + usize + psize;

        buf[0] = 1; /* negotiation version */
        buf[1] = usize;
        memcpy(buf + 2, user, usize);
        buf[2 + usize] = psize;
        memcpy(buf + 3 + usize, pass, psize);

        connection_write_to_buf((char *)buf, reqsize, conn);

        conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_RFC1929_OK;
        ret = 0;
      }
      break;

    case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
      ret = connection_fetch_from_buf_socks_client(conn,
                                                   conn->proxy_state,
                                                   &reason);
      /* send the connect request */
      if (ret == 1) {
        connection_send_socks5_connect(conn);
        ret = 0;
      }
      break;

    case PROXY_SOCKS5_WANT_CONNECT_OK:
      ret = connection_fetch_from_buf_socks_client(conn,
                                                   conn->proxy_state,
                                                   &reason);
      if (ret == 1)
        conn->proxy_state = PROXY_CONNECTED;
      break;

    default:
      log_err(LD_BUG, "Invalid proxy_state for reading, %d",
              conn->proxy_state);
      tor_fragile_assert();
      ret = -1;
      break;
  }

  log_debug(LD_NET, "leaving state %s",
            connection_proxy_state_to_string(conn->proxy_state));

  if (ret < 0) {
    if (reason) {
      log_warn(LD_NET, "Proxy Client: unable to connect to %s:%d (%s)",
                conn->address, conn->port, escaped(reason));
      tor_free(reason);
    } else {
      log_warn(LD_NET, "Proxy Client: unable to connect to %s:%d",
                conn->address, conn->port);
    }
  } else if (ret == 1) {
    log_info(LD_NET, "Proxy Client: connection to %s:%d successful",
              conn->address, conn->port);
  }

  return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return 1 if conn is in 'connecting' state, else return 0.

Definition at line 3672 of file connection.c.

{
  tor_assert(conn);

  if (conn->marked_for_close)
    return 0;
  switch (conn->type)
    {
    case CONN_TYPE_OR:
      return conn->state == OR_CONN_STATE_CONNECTING;
    case CONN_TYPE_EXIT:
      return conn->state == EXIT_CONN_STATE_CONNECTING;
    case CONN_TYPE_DIR:
      return conn->state == DIR_CONN_STATE_CONNECTING;
    }

  return 0;
}

Here is the caller graph for this function:

Return 1 if conn is in state "open" and is not marked for close, else return 0.

Definition at line 3653 of file connection.c.

{
  tor_assert(conn);

  if (conn->marked_for_close)
    return 0;

  if ((conn->type == CONN_TYPE_OR && conn->state == OR_CONN_STATE_OPEN) ||
      (conn->type == CONN_TYPE_AP && conn->state == AP_CONN_STATE_OPEN) ||
      (conn->type == CONN_TYPE_EXIT && conn->state == EXIT_CONN_STATE_OPEN) ||
      (conn->type == CONN_TYPE_CONTROL &&
       conn->state == CONTROL_CONN_STATE_OPEN))
    return 1;

  return 0;
}

Here is the caller graph for this function:

Return conn->outbuf_flushlen: how many bytes conn wants to flush from its outbuf.

Definition at line 3131 of file connection.c.

{
  return conn->outbuf_flushlen > 0;
}

Here is the caller graph for this function:

static INLINE void connection_write_to_buf ( const char *  string,
size_t  len,
connection_t conn 
) [static]

Definition at line 102 of file connection.h.

{
  _connection_write_to_buf_impl(string, len, conn, 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static INLINE void connection_write_to_buf_zlib ( const char *  string,
size_t  len,
dir_connection_t conn,
int  done 
) [static]

Definition at line 107 of file connection.h.

{
  _connection_write_to_buf_impl(string, len, TO_CONN(conn), done ? -1 : 1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Allocate and return a new control_connection_t, initialized as by connection_init().

Definition at line 284 of file connection.c.

{
  control_connection_t *control_conn =
    tor_malloc_zero(sizeof(control_connection_t));
  connection_init(time(NULL),
                  TO_CONN(control_conn), CONN_TYPE_CONTROL, socket_family);
  log_notice(LD_CONTROL, "New control connection opened.");
  return control_conn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

dir_connection_t* dir_connection_new ( int  socket_family)

Allocate and return a new dir_connection_t, initialized as by connection_init().

Definition at line 233 of file connection.c.

{
  dir_connection_t *dir_conn = tor_malloc_zero(sizeof(dir_connection_t));
  connection_init(time(NULL), TO_CONN(dir_conn), CONN_TYPE_DIR, socket_family);
  return dir_conn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

edge_connection_t* edge_connection_new ( int  type,
int  socket_family 
)

Allocate and return a new edge_connection_t, initialized as by connection_init().

Definition at line 273 of file connection.c.

{
  edge_connection_t *edge_conn = tor_malloc_zero(sizeof(edge_connection_t));
  tor_assert(type == CONN_TYPE_EXIT);
  connection_init(time(NULL), TO_CONN(edge_conn), type, socket_family);
  return edge_conn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

entry_connection_t* entry_connection_new ( int  type,
int  socket_family 
)

Allocate and return a new entry_connection_t, initialized as by connection_init().

Definition at line 261 of file connection.c.

{
  entry_connection_t *entry_conn = tor_malloc_zero(sizeof(entry_connection_t));
  tor_assert(type == CONN_TYPE_AP);
  connection_init(time(NULL), ENTRY_TO_CONN(entry_conn), type, socket_family);
  entry_conn->socks_request = socks_request_new();
  return entry_conn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int get_proxy_addrport ( tor_addr_t addr,
uint16_t *  port,
int *  proxy_type,
const connection_t conn 
)

Fills addr and port with the details of the global proxy server we are using.

conn contains the connection we are using the proxy for.

Return 0 on success, -1 on failure.

Definition at line 4174 of file connection.c.

{
  const or_options_t *options = get_options();

  if (options->HTTPSProxy) {
    tor_addr_copy(addr, &options->HTTPSProxyAddr);
    *port = options->HTTPSProxyPort;
    *proxy_type = PROXY_CONNECT;
    return 0;
  } else if (options->Socks4Proxy) {
    tor_addr_copy(addr, &options->Socks4ProxyAddr);
    *port = options->Socks4ProxyPort;
    *proxy_type = PROXY_SOCKS4;
    return 0;
  } else if (options->Socks5Proxy) {
    tor_addr_copy(addr, &options->Socks5ProxyAddr);
    *port = options->Socks5ProxyPort;
    *proxy_type = PROXY_SOCKS5;
    return 0;
  } else if (options->ClientTransportPlugin ||
             options->Bridges) {
    const transport_t *transport = NULL;
    int r;
    r = find_transport_by_bridge_addrport(&conn->addr, conn->port, &transport);
    if (r<0)
      return -1;
    if (transport) { /* transport found */
      tor_addr_copy(addr, &transport->addr);
      *port = transport->port;
      *proxy_type = transport->socks_version;
      return 0;
    }
  }

  *proxy_type = PROXY_NONE;
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int global_write_bucket_low ( connection_t conn,
size_t  attempt,
int  priority 
)

Return 1 if the global write buckets are low enough that we shouldn't send attempt bytes of low-priority directory stuff out to conn.

Else return 0.

Priority is 1 for v1 requests (directories and running-routers), and 2 for v2 requests (statuses and descriptors). But see FFFF in directory_handle_command_get() for why we don't use priority 2 yet.

There are a lot of parameters we could use here:

  • global_relayed_write_bucket. Low is bad.
  • global_write_bucket. Low is bad.
  • bandwidthrate. Low is bad.
  • bandwidthburst. Not a big factor?
  • attempt. High is bad.
  • total bytes queued on outbufs. High is bad. But I'm wary of using this, since a few slow-flushing queues will pump up the number without meaning what we meant to mean. What we really mean is "total directory bytes added to outbufs recently", but that's harder to quantify and harder to keep track of.

Definition at line 2217 of file connection.c.

{
#ifdef USE_BUFFEREVENTS
  ssize_t smaller_bucket = bufferevent_get_max_to_write(conn->bufev);
#else
  int smaller_bucket = global_write_bucket < global_relayed_write_bucket ?
                       global_write_bucket : global_relayed_write_bucket;
#endif
  if (authdir_mode(get_options()) && priority>1)
    return 0; /* there's always room to answer v2 if we're an auth dir */

  if (!connection_is_rate_limited(conn))
    return 0; /* local conns don't get limited */

  if (smaller_bucket < (int)attempt)
    return 1; /* not enough space no matter the priority */

#ifndef USE_BUFFEREVENTS
  if (write_buckets_empty_last_second)
    return 1; /* we're already hitting our limits, no more please */
#endif

  if (priority == 1) { /* old-style v1 query */
    /* Could we handle *two* of these requests within the next two seconds? */
    const or_options_t *options = get_options();
    int64_t can_write = (int64_t)smaller_bucket
      + 2*(options->RelayBandwidthRate ? options->RelayBandwidthRate :
                                         options->BandwidthRate);
    if (can_write < 2*(int64_t)attempt)
      return 1;
  } else { /* v2 query */
    /* no further constraints yet */
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

listener_connection_t* listener_connection_new ( int  type,
int  socket_family 
)

Allocate and return a new listener_connection_t, initialized as by connection_init().

Definition at line 297 of file connection.c.

{
  listener_connection_t *listener_conn =
    tor_malloc_zero(sizeof(listener_connection_t));
  connection_init(time(NULL), TO_CONN(listener_conn), type, socket_family);
  return listener_conn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Log a failed connection to a proxy server.

conn is the connection we use the proxy server for.

Definition at line 4234 of file connection.c.

{
  tor_addr_t proxy_addr;
  uint16_t proxy_port;
  int proxy_type;

  if (get_proxy_addrport(&proxy_addr, &proxy_port, &proxy_type, conn) != 0)
    return; /* if we have no proxy set up, leave this function. */

  log_warn(LD_NET,
           "The connection to the %s proxy server at %s:%u just failed. "
           "Make sure that the proxy server is up and running.",
           proxy_type_to_string(get_proxy_type()), fmt_addr(&proxy_addr),
           proxy_port);
}

Here is the call graph for this function:

Here is the caller graph for this function:

or_connection_t* or_connection_new ( int  socket_family)

Allocate and return a new or_connection_t, initialized as by connection_init().

Definition at line 243 of file connection.c.

{
  or_connection_t *or_conn = tor_malloc_zero(sizeof(or_connection_t));
  time_t now = time(NULL);
  connection_init(now, TO_CONN(or_conn), CONN_TYPE_OR, socket_family);

  or_conn->timestamp_last_added_nonpadding = time(NULL);
  or_conn->next_circ_id = crypto_rand_int(1<<15);

  or_conn->active_circuit_pqueue = smartlist_new();
  or_conn->active_circuit_pqueue_last_recalibrated = cell_ewma_get_tick();

  return or_conn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void remove_file_if_very_old ( const char *  fname,
time_t  now 
)

Given a file name check to see whether the file exists but has not been modified for a very long time.

If so, remove it.

Definition at line 7123 of file config.c.

{
#define VERY_OLD_FILE_AGE (28*24*60*60)
  struct stat st;

  if (stat(fname, &st)==0 && st.st_mtime < now-VERY_OLD_FILE_AGE) {
    char buf[ISO_TIME_LEN+1];
    format_local_iso_time(buf, st.st_mtime);
    log_notice(LD_GENERAL, "Obsolete file %s hasn't been modified since %s. "
               "Removing it.", fname, buf);
    unlink(fname);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int retry_all_listeners ( smartlist_t replaced_conns,
smartlist_t new_conns,
int  close_all_noncontrol 
)

Launch listeners for each port you should have open.

Only launch listeners who are not already open, and only close listeners we no longer want.

Add all old conns that should be closed to replaced_conns. Add all new connections to new_conns.

If close_all_noncontrol is true, then we only open control listeners, and we close all other listeners.

Definition at line 1949 of file connection.c.

{
  smartlist_t *listeners = smartlist_new();
  const or_options_t *options = get_options();
  int retval = 0;
  const uint16_t old_or_port = router_get_advertised_or_port(options);
  const uint16_t old_dir_port = router_get_advertised_dir_port(options, 0);

  SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
    if (connection_is_listener(conn) && !conn->marked_for_close)
      smartlist_add(listeners, conn);
  } SMARTLIST_FOREACH_END(conn);

  if (retry_listener_ports(listeners,
                           get_configured_ports(),
                           new_conns,
                           close_all_noncontrol) < 0)
    retval = -1;

  /* Any members that were still in 'listeners' don't correspond to
   * any configured port.  Kill 'em. */
  SMARTLIST_FOREACH_BEGIN(listeners, connection_t *, conn) {
    log_notice(LD_NET, "Closing no-longer-configured %s on %s:%d",
               conn_type_to_string(conn->type), conn->address, conn->port);
    if (replaced_conns) {
      smartlist_add(replaced_conns, conn);
    } else {
      connection_close_immediate(conn);
      connection_mark_for_close(conn);
    }
  } SMARTLIST_FOREACH_END(conn);

  smartlist_free(listeners);

  /* XXXprop186 should take all advertised ports into account */
  if (old_or_port != router_get_advertised_or_port(options) ||
      old_dir_port != router_get_advertised_dir_port(options, 0)) {
    /* Our chosen ORPort or DirPort is not what it used to be: the
     * descriptor we had (if any) should be regenerated.  (We won't
     * automatically notice this because of changes in the option,
     * since the value could be "auto".) */
    mark_my_descriptor_dirty("Chosen Or/DirPort changed");
  }

  return retval;
}

Here is the call graph for this function:

Here is the caller graph for this function: