|
@@ -93,13 +93,12 @@
|
|
#include "core/or/origin_circuit_st.h"
|
|
#include "core/or/origin_circuit_st.h"
|
|
#include "feature/nodelist/routerinfo_st.h"
|
|
#include "feature/nodelist/routerinfo_st.h"
|
|
#include "core/or/socks_request_st.h"
|
|
#include "core/or/socks_request_st.h"
|
|
|
|
+#include "core/or/sendme.h"
|
|
|
|
|
|
static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell,
|
|
static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell,
|
|
cell_direction_t cell_direction,
|
|
cell_direction_t cell_direction,
|
|
crypt_path_t *layer_hint);
|
|
crypt_path_t *layer_hint);
|
|
|
|
|
|
-static void circuit_consider_sending_sendme(circuit_t *circ,
|
|
|
|
- crypt_path_t *layer_hint);
|
|
|
|
static void circuit_resume_edge_reading(circuit_t *circ,
|
|
static void circuit_resume_edge_reading(circuit_t *circ,
|
|
crypt_path_t *layer_hint);
|
|
crypt_path_t *layer_hint);
|
|
static int circuit_resume_edge_reading_helper(edge_connection_t *conn,
|
|
static int circuit_resume_edge_reading_helper(edge_connection_t *conn,
|
|
@@ -530,6 +529,60 @@ relay_command_to_string(uint8_t command)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ * the relay payload length expected to be put in the cell. It can not be
|
|
|
|
+ * bigger than RELAY_PAYLOAD_SIZE else this function assert().
|
|
|
|
+ *
|
|
|
|
+ * Value will always be smaller than CELL_PAYLOAD_SIZE because this offset is
|
|
|
|
+ * for the entire cell length not just the data payload length. Zero is
|
|
|
|
+ * returned if there is no room for padding.
|
|
|
|
+ *
|
|
|
|
+ * This function always skips the first 4 bytes after the payload because
|
|
|
|
+ * having some unused zero bytes has saved us a lot of times in the past. */
|
|
|
|
+
|
|
|
|
+STATIC size_t
|
|
|
|
+get_pad_cell_offset(size_t data_len)
|
|
|
|
+{
|
|
|
|
+
|
|
|
|
+ * because if tor is tricked somehow into not adding random bytes to the
|
|
|
|
+ * payload with this function returning 0 for a bad data_len, the entire
|
|
|
|
+ * authenticated SENDME design can be bypassed leading to bad denial of
|
|
|
|
+ * service attacks. */
|
|
|
|
+ tor_assert(data_len <= RELAY_PAYLOAD_SIZE);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ * of zero indicating that no padding needs to be added. */
|
|
|
|
+ size_t offset = RELAY_HEADER_SIZE + data_len + 4;
|
|
|
|
+ if (offset >= CELL_PAYLOAD_SIZE) {
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ return offset;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ * where the other side can predict all of the bytes in the payload and thus
|
|
|
|
+ * compute the authenticated SENDME cells without seeing the traffic. See
|
|
|
|
+ * proposal 289. */
|
|
|
|
+static void
|
|
|
|
+pad_cell_payload(uint8_t *cell_payload, size_t data_len)
|
|
|
|
+{
|
|
|
|
+ size_t pad_offset, pad_len;
|
|
|
|
+
|
|
|
|
+ tor_assert(cell_payload);
|
|
|
|
+
|
|
|
|
+ pad_offset = get_pad_cell_offset(data_len);
|
|
|
|
+ if (pad_offset == 0) {
|
|
|
|
+
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ * payload size so we offset it using the full lenght of the cell. */
|
|
|
|
+ pad_len = CELL_PAYLOAD_SIZE - pad_offset;
|
|
|
|
+ crypto_fast_rng_getbytes(get_thread_fast_rng(),
|
|
|
|
+ cell_payload + pad_offset, pad_len);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
|
|
* it onto the open circuit <b>circ</b>. <b>stream_id</b> is the ID on
|
|
* it onto the open circuit <b>circ</b>. <b>stream_id</b> is the ID on
|
|
* <b>circ</b> for the stream that's sending the relay cell, or 0 if it's a
|
|
* <b>circ</b> for the stream that's sending the relay cell, or 0 if it's a
|
|
@@ -573,6 +626,9 @@ relay_send_command_from_edge_,(streamid_t stream_id, circuit_t *circ,
|
|
if (payload_len)
|
|
if (payload_len)
|
|
memcpy(cell.payload+RELAY_HEADER_SIZE, payload, payload_len);
|
|
memcpy(cell.payload+RELAY_HEADER_SIZE, payload, payload_len);
|
|
|
|
|
|
|
|
+
|
|
|
|
+ pad_cell_payload(cell.payload, payload_len);
|
|
|
|
+
|
|
log_debug(LD_OR,"delivering %d cell %s.", relay_command,
|
|
log_debug(LD_OR,"delivering %d cell %s.", relay_command,
|
|
cell_direction == CELL_DIRECTION_OUT ? "forward" : "backward");
|
|
cell_direction == CELL_DIRECTION_OUT ? "forward" : "backward");
|
|
|
|
|
|
@@ -640,6 +696,14 @@ relay_send_command_from_edge_,(streamid_t stream_id, circuit_t *circ,
|
|
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
|
|
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ * we need to. This call needs to be after the circuit_package_relay_cell()
|
|
|
|
+ * because the cell digest is set within that function. */
|
|
|
|
+ if (relay_command == RELAY_COMMAND_DATA) {
|
|
|
|
+ sendme_record_cell_digest(circ);
|
|
|
|
+ }
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1429,6 +1493,81 @@ connection_edge_process_relay_cell_not_open(
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ * cell, it is destined for the given <b>conn</b>. If it is a circuit level
|
|
|
|
+ * cell, it is destined for the <b>layer_hint</b>. The <b>domain</b> is the
|
|
|
|
+ * logging domain that should be used.
|
|
|
|
+ *
|
|
|
|
+ * Return 0 if everything went well or a negative value representing a circuit
|
|
|
|
+ * end reason on error for which the caller is responsible for closing it. */
|
|
|
|
+static int
|
|
|
|
+process_sendme_cell(const relay_header_t *rh, const cell_t *cell,
|
|
|
|
+ circuit_t *circ, edge_connection_t *conn,
|
|
|
|
+ crypt_path_t *layer_hint, int domain)
|
|
|
|
+{
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ tor_assert(rh);
|
|
|
|
+
|
|
|
|
+ if (!rh->stream_id) {
|
|
|
|
+
|
|
|
|
+ ret = sendme_process_circuit_level(layer_hint, circ,
|
|
|
|
+ cell->payload + RELAY_HEADER_SIZE,
|
|
|
|
+ rh->length);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ * SENDME cell that updated our package window. */
|
|
|
|
+ circuit_resume_edge_reading(circ, layer_hint);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (!conn) {
|
|
|
|
+ if (CIRCUIT_IS_ORIGIN(circ)) {
|
|
|
|
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
|
|
|
+ if (connection_half_edge_is_valid_sendme(ocirc->half_streams,
|
|
|
|
+ rh->stream_id)) {
|
|
|
|
+ circuit_read_valid_data(ocirc, rh->length);
|
|
|
|
+ log_info(domain, "Sendme cell on circ %u valid on half-closed "
|
|
|
|
+ "stream id %d",
|
|
|
|
+ ocirc->global_identifier, rh->stream_id);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ log_info(domain, "SENDME cell dropped, unknown stream (streamid %d).",
|
|
|
|
+ rh->stream_id);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ ret = sendme_process_stream_level(conn, circ, rh->length);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ * properly updated, we'll read on the edge connection to see if we can
|
|
|
|
+ * get data out towards the end point (Exit or client) since we are now
|
|
|
|
+ * allowed to deliver more cells. */
|
|
|
|
+
|
|
|
|
+ if (circuit_queue_streams_are_blocked(circ)) {
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ connection_start_reading(TO_CONN(conn));
|
|
|
|
+
|
|
|
|
+ if (connection_edge_package_raw_inbuf(conn, 1, NULL) < 0) {
|
|
|
|
+
|
|
|
|
+ connection_mark_for_close(TO_CONN(conn));
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
|
|
* <b>conn</b> is NULL this is a control cell, else <b>cell</b> is
|
|
* <b>conn</b> is NULL this is a control cell, else <b>cell</b> is
|
|
* destined for <b>conn</b>.
|
|
* destined for <b>conn</b>.
|
|
@@ -1549,22 +1688,19 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
|
return connection_exit_begin_conn(cell, circ);
|
|
return connection_exit_begin_conn(cell, circ);
|
|
case RELAY_COMMAND_DATA:
|
|
case RELAY_COMMAND_DATA:
|
|
++stats_n_data_cells_received;
|
|
++stats_n_data_cells_received;
|
|
- if (( layer_hint && --layer_hint->deliver_window < 0) ||
|
|
+
|
|
- (!layer_hint && --circ->deliver_window < 0)) {
|
|
+
|
|
|
|
+ * If the deliver window goes below 0, we end the circuit and stream due
|
|
|
|
+ * to a protocol failure. */
|
|
|
|
+ if (sendme_circuit_data_received(circ, layer_hint) < 0) {
|
|
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
|
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
|
"(relay data) circ deliver_window below 0. Killing.");
|
|
"(relay data) circ deliver_window below 0. Killing.");
|
|
- if (conn) {
|
|
+ connection_edge_end_close(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
-
|
|
|
|
- * not send an END and mark the stream for close as appropriate? */
|
|
|
|
- connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
|
|
- connection_mark_for_close(TO_CONN(conn));
|
|
|
|
- }
|
|
|
|
return -END_CIRC_REASON_TORPROTOCOL;
|
|
return -END_CIRC_REASON_TORPROTOCOL;
|
|
}
|
|
}
|
|
- log_debug(domain,"circ deliver_window now %d.", layer_hint ?
|
|
|
|
- layer_hint->deliver_window : circ->deliver_window);
|
|
|
|
|
|
|
|
- circuit_consider_sending_sendme(circ, layer_hint);
|
|
+
|
|
|
|
+ sendme_circuit_consider_sending(circ, layer_hint);
|
|
|
|
|
|
if (rh.stream_id == 0) {
|
|
if (rh.stream_id == 0) {
|
|
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay data cell with zero "
|
|
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay data cell with zero "
|
|
@@ -1587,9 +1723,14 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- if (--conn->deliver_window < 0) {
|
|
+
|
|
|
|
+ * cell. Going below 0 means we have a protocol level error so the
|
|
|
|
+ * stream and circuit are closed. */
|
|
|
|
+
|
|
|
|
+ if (sendme_stream_data_received(conn) < 0) {
|
|
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
|
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
|
"(relay data) conn deliver_window below 0. Killing.");
|
|
"(relay data) conn deliver_window below 0. Killing.");
|
|
|
|
+ connection_edge_end_close(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
return -END_CIRC_REASON_TORPROTOCOL;
|
|
return -END_CIRC_REASON_TORPROTOCOL;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1615,7 +1756,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
|
|
|
|
|
* a SENDME could arrive before the CONNECTED.
|
|
* a SENDME could arrive before the CONNECTED.
|
|
*/
|
|
*/
|
|
- connection_edge_consider_sending_sendme(conn);
|
|
+ sendme_connection_edge_consider_sending(conn);
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -1808,99 +1949,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
|
(unsigned)circ->n_circ_id, rh.stream_id);
|
|
(unsigned)circ->n_circ_id, rh.stream_id);
|
|
return 0;
|
|
return 0;
|
|
case RELAY_COMMAND_SENDME:
|
|
case RELAY_COMMAND_SENDME:
|
|
- if (!rh.stream_id) {
|
|
+ return process_sendme_cell(&rh, cell, circ, conn, layer_hint, domain);
|
|
- if (layer_hint) {
|
|
|
|
- if (layer_hint->package_window + CIRCWINDOW_INCREMENT >
|
|
|
|
- CIRCWINDOW_START_MAX) {
|
|
|
|
- static struct ratelim_t exit_warn_ratelim = RATELIM_INIT(600);
|
|
|
|
- log_fn_ratelim(&exit_warn_ratelim, LOG_WARN, LD_PROTOCOL,
|
|
|
|
- "Unexpected sendme cell from exit relay. "
|
|
|
|
- "Closing circ.");
|
|
|
|
- return -END_CIRC_REASON_TORPROTOCOL;
|
|
|
|
- }
|
|
|
|
- layer_hint->package_window += CIRCWINDOW_INCREMENT;
|
|
|
|
- log_debug(LD_APP,"circ-level sendme at origin, packagewindow %d.",
|
|
|
|
- layer_hint->package_window);
|
|
|
|
- circuit_resume_edge_reading(circ, layer_hint);
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- * they are rate limited.
|
|
|
|
- */
|
|
|
|
- if (CIRCUIT_IS_ORIGIN(circ)) {
|
|
|
|
- circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ),
|
|
|
|
- rh.length);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- } else {
|
|
|
|
- if (circ->package_window + CIRCWINDOW_INCREMENT >
|
|
|
|
- CIRCWINDOW_START_MAX) {
|
|
|
|
- static struct ratelim_t client_warn_ratelim = RATELIM_INIT(600);
|
|
|
|
- log_fn_ratelim(&client_warn_ratelim,LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
|
|
|
- "Unexpected sendme cell from client. "
|
|
|
|
- "Closing circ (window %d).",
|
|
|
|
- circ->package_window);
|
|
|
|
- return -END_CIRC_REASON_TORPROTOCOL;
|
|
|
|
- }
|
|
|
|
- circ->package_window += CIRCWINDOW_INCREMENT;
|
|
|
|
- log_debug(LD_APP,
|
|
|
|
- "circ-level sendme at non-origin, packagewindow %d.",
|
|
|
|
- circ->package_window);
|
|
|
|
- circuit_resume_edge_reading(circ, layer_hint);
|
|
|
|
- }
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
- if (!conn) {
|
|
|
|
- if (CIRCUIT_IS_ORIGIN(circ)) {
|
|
|
|
- origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
|
|
|
- if (connection_half_edge_is_valid_sendme(ocirc->half_streams,
|
|
|
|
- rh.stream_id)) {
|
|
|
|
- circuit_read_valid_data(ocirc, rh.length);
|
|
|
|
- log_info(domain,
|
|
|
|
- "sendme cell on circ %u valid on half-closed "
|
|
|
|
- "stream id %d", ocirc->global_identifier, rh.stream_id);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- log_info(domain,"sendme cell dropped, unknown stream (streamid %d).",
|
|
|
|
- rh.stream_id);
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- * (i.e. initial) stream SENDME window worth of data. Well-behaved
|
|
|
|
- * stock clients will not request more than this max (as per the check
|
|
|
|
- * in the while loop of connection_edge_consider_sending_sendme()).
|
|
|
|
- */
|
|
|
|
- if (conn->package_window + STREAMWINDOW_INCREMENT >
|
|
|
|
- STREAMWINDOW_START_MAX) {
|
|
|
|
- static struct ratelim_t stream_warn_ratelim = RATELIM_INIT(600);
|
|
|
|
- log_fn_ratelim(&stream_warn_ratelim, LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
|
|
|
- "Unexpected stream sendme cell. Closing circ (window %d).",
|
|
|
|
- conn->package_window);
|
|
|
|
- return -END_CIRC_REASON_TORPROTOCOL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- if (CIRCUIT_IS_ORIGIN(circ)) {
|
|
|
|
- circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ),
|
|
|
|
- rh.length);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- conn->package_window += STREAMWINDOW_INCREMENT;
|
|
|
|
- log_debug(domain,"stream-level sendme, packagewindow now %d.",
|
|
|
|
- conn->package_window);
|
|
|
|
- if (circuit_queue_streams_are_blocked(circ)) {
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
- connection_start_reading(TO_CONN(conn));
|
|
|
|
-
|
|
|
|
- if (connection_edge_package_raw_inbuf(conn, 1, NULL) < 0) {
|
|
|
|
-
|
|
|
|
- connection_mark_for_close(TO_CONN(conn));
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
- return 0;
|
|
|
|
case RELAY_COMMAND_RESOLVE:
|
|
case RELAY_COMMAND_RESOLVE:
|
|
if (layer_hint) {
|
|
if (layer_hint) {
|
|
log_fn(LOG_PROTOCOL_WARN, LD_APP,
|
|
log_fn(LOG_PROTOCOL_WARN, LD_APP,
|
|
@@ -2091,15 +2140,17 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!cpath_layer) {
|
|
+
|
|
- tor_assert(circ->package_window > 0);
|
|
+ if (sendme_note_circuit_data_packaged(circ, cpath_layer) < 0) {
|
|
- circ->package_window--;
|
|
+
|
|
- } else {
|
|
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
|
- tor_assert(cpath_layer->package_window > 0);
|
|
+ "Circuit package window is below 0. Closing circuit.");
|
|
- cpath_layer->package_window--;
|
|
+ conn->end_reason = END_STREAM_REASON_TORPROTOCOL;
|
|
|
|
+ return -1;
|
|
}
|
|
}
|
|
|
|
|
|
- if (--conn->package_window <= 0) {
|
|
+
|
|
|
|
+ if (sendme_note_stream_data_packaged(conn) < 0) {
|
|
connection_stop_reading(TO_CONN(conn));
|
|
connection_stop_reading(TO_CONN(conn));
|
|
log_debug(domain,"conn->package_window reached 0.");
|
|
log_debug(domain,"conn->package_window reached 0.");
|
|
circuit_consider_stop_edge_reading(circ, cpath_layer);
|
|
circuit_consider_stop_edge_reading(circ, cpath_layer);
|
|
@@ -2117,42 +2168,6 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
|
|
goto repeat_connection_edge_package_raw_inbuf;
|
|
goto repeat_connection_edge_package_raw_inbuf;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- * we've just finished flushing all bytes to stream <b>conn</b>,
|
|
|
|
- * or when we've flushed *some* bytes to the stream <b>conn</b>.
|
|
|
|
- *
|
|
|
|
- * If conn->outbuf is not too full, and our deliver window is
|
|
|
|
- * low, send back a suitable number of stream-level sendme cells.
|
|
|
|
- */
|
|
|
|
-void
|
|
|
|
-connection_edge_consider_sending_sendme(edge_connection_t *conn)
|
|
|
|
-{
|
|
|
|
- circuit_t *circ;
|
|
|
|
-
|
|
|
|
- if (connection_outbuf_too_full(TO_CONN(conn)))
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- circ = circuit_get_by_edge_conn(conn);
|
|
|
|
- if (!circ) {
|
|
|
|
-
|
|
|
|
- * arrived and torn down the circuit */
|
|
|
|
- log_info(LD_APP,"No circuit associated with conn. Skipping.");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- while (conn->deliver_window <= STREAMWINDOW_START - STREAMWINDOW_INCREMENT) {
|
|
|
|
- log_debug(conn->base_.type == CONN_TYPE_AP ?LD_APP:LD_EXIT,
|
|
|
|
- "Outbuf %d, Queuing stream sendme.",
|
|
|
|
- (int)conn->base_.outbuf_flushlen);
|
|
|
|
- conn->deliver_window += STREAMWINDOW_INCREMENT;
|
|
|
|
- if (connection_edge_send_command(conn, RELAY_COMMAND_SENDME,
|
|
|
|
- NULL, 0) < 0) {
|
|
|
|
- log_warn(LD_APP,"connection_edge_send_command failed. Skipping.");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
|
|
|
|
* (on hop <b>layer_hint</b>, if we're the OP). Go through all the
|
|
* (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
|
|
* attached streams and let them resume reading and packaging, if
|
|
@@ -2369,33 +2384,6 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- * <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.
|
|
|
|
- */
|
|
|
|
-static void
|
|
|
|
-circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint)
|
|
|
|
-{
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- while ((layer_hint ? layer_hint->deliver_window : circ->deliver_window) <=
|
|
|
|
- CIRCWINDOW_START - CIRCWINDOW_INCREMENT) {
|
|
|
|
- log_debug(LD_CIRC,"Queuing circuit sendme.");
|
|
|
|
- if (layer_hint)
|
|
|
|
- layer_hint->deliver_window += CIRCWINDOW_INCREMENT;
|
|
|
|
- else
|
|
|
|
- circ->deliver_window += CIRCWINDOW_INCREMENT;
|
|
|
|
- if (relay_send_command_from_edge(0, circ, RELAY_COMMAND_SENDME,
|
|
|
|
- NULL, 0, layer_hint) < 0) {
|
|
|
|
- log_warn(LD_CIRC,
|
|
|
|
- "relay_send_command_from_edge failed. Circuit's closed.");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
|
|
|
|
static size_t total_cells_allocated = 0;
|
|
static size_t total_cells_allocated = 0;
|
|
|
|
|