From 8f6aa6688fa6c5bfa60e0935780f6f6f0c70410b Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Mon, 10 May 2004 01:32:57 +0000 Subject: [PATCH] function header comments for connection.c, including doxygen markup svn:r1825 --- src/or/connection.c | 174 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 148 insertions(+), 26 deletions(-) diff --git a/src/or/connection.c b/src/or/connection.c index 75d0981f32..e165dae33b 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -6,9 +6,9 @@ /********* START VARIABLES **********/ -extern or_options_t options; /* command-line and config-file options */ +extern or_options_t options; /**< command-line and config-file options */ -/* Array of strings to make conn->type human-readable */ +/** Array of strings to make conn->type human-readable */ char *conn_type_to_string[] = { "", /* 0 */ "OP listener", /* 1 */ @@ -24,7 +24,7 @@ char *conn_type_to_string[] = { "CPU worker", /* 11 */ }; -/* Array of string arrays to make {conn->type,conn->state} human-readable */ +/** Array of string arrays to make {conn->type,conn->state} human-readable */ char *conn_state_to_string[][_CONN_TYPE_MAX+1] = { { NULL }, /* no type associated with 0 */ { NULL }, /* op listener, obsolete */ @@ -74,7 +74,7 @@ static int connection_receiver_bucket_should_increase(connection_t *conn); /**************************************************************/ -/* Allocate space for a new connection_t. This function just initializes +/** Allocate space for a new connection_t. This function just initializes * conn; you must call connection_add() to link it into the main array. * * Set conn->type to 'type'. Set conn->s and conn->poll_index to @@ -114,8 +114,8 @@ connection_t *connection_new(int type) { return conn; } -/* Deallocate memory used by 'conn'. Deallocate its buffers if necessary, - * close its socket if necessary, and mark the directory as dirty if conn +/** Deallocate memory used by conn. Deallocate its buffers if necessary, + * close its socket if necessary, and mark the directory as dirty if conn * is an OR or OP connection. */ void connection_free(connection_t *conn) { @@ -147,6 +147,10 @@ void connection_free(connection_t *conn) { free(conn); } +/** Call connection_free() on every connection in our array. + * This is used by cpuworkers and dnsworkers when they fork, + * so they don't keep resources held open (especially sockets). + */ void connection_free_all(void) { int i, n; connection_t **carray; @@ -156,8 +160,9 @@ void connection_free_all(void) { connection_free(carray[i]); } -/* 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 +/** 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(). */ void connection_close_immediate(connection_t *conn) { @@ -178,6 +183,16 @@ void connection_close_immediate(connection_t *conn) } } +/** Mark conn to be closed next time we loop through + * conn_close_if_marked() in main.c. Do any cleanup needed: + * - Directory conns that fail 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. + */ int _connection_mark_for_close(connection_t *conn, char reason) { @@ -214,7 +229,6 @@ _connection_mark_for_close(connection_t *conn, char reason) } else { rep_hist_note_connection_died(conn->nickname, time(NULL)); } - /* No special processing needed. */ break; case CONN_TYPE_AP: if (conn->socks_request->has_finished == 0) { @@ -250,6 +264,11 @@ _connection_mark_for_close(connection_t *conn, char reason) return retval; } +/** 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. + */ void connection_expire_held_open(void) { connection_t **carray, *conn; @@ -275,6 +294,10 @@ void connection_expire_held_open(void) } } +/** Bind a new non-blocking socket listening to + * bindaddress:bindport, and add this new connection + * (of type type) to the connection array. + */ int connection_create_listener(char *bindaddress, uint16_t bindport, int type) { struct sockaddr_in bindaddr; /* where to bind */ connection_t *conn; @@ -328,6 +351,9 @@ int connection_create_listener(char *bindaddress, uint16_t bindport, int type) { return 0; } +/** The listener connection conn told poll() it wanted to read. + * Call accept() on conn->s, and add the new connection if necessary. + */ static int connection_handle_listener_read(connection_t *conn, int new_type) { int news; /* the new socket */ connection_t *newconn; @@ -367,6 +393,9 @@ static int connection_handle_listener_read(connection_t *conn, int new_type) { return 0; } +/** Initialize states for newly accepted connection conn. + * If conn is an OR, start the tls handshake. + */ static int connection_init_accepted_conn(connection_t *conn) { connection_start_reading(conn); @@ -385,11 +414,13 @@ static int connection_init_accepted_conn(connection_t *conn) { return 0; } -/* Take conn, make a nonblocking socket; try to connect to +/** Take conn, make a nonblocking socket; try to connect to * addr:port (they arrive in *host order*). If fail, return -1. 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. + * + * address is used to make the logs useful. + * + * On success, add 'conn' to the list of polled connections. */ int connection_connect(connection_t *conn, char *address, uint32_t addr, uint16_t port) { int s; @@ -434,6 +465,9 @@ int connection_connect(connection_t *conn, char *address, uint32_t addr, uint16_ return 1; } +/** If there exists a listener of type type in the connection + * array, mark it for close. + */ static void listener_close_if_present(int type) { connection_t *conn; tor_assert(type == CONN_TYPE_OR_LISTENER || @@ -446,7 +480,10 @@ static void listener_close_if_present(int type) { } } -/* start all connections that should be up but aren't */ +/** Start all connections that should be up but aren't. + * - Connect to all ORs if you're an OR. + * - Relaunch listeners for each port you have open. + */ int retry_all_connections(void) { if(options.ORPort) { @@ -480,9 +517,9 @@ int retry_all_connections(void) { return 0; } -extern int global_read_bucket; +extern int global_read_bucket; /**< from main.c */ -/* how many bytes at most can we read onto this connection? */ +/** How many bytes at most can we read onto this connection? */ int connection_bucket_read_limit(connection_t *conn) { int at_most; @@ -507,7 +544,7 @@ int connection_bucket_read_limit(connection_t *conn) { return at_most; } -/* we just read num_read onto conn. Decrement buckets appropriately. */ +/** We just read num_read onto conn. Decrement buckets appropriately. */ void connection_bucket_decrement(connection_t *conn, int num_read) { global_read_bucket -= num_read; tor_assert(global_read_bucket >= 0); if(connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) { @@ -528,15 +565,17 @@ void connection_bucket_decrement(connection_t *conn, int num_read) { } } -/* keep a timeval to know when time has passed enough to refill buckets */ +/** Keep a timeval to know when time has passed enough to refill buckets */ static struct timeval current_time; +/** Initiatialize the global read bucket to options.BandwidthBurst, + * and current_time to the current time. */ void connection_bucket_init(void) { tor_gettimeofday(¤t_time); global_read_bucket = options.BandwidthBurst; /* start it at max traffic */ } -/* some time has passed; increment buckets appropriately. */ +/** Some time has passed; increment buckets appropriately. */ void connection_bucket_refill(struct timeval *now) { int i, n; connection_t *conn; @@ -581,6 +620,9 @@ void connection_bucket_refill(struct timeval *now) { } } +/** Is the receiver bucket for connection conn low enough that we + * should add another pile of tokens to it? + */ static int connection_receiver_bucket_should_increase(connection_t *conn) { tor_assert(conn); @@ -596,6 +638,18 @@ static int connection_receiver_bucket_should_increase(connection_t *conn) { return 1; } +/** Read bytes from conn->s and process them. + * + * This function gets called from conn_read() in main.c, either + * when poll() has declared that conn wants to read, or (for OR conns) + * when there are pending TLS bytes. + * + * It calls connection_read_to_buf() to bring in any new bytes, + * and then calls connection_process_inbuf() to process them. + * + * Mark the connection and return -1 if you want to close it, else + * return 0. + */ int connection_handle_read(connection_t *conn) { conn->timestamp_lastread = time(NULL); @@ -628,7 +682,12 @@ int connection_handle_read(connection_t *conn) { return 0; } -/* return -1 if we want to break conn, else return 0 */ +/** Pull in new bytes from conn->s onto conn->inbuf, either + * directly or via TLS. Reduce the token buckets by the number of + * bytes read. + * + * Return -1 if we want to break conn, else return 0. + */ int connection_read_to_buf(connection_t *conn) { int result; int at_most; @@ -676,19 +735,39 @@ int connection_read_to_buf(connection_t *conn) { return 0; } +/** A pass-through to fetch_from_buf. */ int connection_fetch_from_buf(char *string, int len, connection_t *conn) { return fetch_from_buf(string, len, conn->inbuf); } +/** Return conn->outbuf_flushlen: how many bytes conn wants to flush + * from its outbuf. */ int connection_wants_to_flush(connection_t *conn) { return conn->outbuf_flushlen; } +/** 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(). + */ int connection_outbuf_too_full(connection_t *conn) { return (conn->outbuf_flushlen > 10*CELL_PAYLOAD_SIZE); } -/* mark and return -1 if you want to break the conn, else return 0 */ +/** Try to flush more bytes onto conn->s. + * + * This function gets called either from conn_write() in main.c + * when poll() has declared that conn wants to write, or below + * from connection_write_to_buf() when an entire TLS record is ready. + * + * Update conn->timestamp_lastwritten to now, and call flush_buf + * or flush_buf_tls appropriately. If it succeeds and there no more + * more bytes on conn->outbuf, then call connection_finished_flushing + * on it too. + * + * Mark the connection and return -1 if you want to close it, else + * return 0. + */ int connection_handle_write(connection_t *conn) { tor_assert(!connection_is_listener(conn)); @@ -754,6 +833,10 @@ int connection_handle_write(connection_t *conn) { return 0; } +/** Append len bytes of string onto conn's + * outbuf, and ask it to start writing. If it's an OR conn, and an + * entire TLS record is ready, then try to flush it now. + */ void connection_write_to_buf(const char *string, int len, connection_t *conn) { if(!len || conn->marked_for_close) @@ -788,7 +871,8 @@ void connection_write_to_buf(const char *string, int len, connection_t *conn) { } } -/* get the conn to addr/port that has the most recent timestamp_created */ +/** Return the conn to addr/port that has the most recent + * timestamp_created, or NULL if no such conn exists. */ connection_t *connection_exact_get_by_addr_port(uint32_t addr, uint16_t port) { int i, n; connection_t *conn, *best=NULL; @@ -804,12 +888,14 @@ connection_t *connection_exact_get_by_addr_port(uint32_t addr, uint16_t port) { return best; } +/** Find a connection to the router described by addr and port, + * or alternately any router with the same identity key. + * This connection *must* be in 'open' state. + * If not, return NULL. + */ +/* XXX this twin thing is busted, now that we're rotating onion + * keys. abandon/patch? */ connection_t *connection_twin_get_by_addr_port(uint32_t addr, uint16_t port) { - /* Find a connection to the router described by addr and port, - * or alternately any router which knows its key. - * This connection *must* be in 'open' state. - * If not, return NULL. - */ int i, n; connection_t *conn; routerinfo_t *router; @@ -841,6 +927,9 @@ connection_t *connection_twin_get_by_addr_port(uint32_t addr, uint16_t port) { return NULL; } +/** Return a connection of type type that is not marked for + * close. + */ connection_t *connection_get_by_type(int type) { int i, n; connection_t *conn; @@ -855,6 +944,9 @@ connection_t *connection_get_by_type(int type) { return NULL; } +/** Return a connection of type type that is in state state, + * and that is not marked for close. + */ connection_t *connection_get_by_type_state(int type, int state) { int i, n; connection_t *conn; @@ -869,6 +961,10 @@ connection_t *connection_get_by_type_state(int type, int state) { return NULL; } +/** Return the connection of type type that is in state + * state, that was written to least recently, and that is not + * marked for close. + */ connection_t *connection_get_by_type_state_lastwritten(int type, int state) { int i, n; connection_t *conn, *best=NULL; @@ -884,6 +980,9 @@ connection_t *connection_get_by_type_state_lastwritten(int type, int state) { return best; } +/** Return a connection of type type that has rendquery equal + * to rendquery, and that is not marked for close. + */ connection_t *connection_get_by_type_rendquery(int type, const char *rendquery) { int i, n; connection_t *conn; @@ -900,6 +999,7 @@ connection_t *connection_get_by_type_rendquery(int type, const char *rendquery) return NULL; } +/** Return 1 if conn is a listener conn, else return 0. */ int connection_is_listener(connection_t *conn) { if(conn->type == CONN_TYPE_OR_LISTENER || conn->type == CONN_TYPE_AP_LISTENER || @@ -908,6 +1008,9 @@ int connection_is_listener(connection_t *conn) { return 0; } +/** Return 1 if conn is in state 'open' and is not marked + * for close, else return 0. + */ int connection_state_is_open(connection_t *conn) { tor_assert(conn); @@ -922,6 +1025,11 @@ int connection_state_is_open(connection_t *conn) { return 0; } +/** Write a 'destroy' cell with circ ID circ_id onto OR connection + * conn. + * + * Return 0. + */ int connection_send_destroy(uint16_t circ_id, connection_t *conn) { cell_t cell; @@ -936,6 +1044,11 @@ int connection_send_destroy(uint16_t circ_id, connection_t *conn) { return 0; } +/** Process new bytes that have arrived on conn->inbuf. + * + * This function just passes conn to the connection-specific + * connection_*_process_inbuf() function. + */ int connection_process_inbuf(connection_t *conn) { tor_assert(conn); @@ -958,6 +1071,12 @@ int connection_process_inbuf(connection_t *conn) { } } +/** We just finished flushing bytes from conn->outbuf, and there + * are no more bytes remaining. + * + * This function just passes conn to the connection-specific + * connection_*_finished_flushing() function. + */ int connection_finished_flushing(connection_t *conn) { tor_assert(conn); @@ -982,6 +1101,9 @@ int connection_finished_flushing(connection_t *conn) { } } +/** Verify that connection conn has all of its invariants + * correct. Trigger an assert if anything is invalid. + */ void assert_connection_ok(connection_t *conn, time_t now) { tor_assert(conn);