Loading doc/TODO +2 −2 Changes for doc/TODO: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -30,8 +30,8 @@ Things we'd like to do in 0.2.0.x: act-on-netinfo logic separate so it can get called _after_ negotiation. - Variable-length cells - Add structure - Add parse logic o Add structure o Add parse logic - Make CERT and VERSIONS variable. - CERT cells - functions to parse x509 certs Loading src/or/buffers.c +36 −0 Changes for src/or/buffers.c: 36 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -993,6 +993,42 @@ fetch_from_buf(char *string, size_t string_len, buf_t *buf) return buf->datalen; } /** DOCDOC Returns 0 on "not a var-length cell."; 1 whether it's all here * yet or not. */ int fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out) { char hdr[VAR_CELL_HEADER_SIZE]; var_cell_t *result; uint8_t command; uint16_t length; check(); *out = NULL; if (buf->datalen < VAR_CELL_HEADER_SIZE) return 0; peek_from_buf(hdr, sizeof(hdr), buf); command = *(uint8_t*)(hdr+2); if (!(CELL_COMMAND_IS_VAR_LENGTH(command))) return 0; length = ntohs(get_uint16(hdr+3)); if (buf->datalen < (size_t)(VAR_CELL_HEADER_SIZE+length)) return 1; result = tor_malloc(sizeof(var_cell_t)+length-1); result->command = command; result->payload_len = length; result->circ_id = ntohs(*(uint16_t*)hdr); buf_remove_from_front(buf, VAR_CELL_HEADER_SIZE); peek_from_buf(result->payload, length, buf); buf_remove_from_front(buf, length); check(); *out = result; return 1; } /** Move up to *<b>buf_flushlen</b> bytes from <b>buf_in</b> to * <b>buf_out</b>, and modify *<b>buf_flushlen</b> appropriately. * Return the number of bytes actually copied. Loading src/or/command.c +56 −8 Changes for src/or/command.c: 56 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -35,9 +35,10 @@ static void command_process_create_cell(cell_t *cell, or_connection_t *conn); static void command_process_created_cell(cell_t *cell, or_connection_t *conn); static void command_process_relay_cell(cell_t *cell, or_connection_t *conn); static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn); static void command_process_versions_cell(cell_t *cell, or_connection_t *conn); static void command_process_versions_cell(var_cell_t *cell, or_connection_t *conn); static void command_process_netinfo_cell(cell_t *cell, or_connection_t *conn); static void command_process_cert_cell(cell_t *cell, or_connection_t *conn); static void command_process_cert_cell(var_cell_t *cell, or_connection_t *conn); static void command_process_link_auth_cell(cell_t *cell,or_connection_t *conn); #ifdef KEEP_TIMING_STATS Loading Loading @@ -143,16 +144,14 @@ command_process_cell(cell_t *cell, or_connection_t *conn) PROCESS_CELL(destroy, cell, conn); break; case CELL_VERSIONS: ++stats_n_versions_cells_processed; PROCESS_CELL(versions, cell, conn); tor_fragile_assert(); break; case CELL_NETINFO: ++stats_n_netinfo_cells_processed; PROCESS_CELL(netinfo, cell, conn); break; case CELL_CERT: ++stats_n_cert_cells_processed; PROCESS_CELL(cert, cell, conn); tor_fragile_assert(); break; case CELL_LINK_AUTH: ++stats_n_link_auth_cells_processed; Loading @@ -165,6 +164,55 @@ command_process_cell(cell_t *cell, or_connection_t *conn) } } /** Process a <b>cell</b> that was just received on <b>conn</b>. Keep internal * statistics about how many of each cell we've processed so far * this second, and the total number of microseconds it took to * process each type of cell. */ void command_process_var_cell(var_cell_t *cell, or_connection_t *conn) { #ifdef KEEP_TIMING_STATS /* how many of each cell have we seen so far this second? needs better * name. */ static int num_versions=0, num_cert=0; time_t now = time(NULL); if (now > current_second) { /* the second has rolled over */ /* print stats */ log_info(LD_OR, "At end of second: %d versions (%d ms), %d cert (%d ms)", num_versions, versions_time/1000, cert, cert_time/1000); num_versions = num_cert = 0; versions_time = cert_time = 0; /* remember which second it is, for next time */ current_second = now; } #endif /*XXXX020 reject all when not handshaking. */ switch (cell->command) { case CELL_VERSIONS: ++stats_n_versions_cells_processed; PROCESS_CELL(versions, cell, conn); break; case CELL_CERT: ++stats_n_cert_cells_processed; PROCESS_CELL(cert, cell, conn); break; default: log_warn(LD_BUG, "Variable-length cell of unknown type (%d) received.", cell->command); tor_fragile_assert(); break; } } /** Process a 'create' <b>cell</b> that just arrived from <b>conn</b>. Make a * new circuit with the p_circ_id specified in cell. Put the circuit in state * onionskin_pending, and pass the onionskin to the cpuworker. Circ will get Loading Loading @@ -404,7 +452,7 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn) /** Process a 'versions' cell. The current link protocol version must be 0 * to indicate that no version has yet been negotiated. DOCDOC say more. */ static void command_process_versions_cell(cell_t *cell, or_connection_t *conn) command_process_versions_cell(var_cell_t *cell, or_connection_t *conn) { uint16_t versionslen; int highest_supported_version = 0; Loading Loading @@ -560,7 +608,7 @@ connection_or_act_on_netinfo(or_connection_t *conn) } static void command_process_cert_cell(cell_t *cell, or_connection_t *conn) command_process_cert_cell(var_cell_t *cell, or_connection_t *conn) { (void) cell; (void) conn; Loading src/or/connection_or.c +35 −5 Changes for src/or/connection_or.c: 35 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -147,6 +147,22 @@ cell_unpack(cell_t *dest, const char *src) memcpy(dest->payload, src+3, CELL_PAYLOAD_SIZE); } /** DOCDOC */ void var_cell_pack_header(var_cell_t *cell, char *hdr_out) { *(uint16_t*)(hdr_out) = htons(cell->circ_id); *(uint8_t*)(hdr_out+2) = cell->command; set_uint16(hdr_out+3, htons(cell->payload_len)); } /** DOCDOC */ void var_cell_free(var_cell_t *cell) { tor_free(cell); } int connection_or_reached_eof(or_connection_t *conn) { Loading Loading @@ -825,6 +841,13 @@ connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn) connection_write_to_buf(networkcell.body, CELL_NETWORK_SIZE, TO_CONN(conn)); } /** DOCDOC */ static int connection_fetch_var_cell_from_buf(or_connection_t *conn, var_cell_t **out) { return fetch_var_cell_from_buf(conn->_base.inbuf, out); } /** Process cells from <b>conn</b>'s inbuf. * * Loop: while inbuf contains a cell, pull it off the inbuf, unpack it, Loading @@ -835,14 +858,21 @@ connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn) static int connection_or_process_cells_from_inbuf(or_connection_t *conn) { char buf[CELL_NETWORK_SIZE]; cell_t cell; var_cell_t *var_cell; loop: while (1) { log_debug(LD_OR, "%d: starting, inbuf_datalen %d (%d pending in tls object).", conn->_base.s,(int)buf_datalen(conn->_base.inbuf), tor_tls_get_pending_bytes(conn->tls)); if (connection_fetch_var_cell_from_buf(conn, &var_cell)) { if (!var_cell) return 0; /* not yet. */ command_process_var_cell(var_cell, conn); var_cell_free(var_cell); } else { char buf[CELL_NETWORK_SIZE]; cell_t cell; if (buf_datalen(conn->_base.inbuf) < CELL_NETWORK_SIZE) /* whole response available? */ return 0; /* not yet */ Loading @@ -854,8 +884,8 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn) cell_unpack(&cell, buf); command_process_cell(&cell, conn); goto loop; /* process the remainder of the buffer */ } } } /** Write a destroy cell with circ ID <b>circ_id</b> and reason <b>reason</b> Loading src/or/or.h +23 −8 Changes for src/or/or.h: 23 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -660,6 +660,9 @@ typedef enum { #define CELL_CERT 9 #define CELL_LINK_AUTH 10 #define CELL_COMMAND_IS_VAR_LENGTH(x) \ ((x) == CELL_CERT || (x) == CELL_VERSIONS) /** How long to test reachability before complaining to the user. */ #define TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT (20*60) Loading Loading @@ -701,28 +704,36 @@ typedef enum { /** Number of bytes in a cell transmitted over the network. */ #define CELL_NETWORK_SIZE 512 #define VAR_CELL_HEADER_SIZE 5 /** Number of bytes in a relay cell's header (not including general cell * header). */ #define RELAY_HEADER_SIZE (1+2+2+4+2) /** Largest number of bytes that can fit in a relay cell payload. */ #define RELAY_PAYLOAD_SIZE (CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE) typedef struct cell_t cell_t; /** Parsed onion routing cell. All communication between nodes * is via cells. */ struct cell_t { typedef struct cell_t { uint16_t circ_id; /**< Circuit which received the cell. */ uint8_t command; /**< Type of the cell: one of PADDING, CREATE, RELAY, * or DESTROY. */ uint8_t command; /**< Type of the cell: one of CELL_PADDING, CELL_CREATE, * CELL_DESTROY, etc */ char payload[CELL_PAYLOAD_SIZE]; /**< Cell body. */ }; } cell_t; /** Parsed variable-length onion routing cell. */ typedef struct var_cell_t { uint8_t command; uint16_t circ_id; uint16_t payload_len; char payload[1]; } var_cell_t; typedef struct packed_cell_t packed_cell_t; /** A cell as packed for writing to the network. */ struct packed_cell_t { typedef struct packed_cell_t { struct packed_cell_t *next; /**< Next cell queued on this circuit. */ char body[CELL_NETWORK_SIZE]; /**< Cell as packed for network. */ }; } packed_cell_t; /** A queue of cells on a circuit, waiting to be added to the * or_connection_t's outbuf. */ Loading Loading @@ -2387,6 +2398,7 @@ int write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state, const char *data, size_t data_len, int done); int move_buf_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen); int fetch_from_buf(char *string, size_t string_len, buf_t *buf); int fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out); int fetch_from_buf_http(buf_t *buf, char **headers_out, size_t max_headerlen, char **body_out, size_t *body_used, size_t max_bodylen, Loading Loading @@ -2546,6 +2558,7 @@ int connection_ap_handshake_attach_circuit(edge_connection_t *conn); /********************************* command.c ***************************/ void command_process_cell(cell_t *cell, or_connection_t *conn); void command_process_var_cell(var_cell_t *cell, or_connection_t *conn); void connection_or_act_on_netinfo(or_connection_t *conn); extern uint64_t stats_n_padding_cells_processed; Loading Loading @@ -2786,6 +2799,8 @@ int connection_or_compute_link_auth_hmac(or_connection_t *conn, char *hmac_out); void cell_pack(packed_cell_t *dest, const cell_t *src); void var_cell_pack_header(var_cell_t *cell, char *hdr_out); void var_cell_free(var_cell_t *cell); /********************************* control.c ***************************/ Loading Loading
doc/TODO +2 −2 Changes for doc/TODO: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -30,8 +30,8 @@ Things we'd like to do in 0.2.0.x: act-on-netinfo logic separate so it can get called _after_ negotiation. - Variable-length cells - Add structure - Add parse logic o Add structure o Add parse logic - Make CERT and VERSIONS variable. - CERT cells - functions to parse x509 certs Loading
src/or/buffers.c +36 −0 Changes for src/or/buffers.c: 36 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -993,6 +993,42 @@ fetch_from_buf(char *string, size_t string_len, buf_t *buf) return buf->datalen; } /** DOCDOC Returns 0 on "not a var-length cell."; 1 whether it's all here * yet or not. */ int fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out) { char hdr[VAR_CELL_HEADER_SIZE]; var_cell_t *result; uint8_t command; uint16_t length; check(); *out = NULL; if (buf->datalen < VAR_CELL_HEADER_SIZE) return 0; peek_from_buf(hdr, sizeof(hdr), buf); command = *(uint8_t*)(hdr+2); if (!(CELL_COMMAND_IS_VAR_LENGTH(command))) return 0; length = ntohs(get_uint16(hdr+3)); if (buf->datalen < (size_t)(VAR_CELL_HEADER_SIZE+length)) return 1; result = tor_malloc(sizeof(var_cell_t)+length-1); result->command = command; result->payload_len = length; result->circ_id = ntohs(*(uint16_t*)hdr); buf_remove_from_front(buf, VAR_CELL_HEADER_SIZE); peek_from_buf(result->payload, length, buf); buf_remove_from_front(buf, length); check(); *out = result; return 1; } /** Move up to *<b>buf_flushlen</b> bytes from <b>buf_in</b> to * <b>buf_out</b>, and modify *<b>buf_flushlen</b> appropriately. * Return the number of bytes actually copied. Loading
src/or/command.c +56 −8 Changes for src/or/command.c: 56 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -35,9 +35,10 @@ static void command_process_create_cell(cell_t *cell, or_connection_t *conn); static void command_process_created_cell(cell_t *cell, or_connection_t *conn); static void command_process_relay_cell(cell_t *cell, or_connection_t *conn); static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn); static void command_process_versions_cell(cell_t *cell, or_connection_t *conn); static void command_process_versions_cell(var_cell_t *cell, or_connection_t *conn); static void command_process_netinfo_cell(cell_t *cell, or_connection_t *conn); static void command_process_cert_cell(cell_t *cell, or_connection_t *conn); static void command_process_cert_cell(var_cell_t *cell, or_connection_t *conn); static void command_process_link_auth_cell(cell_t *cell,or_connection_t *conn); #ifdef KEEP_TIMING_STATS Loading Loading @@ -143,16 +144,14 @@ command_process_cell(cell_t *cell, or_connection_t *conn) PROCESS_CELL(destroy, cell, conn); break; case CELL_VERSIONS: ++stats_n_versions_cells_processed; PROCESS_CELL(versions, cell, conn); tor_fragile_assert(); break; case CELL_NETINFO: ++stats_n_netinfo_cells_processed; PROCESS_CELL(netinfo, cell, conn); break; case CELL_CERT: ++stats_n_cert_cells_processed; PROCESS_CELL(cert, cell, conn); tor_fragile_assert(); break; case CELL_LINK_AUTH: ++stats_n_link_auth_cells_processed; Loading @@ -165,6 +164,55 @@ command_process_cell(cell_t *cell, or_connection_t *conn) } } /** Process a <b>cell</b> that was just received on <b>conn</b>. Keep internal * statistics about how many of each cell we've processed so far * this second, and the total number of microseconds it took to * process each type of cell. */ void command_process_var_cell(var_cell_t *cell, or_connection_t *conn) { #ifdef KEEP_TIMING_STATS /* how many of each cell have we seen so far this second? needs better * name. */ static int num_versions=0, num_cert=0; time_t now = time(NULL); if (now > current_second) { /* the second has rolled over */ /* print stats */ log_info(LD_OR, "At end of second: %d versions (%d ms), %d cert (%d ms)", num_versions, versions_time/1000, cert, cert_time/1000); num_versions = num_cert = 0; versions_time = cert_time = 0; /* remember which second it is, for next time */ current_second = now; } #endif /*XXXX020 reject all when not handshaking. */ switch (cell->command) { case CELL_VERSIONS: ++stats_n_versions_cells_processed; PROCESS_CELL(versions, cell, conn); break; case CELL_CERT: ++stats_n_cert_cells_processed; PROCESS_CELL(cert, cell, conn); break; default: log_warn(LD_BUG, "Variable-length cell of unknown type (%d) received.", cell->command); tor_fragile_assert(); break; } } /** Process a 'create' <b>cell</b> that just arrived from <b>conn</b>. Make a * new circuit with the p_circ_id specified in cell. Put the circuit in state * onionskin_pending, and pass the onionskin to the cpuworker. Circ will get Loading Loading @@ -404,7 +452,7 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn) /** Process a 'versions' cell. The current link protocol version must be 0 * to indicate that no version has yet been negotiated. DOCDOC say more. */ static void command_process_versions_cell(cell_t *cell, or_connection_t *conn) command_process_versions_cell(var_cell_t *cell, or_connection_t *conn) { uint16_t versionslen; int highest_supported_version = 0; Loading Loading @@ -560,7 +608,7 @@ connection_or_act_on_netinfo(or_connection_t *conn) } static void command_process_cert_cell(cell_t *cell, or_connection_t *conn) command_process_cert_cell(var_cell_t *cell, or_connection_t *conn) { (void) cell; (void) conn; Loading
src/or/connection_or.c +35 −5 Changes for src/or/connection_or.c: 35 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -147,6 +147,22 @@ cell_unpack(cell_t *dest, const char *src) memcpy(dest->payload, src+3, CELL_PAYLOAD_SIZE); } /** DOCDOC */ void var_cell_pack_header(var_cell_t *cell, char *hdr_out) { *(uint16_t*)(hdr_out) = htons(cell->circ_id); *(uint8_t*)(hdr_out+2) = cell->command; set_uint16(hdr_out+3, htons(cell->payload_len)); } /** DOCDOC */ void var_cell_free(var_cell_t *cell) { tor_free(cell); } int connection_or_reached_eof(or_connection_t *conn) { Loading Loading @@ -825,6 +841,13 @@ connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn) connection_write_to_buf(networkcell.body, CELL_NETWORK_SIZE, TO_CONN(conn)); } /** DOCDOC */ static int connection_fetch_var_cell_from_buf(or_connection_t *conn, var_cell_t **out) { return fetch_var_cell_from_buf(conn->_base.inbuf, out); } /** Process cells from <b>conn</b>'s inbuf. * * Loop: while inbuf contains a cell, pull it off the inbuf, unpack it, Loading @@ -835,14 +858,21 @@ connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn) static int connection_or_process_cells_from_inbuf(or_connection_t *conn) { char buf[CELL_NETWORK_SIZE]; cell_t cell; var_cell_t *var_cell; loop: while (1) { log_debug(LD_OR, "%d: starting, inbuf_datalen %d (%d pending in tls object).", conn->_base.s,(int)buf_datalen(conn->_base.inbuf), tor_tls_get_pending_bytes(conn->tls)); if (connection_fetch_var_cell_from_buf(conn, &var_cell)) { if (!var_cell) return 0; /* not yet. */ command_process_var_cell(var_cell, conn); var_cell_free(var_cell); } else { char buf[CELL_NETWORK_SIZE]; cell_t cell; if (buf_datalen(conn->_base.inbuf) < CELL_NETWORK_SIZE) /* whole response available? */ return 0; /* not yet */ Loading @@ -854,8 +884,8 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn) cell_unpack(&cell, buf); command_process_cell(&cell, conn); goto loop; /* process the remainder of the buffer */ } } } /** Write a destroy cell with circ ID <b>circ_id</b> and reason <b>reason</b> Loading
src/or/or.h +23 −8 Changes for src/or/or.h: 23 added lines, 8 removed lines. Original line number Diff line number Diff line Loading @@ -660,6 +660,9 @@ typedef enum { #define CELL_CERT 9 #define CELL_LINK_AUTH 10 #define CELL_COMMAND_IS_VAR_LENGTH(x) \ ((x) == CELL_CERT || (x) == CELL_VERSIONS) /** How long to test reachability before complaining to the user. */ #define TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT (20*60) Loading Loading @@ -701,28 +704,36 @@ typedef enum { /** Number of bytes in a cell transmitted over the network. */ #define CELL_NETWORK_SIZE 512 #define VAR_CELL_HEADER_SIZE 5 /** Number of bytes in a relay cell's header (not including general cell * header). */ #define RELAY_HEADER_SIZE (1+2+2+4+2) /** Largest number of bytes that can fit in a relay cell payload. */ #define RELAY_PAYLOAD_SIZE (CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE) typedef struct cell_t cell_t; /** Parsed onion routing cell. All communication between nodes * is via cells. */ struct cell_t { typedef struct cell_t { uint16_t circ_id; /**< Circuit which received the cell. */ uint8_t command; /**< Type of the cell: one of PADDING, CREATE, RELAY, * or DESTROY. */ uint8_t command; /**< Type of the cell: one of CELL_PADDING, CELL_CREATE, * CELL_DESTROY, etc */ char payload[CELL_PAYLOAD_SIZE]; /**< Cell body. */ }; } cell_t; /** Parsed variable-length onion routing cell. */ typedef struct var_cell_t { uint8_t command; uint16_t circ_id; uint16_t payload_len; char payload[1]; } var_cell_t; typedef struct packed_cell_t packed_cell_t; /** A cell as packed for writing to the network. */ struct packed_cell_t { typedef struct packed_cell_t { struct packed_cell_t *next; /**< Next cell queued on this circuit. */ char body[CELL_NETWORK_SIZE]; /**< Cell as packed for network. */ }; } packed_cell_t; /** A queue of cells on a circuit, waiting to be added to the * or_connection_t's outbuf. */ Loading Loading @@ -2387,6 +2398,7 @@ int write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state, const char *data, size_t data_len, int done); int move_buf_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen); int fetch_from_buf(char *string, size_t string_len, buf_t *buf); int fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out); int fetch_from_buf_http(buf_t *buf, char **headers_out, size_t max_headerlen, char **body_out, size_t *body_used, size_t max_bodylen, Loading Loading @@ -2546,6 +2558,7 @@ int connection_ap_handshake_attach_circuit(edge_connection_t *conn); /********************************* command.c ***************************/ void command_process_cell(cell_t *cell, or_connection_t *conn); void command_process_var_cell(var_cell_t *cell, or_connection_t *conn); void connection_or_act_on_netinfo(or_connection_t *conn); extern uint64_t stats_n_padding_cells_processed; Loading Loading @@ -2786,6 +2799,8 @@ int connection_or_compute_link_auth_hmac(or_connection_t *conn, char *hmac_out); void cell_pack(packed_cell_t *dest, const cell_t *src); void var_cell_pack_header(var_cell_t *cell, char *hdr_out); void var_cell_free(var_cell_t *cell); /********************************* control.c ***************************/ Loading