diff options
author | Roger Dingledine <arma@torproject.org> | 2004-05-10 07:02:58 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2004-05-10 07:02:58 +0000 |
commit | d9fa234fd9b4922c70c023ad08e9854459117640 (patch) | |
tree | 2cd09003728109a021580e3f1292e931ac1b14ca | |
parent | 3bf2c572ad02b557c11fd760b45d0a1f7f087efa (diff) | |
download | tor-d9fa234fd9b4922c70c023ad08e9854459117640.tar.gz tor-d9fa234fd9b4922c70c023ad08e9854459117640.zip |
comments and doxygen markup on circuit.c
svn:r1837
-rw-r--r-- | src/or/circuit.c | 338 |
1 files changed, 265 insertions, 73 deletions
diff --git a/src/or/circuit.c b/src/or/circuit.c index 93b13a8521..85e88e0755 100644 --- a/src/or/circuit.c +++ b/src/or/circuit.c @@ -2,6 +2,12 @@ /* See LICENSE for licensing information */ /* $Id$ */ +/** + * \file circuit.c + * \brief Manage circuits and the global circuit list. Also handle + * relay cell encryption/decryption. + **/ + #include "or.h" extern or_options_t options; /* command-line and config-file options */ @@ -21,13 +27,22 @@ static void circuit_is_open(circuit_t *circ); static void circuit_build_failed(circuit_t *circ); static circuit_t *circuit_establish_circuit(uint8_t purpose, const char *exit_nickname); +/** Stats: how many relay cells have originated at this hop, or have + * been relayed onward (not recognized at this hop)? + */ unsigned long stats_n_relay_cells_relayed = 0; +/** Stats: how many relay cells have been delivered to streams at this + * hop? + */ unsigned long stats_n_relay_cells_delivered = 0; /********* START VARIABLES **********/ -static int circuitlist_len=0; +/** A global (within this file) list of all circuits at this hop. */ static circuit_t *global_circuitlist=NULL; +/** How many entries are in global_circuitlist? */ +static int circuitlist_len=0; +/** Array of strings to make circ-\>state human-readable */ char *circuit_state_to_string[] = { "doing handshakes", /* 0 */ "processing the onion", /* 1 */ @@ -37,7 +52,7 @@ char *circuit_state_to_string[] = { /********* END VARIABLES ************/ -/* add 'circ' to the global list of circuits. This is called only from +/** Add <b>circ</b> to the global list of circuits. This is called only from * within circuit_new. */ static void circuit_add(circuit_t *circ) { @@ -51,26 +66,9 @@ static void circuit_add(circuit_t *circ) { ++circuitlist_len; } -void circuit_remove(circuit_t *circ) { - circuit_t *tmpcirc; - - tor_assert(circ && global_circuitlist); - - if(global_circuitlist == circ) { - global_circuitlist = global_circuitlist->next; - --circuitlist_len; - return; - } - - for(tmpcirc = global_circuitlist;tmpcirc->next;tmpcirc = tmpcirc->next) { - if(tmpcirc->next == circ) { - tmpcirc->next = circ->next; - --circuitlist_len; - return; - } - } -} - +/** Detach from the global circuit list, and deallocate, all + * circuits that have been marked for close. + */ void circuit_close_all_marked() { circuit_t *tmp,*m; @@ -95,6 +93,9 @@ void circuit_close_all_marked() } } +/** Allocate space for a new circuit, initializing with <b>p_circ_id</b> + * and <b>p_conn</b>. Add it to the global circuit list. + */ circuit_t *circuit_new(uint16_t p_circ_id, connection_t *p_conn) { circuit_t *circ; @@ -122,6 +123,8 @@ circuit_t *circuit_new(uint16_t p_circ_id, connection_t *p_conn) { return circ; } +/** Deallocate space associated with circ. + */ void circuit_free(circuit_t *circ) { tor_assert(circ); tor_assert(circ->magic == CIRCUIT_MAGIC); @@ -148,6 +151,7 @@ void circuit_free(circuit_t *circ) { free(circ); } +/** Deallocate space associated with the linked list <b>cpath</b>. */ void circuit_free_cpath(crypt_path_t *cpath) { crypt_path_t *victim, *head=cpath; @@ -165,6 +169,7 @@ void circuit_free_cpath(crypt_path_t *cpath) { circuit_free_cpath_node(cpath); } +/** Deallocate space associated with the cpath node <b>victim</b>. */ static void circuit_free_cpath_node(crypt_path_t *victim) { if(victim->f_crypto) crypto_free_cipher_env(victim->f_crypto); @@ -179,7 +184,13 @@ static void circuit_free_cpath_node(crypt_path_t *victim) { free(victim); } -/* return 0 if can't get a unique circ_id. */ +/** Iterate over values of circ_id, starting from conn-\>next_circ_id, + * and with the high bit specified by circ_id_type (see + * decide_circ_id_type()), until we get a circ_id that is not in use + * by any other circuit on that conn. + * + * Return it, or 0 if can't get a unique circ_id. + */ static uint16_t get_unique_circ_id_by_conn(connection_t *conn, int circ_id_type) { uint16_t test_circ_id; int attempts=0; @@ -207,6 +218,12 @@ static uint16_t get_unique_circ_id_by_conn(connection_t *conn, int circ_id_type) return test_circ_id; } +/** Return a circ such that: + * - circ-\>n_circ_id or circ-\>p_circ_id is equal to <b>circ_id</b>, and + * - circ is attached to <b>conn</b>, either as p_conn, n-conn, or + * in p_streams or n_streams. + * Return NULL if no such circuit exists. + */ circuit_t *circuit_get_by_circ_id_conn(uint16_t circ_id, connection_t *conn) { circuit_t *circ; connection_t *tmpconn; @@ -239,6 +256,11 @@ circuit_t *circuit_get_by_circ_id_conn(uint16_t circ_id, connection_t *conn) { return NULL; } +/** Return a circ such that circ is attached to <b>conn</b>, either as + * p_conn, n-conn, or in p_streams or n_streams. + * + * Return NULL if no such circuit exists. + */ circuit_t *circuit_get_by_conn(connection_t *conn) { circuit_t *circ; connection_t *tmpconn; @@ -264,7 +286,8 @@ circuit_t *circuit_get_by_conn(connection_t *conn) { return NULL; } -/* Return 1 iff 'c' could be returned by circuit_get_best. +/* Return 1 if <b>circ</b> could be returned by circuit_get_best(). + * Else return 0. */ static int circuit_is_acceptable(circuit_t *circ, connection_t *conn, @@ -333,8 +356,8 @@ static int circuit_is_acceptable(circuit_t *circ, return 1; } -/* Return 1 iff circuit 'a' is better than circuit 'b' for purpose. Used by - * circuit_get_best +/* Return 1 if circuit <b>a</b> is better than circuit <b>b</b> for + * <b>purpose</b>, and return 0 otherwise. Used by circuit_get_best. */ static int circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose) { @@ -367,9 +390,10 @@ static int circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose) return 0; } -/* Find the best circ that conn can use, preferably one which is +/** Find the best circ that conn can use, preferably one which is * dirty. Circ must not be too old. - * conn must be defined. + * + * Conn must be defined. * * If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN. * @@ -407,6 +431,12 @@ circuit_t *circuit_get_best(connection_t *conn, return best; } +/** Return a circ such that: + * - circ-\>rend_query is equal to <b>rend_query</b>, and + * - circ-\>purpose is equal to <b>purpose</b>. + * + * Return NULL if no such circuit exists. + */ circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query, uint8_t purpose) { circuit_t *circ; @@ -419,9 +449,9 @@ circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query, uint8_t return NULL; } -/* Return the first circuit in global_circuitlist after 'start' whose - * rend_pk_digest field is 'digest' and whose purpose is purpose. Returns - * NULL if no circuit is found. If 'start' is null, begin at the start of +/** Return the first circuit in global_circuitlist after <b>start</b> whose + * rend_pk_digest field is <b>digest</b> and whose purpose is <b>purpose</b>. Returns + * NULL if no circuit is found. If <b>start</b> is NULL, begin at the start of * the list. */ circuit_t *circuit_get_next_by_pk_and_purpose(circuit_t *start, @@ -444,7 +474,7 @@ circuit_t *circuit_get_next_by_pk_and_purpose(circuit_t *start, return NULL; } -/* Return the circuit waiting for a rendezvous with the provided cookie. +/** Return the circuit waiting for a rendezvous with the provided cookie. * Return NULL if no such circuit is found. */ circuit_t *circuit_get_rendezvous(const char *cookie) @@ -459,14 +489,15 @@ circuit_t *circuit_get_rendezvous(const char *cookie) return NULL; } -#define MIN_SECONDS_BEFORE_EXPIRING_CIRC 30 -/* circuits that were born at the end of their second might be expired +/** Circuits that were born at the end of their second might be expired * after 30.1 seconds; circuits born at the beginning might be expired * after closer to 31 seconds. */ +#define MIN_SECONDS_BEFORE_EXPIRING_CIRC 30 -/* close all circuits that start at us, aren't open, and were born - * at least MIN_SECONDS_BEFORE_EXPIRING_CIRC seconds ago */ +/** Close all circuits that start at us, aren't open, and were born + * at least MIN_SECONDS_BEFORE_EXPIRING_CIRC seconds ago. + */ void circuit_expire_building(time_t now) { circuit_t *victim, *circ = global_circuitlist; @@ -531,7 +562,8 @@ void circuit_expire_building(time_t now) { } } -/* count the number of circs starting at us that aren't open */ +/** Count the number of circs originating here that aren't open, and + * that have the specified <b>purpose</b>. */ int circuit_count_building(uint8_t purpose) { circuit_t *circ; int num=0; @@ -546,8 +578,12 @@ int circuit_count_building(uint8_t purpose) { return num; } +/** How many circuits do we want simultaneously in-progress to handle + * a given stream? + */ #define MIN_CIRCUITS_HANDLING_STREAM 2 -/* return 1 if at least MIN_CIRCUITS_HANDLING_STREAM non-open + +/** Return 1 if at least MIN_CIRCUITS_HANDLING_STREAM non-open * general-purpose circuits will have an acceptable exit node for * conn. Else return 0. */ @@ -571,6 +607,10 @@ int circuit_stream_is_being_handled(connection_t *conn) { return 0; } +/** Return the circuit that is open, has specified <b>purpose</b>, + * has a timestamp_dirty value of 0, and was created most recently, + * or NULL if no circuit fits this description. + */ static circuit_t * circuit_get_youngest_clean_open(uint8_t purpose) { circuit_t *circ; @@ -586,10 +626,10 @@ circuit_get_youngest_clean_open(uint8_t purpose) { return youngest; } -/* Build a new test circuit every 5 minutes */ +/** Build a new test circuit every 5 minutes */ #define TESTING_CIRCUIT_INTERVAL 300 -/* this function is called once a second. its job is to make sure +/** This function is called once a second. Its job is to make sure * all services we offer have enough circuits available. Some * services just want enough circuits for current tasks, whereas * others want a minimum set of idle circuits hanging around. @@ -620,6 +660,10 @@ void circuit_build_needed_circs(time_t now) { } } +/** How many simultaneous in-progress general-purpose circuits do we + * want to be building at once, if there are no open general-purpose + * circuits? + */ #define CIRCUIT_MIN_BUILDING_GENERAL 3 /* if there's no open circ, and less than 3 are on the way, * go ahead and try another. */ @@ -631,7 +675,9 @@ void circuit_build_needed_circs(time_t now) { /* XXX count idle rendezvous circs and build more */ } -/* update digest from the payload of cell. assign integrity part to cell. */ +/** Update digest from the payload of cell. Assign integrity part to + * cell. + */ static void relay_set_digest(crypto_digest_env_t *digest, cell_t *cell) { char integrity[4]; relay_header_t rh; @@ -645,8 +691,10 @@ static void relay_set_digest(crypto_digest_env_t *digest, cell_t *cell) { relay_header_pack(cell->payload, &rh); } -/* update digest from the payload of cell (with the integrity part set - * to 0). If the integrity part is valid return 1, else restore digest +/** Does the digest for this circuit indicate that this cell is for us? + * + * Update digest from the payload of cell (with the integrity part set + * to 0). If the integrity part is valid, return 1, else restore digest * and cell to their original state and return 0. */ static int relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell) { @@ -683,6 +731,13 @@ static int relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell) { return 1; } +/** Apply <b>cipher</b> to CELL_PAYLOAD_SIZE bytes of <b>in</b> + * (in place). + * + * If <b>encrypt_mode</b> is 1 then encrypt, else decrypt. + * + * Return -1 if the crypto fails, else return 0. + */ static int relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in, int encrypt_mode) { char out[CELL_PAYLOAD_SIZE]; /* 'in' must be this size too */ @@ -701,13 +756,15 @@ static int relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in, return 0; } -/* -receive a relay cell: - - crypt it (encrypt APward, decrypt at AP, decrypt exitward) - - check if recognized (if exitward) - - if recognized, check digest, find right conn, deliver to edge. - - else connection_or_write_cell_to_buf to the right conn -*/ +/** Receive a relay cell: + * - Crypt it (encrypt APward, decrypt at AP, decrypt exitward). + * - Check if recognized (if exitward). + * - If recognized and the digest checks out, then find if there's + * a conn that the cell is intended for, and deliver it to + * connection_edge. + * - Else connection_or_write_cell_to_buf to the conn on the other + * side of the circuit. + */ int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction) { connection_t *conn=NULL; @@ -776,6 +833,23 @@ int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, return 0; } +/** Do the appropriate en/decryptions for <b>cell</b> arriving on + * <b>circ</b> in direction <b>cell_direction</b>. + * + * If cell_direction == CELL_DIRECTION_IN: + * - If we're at the origin (we're the OP), for hops 1..N, + * decrypt cell. If recognized, stop. + * - Else (we're not the OP), encrypt one hop. Cell is not recognized. + * + * If cell_direction == CELL_DIRECTION_OUT: + * - decrypt one hop. Check if recognized. + * + * If cell is recognized, set *recognized to 1, and set + * *layer_hint to the hop that recognized it. + * + * Return -1 to indicate that we should mark the circuit for close, + * else return 0. + */ /* wrap this into receive_relay_cell one day */ static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction, crypt_path_t **layer_hint, char *recognized) { @@ -786,8 +860,8 @@ static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction, tor_assert(cell_direction == CELL_DIRECTION_IN || cell_direction == CELL_DIRECTION_OUT); if(cell_direction == CELL_DIRECTION_IN) { - if(CIRCUIT_IS_ORIGIN(circ)) { /* we're at the beginning of the circuit. - We'll want to do layered crypts. */ + if(CIRCUIT_IS_ORIGIN(circ)) { /* We're at the beginning of the circuit. + We'll want to do layered decrypts. */ tor_assert(circ->cpath); thishop = circ->cpath; if(thishop->state != CPATH_STATE_OPEN) { @@ -837,11 +911,10 @@ static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction, return 0; } -/* -package a relay cell: - 1) encrypt it to the right conn - 2) connection_or_write_cell_to_buf to the right conn -*/ +/** Package a relay cell: + * - Encrypt it to the right layer + * - connection_or_write_cell_to_buf to the right conn + */ int circuit_package_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction, @@ -886,6 +959,9 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ, return 0; } +/** If cell's stream_id matches the stream_id of any conn that's + * attached to circ, return that conn, else return NULL. + */ static connection_t * relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction) { @@ -924,6 +1000,11 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction) return NULL; /* probably a begin relay cell */ } +/** The circuit <b>circ</b> has received a circuit-level sendme + * (on hop <b>layer_hint</b>, if we're the OP). Go through all the + * attached streams and let them resume reading and packaging, if + * their stream windows allow it. + */ void circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint) { log_fn(LOG_DEBUG,"resuming"); @@ -933,6 +1014,10 @@ void circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint) { circuit_resume_edge_reading_helper(circ->p_streams, circ, layer_hint); } +/** A helper function for circuit_resume_edge_reading() above. + * The arguments are the same, except that <b>conn</b> is the head + * of a linked list of edge streams that should each be considered. + */ static int circuit_resume_edge_reading_helper(connection_t *conn, circuit_t *circ, @@ -955,8 +1040,12 @@ circuit_resume_edge_reading_helper(connection_t *conn, return 0; } -/* returns -1 if the window is empty, else 0. - * If it's empty, tell edge conns to stop reading. */ +/** Check if the package window for <b>circ</b> is empty (at + * hop <b>layer_hint</b> if it's defined). + * + * If yes, tell edge streams to stop reading and return -1. + * Else return 0. + */ int circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint) { connection_t *conn = NULL; @@ -979,6 +1068,12 @@ int circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint return 0; } +/** Check if the deliver_window for circuit <b>circ</b> (at hop + * <b>layer_hint</b> if it's defined) is low enough that we should + * send a circuit-level sendme back down the circuit. If so, send + * enough sendmes that the window would be overfull if we sent any + * more. + */ void circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint) { // log_fn(LOG_INFO,"Considering: layer_hint is %s", // layer_hint ? "defined" : "null"); @@ -997,6 +1092,21 @@ void circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint) } } +/** Mark <b>circ</b> to be closed next time we call + * circuit_close_all_marked(). Do any cleanup needed: + * - If state is onionskin_pending, remove circ from the onion_pending + * list. + * - If circ isn't open yet, call circuit_build_failed() if we're + * the origin, and in case call circuit_rep_hist_note_result() + * to note stats. + * - If purpose is C_INTRODUCE_ACK_WAIT, remove the intro point we + * just tried from our list of intro points for that service + * descriptor. + * - Send appropriate destroys and edge_destroys for conns and + * streams attached to circ. + * - If circ->rend_splice is set (we are the midpoint of a joined + * rendezvous stream), then mark the other circuit to close as well. + */ int _circuit_mark_for_close(circuit_t *circ) { connection_t *conn; @@ -1049,6 +1159,9 @@ int _circuit_mark_for_close(circuit_t *circ) { return 0; } +/** If the stream <b>conn</b> is a member of any of the linked + * lists of <b>circ</b>, then remove it from the list. + */ void circuit_detach_stream(circuit_t *circ, connection_t *conn) { connection_t *prevconn; @@ -1098,8 +1211,16 @@ void circuit_detach_stream(circuit_t *circ, connection_t *conn) { tor_assert(0); /* should never get here */ } +/** Notify the global circuit list that <b>conn</b> is about to be + * removed and then freed. + * + * If it's an OR conn, then mark-for-close all the circuits that use + * that conn. + * + * If it's an edge conn, then detach it from its circ, so we don't + * try to reference it later. + */ void circuit_about_to_close_connection(connection_t *conn) { - /* send destroys for all circuits using conn */ /* currently, we assume it's too late to flush conn's buf here. * down the road, maybe we'll consider that eof doesn't mean can't-write */ @@ -1138,6 +1259,10 @@ void circuit_about_to_close_connection(connection_t *conn) { } /* end switch */ } +/** Log, at severity <b>severity</b>, the nicknames of each router in + * circ's cpath. Also log the length of the cpath, and the intended + * exit point. + */ void circuit_log_path(int severity, circuit_t *circ) { char buf[1024]; char *s = buf; @@ -1167,7 +1292,7 @@ void circuit_log_path(int severity, circuit_t *circ) { log_fn(severity,"%s",buf); } -/* Tell the rep(utation)hist(ory) module about the status of the links +/** Tell the rep(utation)hist(ory) module about the status of the links * in circ. Hops that have become OPEN are marked as successfully * extended; the _first_ hop that isn't open (if any) is marked as * unable to extend. @@ -1209,6 +1334,9 @@ circuit_rep_hist_note_result(circuit_t *circ) } while (hop!=circ->cpath); } +/** A helper function for circuit_dump_by_conn() below. Log a bunch + * of information about circuit <b>circ</b>. + */ static void circuit_dump_details(int severity, circuit_t *circ, int poll_index, char *type, int this_circid, int other_circid) { @@ -1227,6 +1355,9 @@ circuit_dump_details(int severity, circuit_t *circ, int poll_index, } } +/** Log, at severity <b>severity</b>, information about each circuit + * that is connected to <b>conn</b>. + */ void circuit_dump_by_conn(connection_t *conn, int severity) { circuit_t *circ; connection_t *tmpconn; @@ -1253,9 +1384,15 @@ void circuit_dump_by_conn(connection_t *conn, int severity) { } } -/* Don't keep more than 10 unused open circuits around. */ +/** Don't keep more than 10 unused open circuits around. */ #define MAX_UNUSED_OPEN_CIRCUITS 10 +/** Find each circuit that has been dirty for too long, and has + * no streams on it: mark it for close. + * + * Also, if there are more than MAX_UNUSED_OPEN_CIRCUITS open and + * unused circuits, then mark the excess circs for close. + */ void circuit_expire_old_circuits(void) { circuit_t *circ; time_t now = time(NULL); @@ -1300,6 +1437,12 @@ void circuit_expire_old_circuits(void) { smartlist_free(unused_open_circs); } +/** The circuit <b>circ</b> has just become open. Take the next + * step: for rendezvous circuits, we pass circ to the appropriate + * function in rendclient or rendservice. For general circuits, we + * call connection_ap_attach_pending, which looks for pending streams + * that could use circ. + */ static void circuit_is_open(circuit_t *circ) { switch(circ->purpose) { @@ -1328,7 +1471,7 @@ static void circuit_is_open(circuit_t *circ) { } } -/* Called whenever a circuit could not be successfully built. +/*~ Called whenever a circuit could not be successfully built. */ static void circuit_build_failed(circuit_t *circ) { @@ -1395,16 +1538,16 @@ static void circuit_build_failed(circuit_t *circ) { } } -/* Number of consecutive failures so far; should only be touched by +/** Number of consecutive failures so far; should only be touched by * circuit_launch_new and circuit_*_failure_count. */ static int n_circuit_failures = 0; -/* Don't retry launching a new circuit if we try this many times with no +/** Don't retry launching a new circuit if we try this many times with no * success. */ #define MAX_CIRCUIT_FAILURES 5 -/* Launch a new circuit and return a pointer to it. Return NULL if you failed. */ +/** Launch a new circuit and return a pointer to it. Return NULL if you failed. */ circuit_t *circuit_launch_new(uint8_t purpose, const char *exit_nickname) { if (n_circuit_failures > MAX_CIRCUIT_FAILURES) { @@ -1417,15 +1560,29 @@ circuit_t *circuit_launch_new(uint8_t purpose, const char *exit_nickname) { return circuit_establish_circuit(purpose, exit_nickname); } +/** Record another failure at opening a general circuit. When we have + * too many, we'll stop trying for the remainder of this minute. + */ void circuit_increment_failure_count(void) { ++n_circuit_failures; log_fn(LOG_DEBUG,"n_circuit_failures now %d.",n_circuit_failures); } +/** Reset the failure count for opening general circuits. This means + * we will try MAX_CIRCUIT_FAILURES times more (if necessary) before + * stopping again. + */ void circuit_reset_failure_count(void) { n_circuit_failures = 0; } +/** Build a new circuit for <b>purpose</b>. If <b>exit_nickname</b> + * is defined, then use that as your exit router, else choose a suitable + * exit node. + * + * Also launch a connection to the first OR in the chosen path, if + * it's not open already. + */ static circuit_t *circuit_establish_circuit(uint8_t purpose, const char *exit_nickname) { routerinfo_t *firsthop; @@ -1487,7 +1644,9 @@ static circuit_t *circuit_establish_circuit(uint8_t purpose, return circ; } -/* find circuits that are waiting on me, if any, and get them to send the onion */ +/** Find circuits that are waiting on <b>or_conn</b> to become open, + * if any, and get them to send their create cells forward. + */ void circuit_n_conn_open(connection_t *or_conn) { circuit_t *circ; @@ -1510,6 +1669,16 @@ void circuit_n_conn_open(connection_t *or_conn) { extern int has_completed_circuit; +/** This is the backbone function for building circuits. + * + * If circ's first hop is closed, then we need to build a create + * cell and send it forward. + * + * Otherwise, we need to build a relay extend cell and send it + * forward. + * + * Return -1 if we want to tear down circ, else return 0. + */ int circuit_send_next_onion_skin(circuit_t *circ) { cell_t cell; crypt_path_t *hop; @@ -1593,7 +1762,7 @@ int circuit_send_next_onion_skin(circuit_t *circ) { return 0; } -/* take the 'extend' cell, pull out addr/port plus the onion skin. Make +/** Take the 'extend' cell, pull out addr/port plus the onion skin. Make * sure we're connected to the next hop, and pass it the onion skin in * a create cell. */ @@ -1657,13 +1826,13 @@ int circuit_extend(cell_t *cell, circuit_t *circ) { return 0; } -/* Initialize cpath->{f|b}_{crypto|digest} from the key material in +/** Initialize cpath-\>{f|b}_{crypto|digest} from the key material in * key_data. key_data must contain CPATH_KEY_MATERIAL bytes, which are * used as follows: - * 20 to initialize f_digest - * 20 to initialize b_digest - * 16 to key f_crypto - * 16 to key b_crypto + * - 20 to initialize f_digest + * - 20 to initialize b_digest + * - 16 to key f_crypto + * - 16 to key b_crypto * * (If 'reverse' is true, then f_XX and b_XX are swapped.) */ @@ -1708,6 +1877,14 @@ int circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data, int reverse) return 0; } +/** A created or extended cell came back to us on the circuit, + * and it included <b>reply</b> (the second DH key, plus KH). + * + * Calculate the appropriate keys and digests, make sure KH is + * correct, and initialize this hop of the cpath. + * + * Return -1 if we want to mark circ for close, else return 0. + */ int circuit_finish_handshake(circuit_t *circ, char *reply) { unsigned char keys[CPATH_KEY_MATERIAL_LEN]; crypt_path_t *hop; @@ -1747,6 +1924,12 @@ int circuit_finish_handshake(circuit_t *circ, char *reply) { return 0; } +/** We received a relay truncated cell on circ. + * + * Since we don't ask for truncates currently, getting a truncated + * means that a connection broke or an extend failed. For now, + * just give up: for circ to close, and return 0. + */ int circuit_truncated(circuit_t *circ, crypt_path_t *layer) { crypt_path_t *victim; connection_t *stream; @@ -1784,6 +1967,9 @@ int circuit_truncated(circuit_t *circ, crypt_path_t *layer) { return 0; } +/** Verify that cpath layer <b>cp</b> has all of its invariants + * correct. Trigger an assert if anything is invalid. + */ void assert_cpath_layer_ok(const crypt_path_t *cp) { tor_assert(cp->f_crypto); @@ -1806,6 +1992,9 @@ void assert_cpath_layer_ok(const crypt_path_t *cp) tor_assert(cp->deliver_window >= 0); } +/** Verify that cpath <b>cp</b> has all of its invariants + * correct. Trigger an assert if anything is invalid. + */ void assert_cpath_ok(const crypt_path_t *cp) { while(cp->prev) @@ -1826,6 +2015,9 @@ void assert_cpath_ok(const crypt_path_t *cp) } } +/** Verify that circuit <b>c</b> has all of its invariants + * correct. Trigger an assert if anything is invalid. + */ void assert_circuit_ok(const circuit_t *c) { connection_t *conn; |