return connection_exit_begin_conn(cell, circ);
case RELAY_COMMAND_DATA:
++stats_n_data_cells_received;
- if (( layer_hint && --layer_hint->deliver_window < 0) ||
- (!layer_hint && --circ->deliver_window < 0)) {
+
+ /* Update our circuit-level deliver window that we received a DATA cell.
+ * If the deliver window goes below 0, we end the connection due to a
+ * protocol failure. */
+ if (sendme_circuit_data_received(circ, layer_hint) < 0) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"(relay data) circ deliver_window below 0. Killing.");
if (conn) {
}
return -END_CIRC_REASON_TORPROTOCOL;
}
- log_debug(domain,"circ deliver_window now %d.", layer_hint ?
- layer_hint->deliver_window : circ->deliver_window);
+ /* Consider sending a circuit-level SENDME cell. */
sendme_circuit_consider_sending(circ, layer_hint);
if (rh.stream_id == 0) {
return 0;
}
- if (--conn->deliver_window < 0) { /* is it below 0 after decrement? */
+ /* Update our stream-level deliver window that we just received a DATA
+ * cell. Going below 0 means we have a protocol level error so the
+ * circuit is closed. */
+
+ if (sendme_stream_data_received(conn) < 0) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"(relay data) conn deliver_window below 0. Killing.");
return -END_CIRC_REASON_TORPROTOCOL;
conn->package_window);
return 0;
}
+
+/* Called when a relay DATA cell is received on the given circuit. If
+ * layer_hint is NULL, this means we are the Exit end point else we are the
+ * Client. Update the deliver window and return its new value. */
+int
+sendme_circuit_data_received(circuit_t *circ, crypt_path_t *layer_hint)
+{
+ int deliver_window, domain;
+
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ tor_assert(layer_hint);
+ --layer_hint->deliver_window;
+ deliver_window = layer_hint->deliver_window;
+ domain = LD_APP;
+ } else {
+ tor_assert(!layer_hint);
+ --circ->deliver_window;
+ deliver_window = circ->deliver_window;
+ domain = LD_EXIT;
+ }
+
+ log_debug(domain, "Circuit deliver_window now %d.", deliver_window);
+ return deliver_window;
+}
+
+/* Called when a relay DATA cell is received for the given edge connection
+ * conn. Update the deliver window and return its new value. */
+int
+sendme_stream_data_received(edge_connection_t *conn)
+{
+ tor_assert(conn);
+ return --conn->deliver_window;
+}
#include "core/or/crypt_path_st.h"
#include "core/or/circuit_st.h"
+/* Sending SENDME cell. */
void sendme_connection_edge_consider_sending(edge_connection_t *edge_conn);
void sendme_circuit_consider_sending(circuit_t *circ,
crypt_path_t *layer_hint);
+/* Processing SENDME cell. */
int sendme_process_circuit_level(crypt_path_t *layer_hint,
circuit_t *circ, uint16_t cell_body_len);
int sendme_process_stream_level(edge_connection_t *conn, circuit_t *circ,
uint16_t cell_body_len);
+/* Update deliver window functions. */
+int sendme_stream_data_received(edge_connection_t *conn);
+int sendme_circuit_data_received(circuit_t *circ, crypt_path_t *layer_hint);
+
#endif /* !defined(TOR_SENDME_H) */