Tor 0.4.9.0-alpha-dev
sendme.c
Go to the documentation of this file.
1/* Copyright (c) 2019-2021, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/**
5 * \file sendme.c
6 * \brief Code that is related to SENDME cells both in terms of
7 * creating/parsing cells and handling the content.
8 */
9
10#define SENDME_PRIVATE
11
12#include "core/or/or.h"
13
14#include "app/config/config.h"
17#include "core/or/cell_st.h"
18#include "core/or/crypt_path.h"
19#include "core/or/circuitlist.h"
20#include "core/or/circuituse.h"
21#include "core/or/or_circuit_st.h"
22#include "core/or/relay.h"
23#include "core/or/sendme.h"
27#include "lib/ctime/di_ops.h"
28#include "trunnel/sendme_cell.h"
29
30/* Return the minimum version given by the consensus (if any) that should be
31 * used when emitting a SENDME cell. */
32STATIC int
33get_emit_min_version(void)
34{
35 return networkstatus_get_param(NULL, "sendme_emit_min_version",
36 SENDME_EMIT_MIN_VERSION_DEFAULT,
37 SENDME_EMIT_MIN_VERSION_MIN,
38 SENDME_EMIT_MIN_VERSION_MAX);
39}
40
41/* Return the minimum version given by the consensus (if any) that should be
42 * accepted when receiving a SENDME cell. */
43STATIC int
44get_accept_min_version(void)
45{
46 return networkstatus_get_param(NULL, "sendme_accept_min_version",
47 SENDME_ACCEPT_MIN_VERSION_DEFAULT,
48 SENDME_ACCEPT_MIN_VERSION_MIN,
49 SENDME_ACCEPT_MIN_VERSION_MAX);
50}
51
52/* Pop the first cell digset on the given circuit from the SENDME last digests
53 * list. NULL is returned if the list is uninitialized or empty.
54 *
55 * The caller gets ownership of the returned digest thus is responsible for
56 * freeing the memory. */
57static uint8_t *
58pop_first_cell_digest(const circuit_t *circ)
59{
60 uint8_t *circ_digest;
61
62 tor_assert(circ);
63
64 if (circ->sendme_last_digests == NULL ||
65 smartlist_len(circ->sendme_last_digests) == 0) {
66 return NULL;
67 }
68
69 circ_digest = smartlist_get(circ->sendme_last_digests, 0);
71 return circ_digest;
72}
73
74/* Return true iff the given cell digest matches the first digest in the
75 * circuit sendme list. */
76static bool
77v1_digest_matches(const uint8_t *circ_digest, const uint8_t *cell_digest)
78{
79 tor_assert(circ_digest);
80 tor_assert(cell_digest);
81
82 /* Compare the digest with the one in the SENDME. This cell is invalid
83 * without a perfect match. */
84 if (tor_memneq(circ_digest, cell_digest, TRUNNEL_SENDME_V1_DIGEST_LEN)) {
85 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
86 "SENDME v1 cell digest do not match.");
87 return false;
88 }
89
90 /* Digests matches! */
91 return true;
92}
93
94/* Return true iff the given decoded SENDME version 1 cell is valid and
95 * matches the expected digest on the circuit.
96 *
97 * Validation is done by comparing the digest in the cell from the previous
98 * cell we saw which tells us that the other side has in fact seen that cell.
99 * See proposal 289 for more details. */
100static bool
101cell_v1_is_valid(const sendme_cell_t *cell, const uint8_t *circ_digest)
102{
103 tor_assert(cell);
104 tor_assert(circ_digest);
105
106 const uint8_t *cell_digest = sendme_cell_getconstarray_data_v1_digest(cell);
107 return v1_digest_matches(circ_digest, cell_digest);
108}
109
110/* Return true iff the given cell version can be handled or if the minimum
111 * accepted version from the consensus is known to us. */
112STATIC bool
113cell_version_can_be_handled(uint8_t cell_version)
114{
115 int accept_version = get_accept_min_version();
116
117 /* We will first check if the consensus minimum accepted version can be
118 * handled by us and if not, regardless of the cell version we got, we can't
119 * continue. */
120 if (accept_version > SENDME_MAX_SUPPORTED_VERSION) {
121 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
122 "Unable to accept SENDME version %u (from consensus). "
123 "We only support <= %u. Probably your tor is too old?",
124 accept_version, SENDME_MAX_SUPPORTED_VERSION);
125 goto invalid;
126 }
127
128 /* Then, is this version below the accepted version from the consensus? If
129 * yes, we must not handle it. */
130 if (cell_version < accept_version) {
131 log_info(LD_PROTOCOL, "Unacceptable SENDME version %u. Only "
132 "accepting %u (from consensus). Closing circuit.",
133 cell_version, accept_version);
134 goto invalid;
135 }
136
137 /* Is this cell version supported by us? */
138 if (cell_version > SENDME_MAX_SUPPORTED_VERSION) {
139 log_info(LD_PROTOCOL, "SENDME cell version %u is not supported by us. "
140 "We only support <= %u",
141 cell_version, SENDME_MAX_SUPPORTED_VERSION);
142 goto invalid;
143 }
144
145 return true;
146 invalid:
147 return false;
148}
149
150/* Return true iff the encoded SENDME cell in cell_payload of length
151 * cell_payload_len is valid. For each version:
152 *
153 * 0: No validation
154 * 1: Authenticated with last cell digest.
155 *
156 * This is the main critical function to make sure we can continue to
157 * send/recv cells on a circuit. If the SENDME is invalid, the circuit should
158 * be marked for close by the caller. */
159STATIC bool
160sendme_is_valid(const circuit_t *circ, const uint8_t *cell_payload,
161 size_t cell_payload_len)
162{
163 uint8_t cell_version;
164 uint8_t *circ_digest = NULL;
165 sendme_cell_t *cell = NULL;
166
167 tor_assert(circ);
168 tor_assert(cell_payload);
169
170 /* An empty payload means version 0 so skip trunnel parsing. We won't be
171 * able to parse a 0 length buffer into a valid SENDME cell. */
172 if (cell_payload_len == 0) {
173 cell_version = 0;
174 } else {
175 /* First we'll decode the cell so we can get the version. */
176 if (sendme_cell_parse(&cell, cell_payload, cell_payload_len) < 0) {
177 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
178 "Unparseable SENDME cell received. Closing circuit.");
179 goto invalid;
180 }
181 cell_version = sendme_cell_get_version(cell);
182 }
183
184 /* Validate that we can handle this cell version. */
185 if (!cell_version_can_be_handled(cell_version)) {
186 goto invalid;
187 }
188
189 /* Pop the first element that was added (FIFO). We do that regardless of the
190 * version so we don't accumulate on the circuit if v0 is used by the other
191 * end point. */
192 circ_digest = pop_first_cell_digest(circ);
193 if (circ_digest == NULL) {
194 /* We shouldn't have received a SENDME if we have no digests. Log at
195 * protocol warning because it can be tricked by sending many SENDMEs
196 * without prior data cell. */
197 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
198 "We received a SENDME but we have no cell digests to match. "
199 "Closing circuit.");
200 goto invalid;
201 }
202
203 /* Validate depending on the version now. */
204 switch (cell_version) {
205 case 0x01:
206 if (!cell_v1_is_valid(cell, circ_digest)) {
207 goto invalid;
208 }
209 break;
210 case 0x00:
211 /* Version 0, there is no work to be done on the payload so it is
212 * necessarily valid if we pass the version validation. */
213 break;
214 default:
215 log_warn(LD_PROTOCOL, "Unknown SENDME cell version %d received.",
216 cell_version);
218 break;
219 }
220
221 /* Valid cell. */
222 sendme_cell_free(cell);
223 tor_free(circ_digest);
224 return true;
225 invalid:
226 sendme_cell_free(cell);
227 tor_free(circ_digest);
228 return false;
229}
230
231/* Build and encode a version 1 SENDME cell into payload, which must be at
232 * least of RELAY_PAYLOAD_SIZE bytes, using the digest for the cell data.
233 *
234 * Return the size in bytes of the encoded cell in payload. A negative value
235 * is returned on encoding failure. */
236STATIC ssize_t
237build_cell_payload_v1(const uint8_t *cell_digest, uint8_t *payload)
238{
239 ssize_t len = -1;
240 sendme_cell_t *cell = NULL;
241
242 tor_assert(cell_digest);
243 tor_assert(payload);
244
245 cell = sendme_cell_new();
246
247 /* Building a payload for version 1. */
248 sendme_cell_set_version(cell, 0x01);
249 /* Set the data length field for v1. */
250 sendme_cell_set_data_len(cell, TRUNNEL_SENDME_V1_DIGEST_LEN);
251
252 /* Copy the digest into the data payload. */
253 memcpy(sendme_cell_getarray_data_v1_digest(cell), cell_digest,
254 sendme_cell_get_data_len(cell));
255
256 /* Finally, encode the cell into the payload. */
257 len = sendme_cell_encode(payload, RELAY_PAYLOAD_SIZE, cell);
258
259 sendme_cell_free(cell);
260 return len;
261}
262
263/* Send a circuit-level SENDME on the given circuit using the layer_hint if
264 * not NULL. The digest is only used for version 1.
265 *
266 * Return 0 on success else a negative value and the circuit will be closed
267 * because we failed to send the cell on it. */
268static int
269send_circuit_level_sendme(circuit_t *circ, crypt_path_t *layer_hint,
270 const uint8_t *cell_digest)
271{
272 uint8_t emit_version;
273 uint8_t payload[RELAY_PAYLOAD_SIZE];
274 ssize_t payload_len;
275
276 tor_assert(circ);
277 tor_assert(cell_digest);
278
279 emit_version = get_emit_min_version();
280 switch (emit_version) {
281 case 0x01:
282 payload_len = build_cell_payload_v1(cell_digest, payload);
283 if (BUG(payload_len < 0)) {
284 /* Unable to encode the cell, abort. We can recover from this by closing
285 * the circuit but in theory it should never happen. */
286 return -1;
287 }
288 log_debug(LD_PROTOCOL, "Emitting SENDME version 1 cell.");
289 break;
290 case 0x00:
291 FALLTHROUGH;
292 default:
293 /* Unknown version, fallback to version 0 meaning no payload. */
294 payload_len = 0;
295 log_debug(LD_PROTOCOL, "Emitting SENDME version 0 cell. "
296 "Consensus emit version is %d", emit_version);
297 break;
298 }
299
300 if (relay_send_command_from_edge(0, circ, RELAY_COMMAND_SENDME,
301 (char *) payload, payload_len,
302 layer_hint) < 0) {
303 log_warn(LD_CIRC,
304 "SENDME relay_send_command_from_edge failed. Circuit's closed.");
305 return -1; /* the circuit's closed, don't continue */
306 }
307 return 0;
308}
309
310/* Record the cell digest only if the next cell is expected to be a SENDME. */
311static void
312record_cell_digest_on_circ(circuit_t *circ, const uint8_t *sendme_digest)
313{
314 tor_assert(circ);
315 tor_assert(sendme_digest);
316
317 /* Add the digest to the last seen list in the circuit. */
318 if (circ->sendme_last_digests == NULL) {
320 }
322 tor_memdup(sendme_digest, DIGEST_LEN));
323}
324
325/*
326 * Public API
327 */
328
329/** Return true iff the next cell for the given cell window is expected to be
330 * a SENDME.
331 *
332 * We are able to know that because the package or inflight window value minus
333 * one cell (the possible SENDME cell) should be a multiple of the
334 * cells-per-sendme increment value (set via consensus parameter, negotiated
335 * for the circuit, and passed in as sendme_inc).
336 *
337 * This function is used when recording a cell digest and this is done quite
338 * low in the stack when decrypting or encrypting a cell. The window is only
339 * updated once the cell is actually put in the outbuf.
340 */
341STATIC bool
342circuit_sendme_cell_is_next(int deliver_window, int sendme_inc)
343{
344 /* Are we at the limit of the increment and if not, we don't expect next
345 * cell is a SENDME.
346 *
347 * We test against the window minus 1 because when we are looking if the
348 * next cell is a SENDME, the window (either package or deliver) hasn't been
349 * decremented just yet so when this is called, we are currently processing
350 * the "window - 1" cell.
351 *
352 * Because deliver_window starts at CIRCWINDOW_START and counts down,
353 * to get the actual number of received cells for this check, we must
354 * first convert to received cells, or the modulus operator will fail.
355 */
356 tor_assert(deliver_window <= CIRCWINDOW_START);
357 if (((CIRCWINDOW_START - (deliver_window - 1)) % sendme_inc) != 0) {
358 return false;
359 }
360
361 /* Next cell is expected to be a SENDME. */
362 return true;
363}
364
365/** Called when we've just received a relay data cell, when we've just
366 * finished flushing all bytes to stream <b>conn</b>, or when we've flushed
367 * *some* bytes to the stream <b>conn</b>.
368 *
369 * If conn->outbuf is not too full, and our deliver window is low, send back a
370 * suitable number of stream-level sendme cells.
371 */
372void
374{
375 tor_assert(conn);
376
377 int log_domain = TO_CONN(conn)->type == CONN_TYPE_AP ? LD_APP : LD_EXIT;
378
379 /* If we use flow control, we do not send stream sendmes */
380 if (edge_uses_flow_control(conn))
381 goto end;
382
383 /* Don't send it if we still have data to deliver. */
385 goto end;
386 }
387
388 if (circuit_get_by_edge_conn(conn) == NULL) {
389 /* This can legitimately happen if the destroy has already arrived and
390 * torn down the circuit. */
391 log_info(log_domain, "No circuit associated with edge connection. "
392 "Skipping sending SENDME.");
393 goto end;
394 }
395
396 while (conn->deliver_window <=
398 log_debug(log_domain, "Outbuf %" TOR_PRIuSZ ", queuing stream SENDME.",
399 buf_datalen(TO_CONN(conn)->outbuf));
401 if (connection_edge_send_command(conn, RELAY_COMMAND_SENDME,
402 NULL, 0) < 0) {
403 log_debug(LD_CIRC, "connection_edge_send_command failed while sending "
404 "a SENDME. Circuit probably closed, skipping.");
405 goto end; /* The circuit's closed, don't continue */
406 }
407 }
408
409 end:
410 return;
411}
412
413/** Check if the deliver_window for circuit <b>circ</b> (at hop
414 * <b>layer_hint</b> if it's defined) is low enough that we should
415 * send a circuit-level sendme back down the circuit. If so, send
416 * enough sendmes that the window would be overfull if we sent any
417 * more.
418 */
419void
421{
422 bool sent_one_sendme = false;
423 const uint8_t *digest;
424 int sendme_inc = sendme_get_inc_count(circ, layer_hint);
425
426 while ((layer_hint ? layer_hint->deliver_window : circ->deliver_window) <=
427 CIRCWINDOW_START - sendme_inc) {
428 log_debug(LD_CIRC,"Queuing circuit sendme.");
429 if (layer_hint) {
430 layer_hint->deliver_window += sendme_inc;
431 digest = cpath_get_sendme_digest(layer_hint);
432 } else {
433 circ->deliver_window += sendme_inc;
434 digest = relay_crypto_get_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto);
435 }
436 if (send_circuit_level_sendme(circ, layer_hint, digest) < 0) {
437 return; /* The circuit's closed, don't continue */
438 }
439 /* Current implementation is not suppose to send multiple SENDME at once
440 * because this means we would use the same relay crypto digest for each
441 * SENDME leading to a mismatch on the other side and the circuit to
442 * collapse. Scream loudly if it ever happens so we can address it. */
443 tor_assert_nonfatal(!sent_one_sendme);
444 sent_one_sendme = true;
445 }
446}
447
448/* Process a circuit-level SENDME cell that we just received. The layer_hint,
449 * if not NULL, is the Exit hop of the connection which means that we are a
450 * client. In that case, circ must be an origin circuit. The cell_body_len is
451 * the length of the SENDME cell payload (excluding the header). The
452 * cell_payload is the payload.
453 *
454 * This function validates the SENDME's digest, and then dispatches to
455 * the appropriate congestion control algorithm in use on the circuit.
456 *
457 * Return 0 on success (the SENDME is valid and the package window has
458 * been updated properly).
459 *
460 * On error, a negative value is returned, which indicates that the
461 * circuit must be closed using the value as the reason for it. */
462int
463sendme_process_circuit_level(crypt_path_t *layer_hint,
464 circuit_t *circ, const uint8_t *cell_payload,
465 uint16_t cell_payload_len)
466{
467 tor_assert(circ);
468 tor_assert(cell_payload);
470
471 /* Validate the SENDME cell. Depending on the version, different validation
472 * can be done. An invalid SENDME requires us to close the circuit. */
473 if (!sendme_is_valid(circ, cell_payload, cell_payload_len)) {
474 return -END_CIRC_REASON_TORPROTOCOL;
475 }
476
477 /* origin circuits need to count valid sendmes as valid protocol data */
478 if (CIRCUIT_IS_ORIGIN(circ)) {
479 circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), cell_payload_len);
480 }
481
482 // Get CC
483 if (layer_hint) {
484 cc = layer_hint->ccontrol;
485 } else {
486 cc = circ->ccontrol;
487 }
488
489 /* If there is no CC object, assume fixed alg */
490 if (!cc) {
491 return sendme_process_circuit_level_impl(layer_hint, circ);
492 }
493
494 return congestion_control_dispatch_cc_alg(cc, circ);
495}
496
497/**
498 * Process a SENDME for Tor's original fixed window circuit-level flow control.
499 * Updates the package_window and ensures that it does not exceed the max.
500 *
501 * Returns -END_CIRC_REASON_TORPROTOCOL if the max is exceeded, otherwise
502 * returns 0.
503 */
504int
506{
507 /* If we are the origin of the circuit, we are the Client so we use the
508 * layer hint (the Exit hop) for the package window tracking. */
509 if (CIRCUIT_IS_ORIGIN(circ)) {
510 /* If we are the origin of the circuit, it is impossible to not have a
511 * cpath. Just in case, bug on it and close the circuit. */
512 if (BUG(layer_hint == NULL)) {
513 return -END_CIRC_REASON_TORPROTOCOL;
514 }
515 if ((layer_hint->package_window + CIRCWINDOW_INCREMENT) >
516 CIRCWINDOW_START_MAX) {
517 static struct ratelim_t exit_warn_ratelim = RATELIM_INIT(600);
518 log_fn_ratelim(&exit_warn_ratelim, LOG_WARN, LD_PROTOCOL,
519 "Unexpected sendme cell from exit relay. "
520 "Closing circ.");
521 return -END_CIRC_REASON_TORPROTOCOL;
522 }
524 log_debug(LD_APP, "circ-level sendme at origin, packagewindow %d.",
525 layer_hint->package_window);
526 } else {
527 /* We aren't the origin of this circuit so we are the Exit and thus we
528 * track the package window with the circuit object. */
530 CIRCWINDOW_START_MAX) {
531 static struct ratelim_t client_warn_ratelim = RATELIM_INIT(600);
532 log_fn_ratelim(&client_warn_ratelim, LOG_PROTOCOL_WARN, LD_PROTOCOL,
533 "Unexpected sendme cell from client. "
534 "Closing circ (window %d).", circ->package_window);
535 return -END_CIRC_REASON_TORPROTOCOL;
536 }
538 log_debug(LD_EXIT, "circ-level sendme at non-origin, packagewindow %d.",
539 circ->package_window);
540 }
541
542 return 0;
543}
544
545/* Process a stream-level SENDME cell that we just received. The conn is the
546 * edge connection (stream) that the circuit circ is associated with. The
547 * cell_body_len is the length of the payload (excluding the header).
548 *
549 * Return 0 on success (the SENDME is valid and the package window has
550 * been updated properly).
551 *
552 * On error, a negative value is returned, which indicates that the
553 * circuit must be closed using the value as the reason for it. */
554int
555sendme_process_stream_level(edge_connection_t *conn, circuit_t *circ,
556 uint16_t cell_body_len)
557{
558 tor_assert(conn);
559 tor_assert(circ);
560
561 if (edge_uses_flow_control(conn)) {
562 log_fn(LOG_PROTOCOL_WARN, LD_EDGE,
563 "Congestion control got stream sendme");
564 return -END_CIRC_REASON_TORPROTOCOL;
565 }
566
567 /* Don't allow the other endpoint to request more than our maximum (i.e.
568 * initial) stream SENDME window worth of data. Well-behaved stock clients
569 * will not request more than this max (as per the check in the while loop
570 * of sendme_connection_edge_consider_sending()). */
572 STREAMWINDOW_START_MAX) {
573 static struct ratelim_t stream_warn_ratelim = RATELIM_INIT(600);
574 log_fn_ratelim(&stream_warn_ratelim, LOG_PROTOCOL_WARN, LD_PROTOCOL,
575 "Unexpected stream sendme cell. Closing circ (window %d).",
576 conn->package_window);
577 return -END_CIRC_REASON_TORPROTOCOL;
578 }
579 /* At this point, the stream sendme is valid */
581
582 /* We count circuit-level sendme's as valid delivered data because they are
583 * rate limited. */
584 if (CIRCUIT_IS_ORIGIN(circ)) {
585 circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), cell_body_len);
586 }
587
588 log_debug(CIRCUIT_IS_ORIGIN(circ) ? LD_APP : LD_EXIT,
589 "stream-level sendme, package_window now %d.",
590 conn->package_window);
591 return 0;
592}
593
594/* Called when a relay DATA cell is received on the given circuit. If
595 * layer_hint is NULL, this means we are the Exit end point else we are the
596 * Client. Update the deliver window and return its new value. */
597int
598sendme_circuit_data_received(circuit_t *circ, crypt_path_t *layer_hint)
599{
600 int deliver_window, domain;
601
602 if (CIRCUIT_IS_ORIGIN(circ)) {
603 tor_assert(layer_hint);
604 --layer_hint->deliver_window;
605 deliver_window = layer_hint->deliver_window;
606 domain = LD_APP;
607 } else {
608 tor_assert(!layer_hint);
609 --circ->deliver_window;
610 deliver_window = circ->deliver_window;
611 domain = LD_EXIT;
612 }
613
614 log_debug(domain, "Circuit deliver_window now %d.", deliver_window);
615 return deliver_window;
616}
617
618/* Called when a relay DATA cell is received for the given edge connection
619 * conn. Update the deliver window and return its new value. */
620int
621sendme_stream_data_received(edge_connection_t *conn)
622{
623 tor_assert(conn);
624
625 if (edge_uses_flow_control(conn)) {
626 return flow_control_decide_xoff(conn);
627 } else {
628 return --conn->deliver_window;
629 }
630}
631
632/* Called when a relay DATA cell is packaged on the given circuit. If
633 * layer_hint is NULL, this means we are the Exit end point else we are the
634 * Client. Update the package window and return its new value. */
635int
636sendme_note_circuit_data_packaged(circuit_t *circ, crypt_path_t *layer_hint)
637{
638 int package_window, domain;
640
641 tor_assert(circ);
642
643 if (layer_hint) {
644 cc = layer_hint->ccontrol;
645 domain = LD_APP;
646 } else {
647 cc = circ->ccontrol;
648 domain = LD_EXIT;
649 }
650
651 if (cc) {
652 congestion_control_note_cell_sent(cc, circ, layer_hint);
653 } else {
654 /* Fixed alg uses package_window and must update it */
655
656 if (CIRCUIT_IS_ORIGIN(circ)) {
657 /* Client side. */
658 tor_assert(layer_hint);
659 --layer_hint->package_window;
660 package_window = layer_hint->package_window;
661 } else {
662 /* Exit side. */
663 tor_assert(!layer_hint);
664 --circ->package_window;
665 package_window = circ->package_window;
666 }
667 log_debug(domain, "Circuit package_window now %d.", package_window);
668 }
669
670 /* Return appropriate number designating how many cells can still be sent */
671 return congestion_control_get_package_window(circ, layer_hint);
672}
673
674/* Called when a relay DATA cell is packaged for the given edge connection
675 * conn. Update the package window and return its new value. */
676int
677sendme_note_stream_data_packaged(edge_connection_t *conn, size_t len)
678{
679 tor_assert(conn);
680
681 if (edge_uses_flow_control(conn)) {
683 if (conn->xoff_received)
684 return -1;
685 else
686 return 1;
687 }
688
689 --conn->package_window;
690 log_debug(LD_APP, "Stream package_window now %d.", conn->package_window);
691 return conn->package_window;
692}
693
694/* Record the cell digest into the circuit sendme digest list depending on
695 * which edge we are. The digest is recorded only if we expect the next cell
696 * that we will receive is a SENDME so we can match the digest. */
697void
698sendme_record_cell_digest_on_circ(circuit_t *circ, crypt_path_t *cpath)
699{
700 uint8_t *sendme_digest;
701
702 tor_assert(circ);
703
704 /* Is this the last cell before a SENDME? The idea is that if the
705 * package_window reaches a multiple of the increment, after this cell, we
706 * should expect a SENDME. */
707 if (!circuit_sent_cell_for_sendme(circ, cpath)) {
708 return;
709 }
710
711 /* Getting the digest is expensive so we only do it once we are certain to
712 * record it on the circuit. */
713 if (cpath) {
714 sendme_digest = cpath_get_sendme_digest(cpath);
715 } else {
716 sendme_digest =
718 }
719
720 record_cell_digest_on_circ(circ, sendme_digest);
721}
722
723/* Called once we decrypted a cell and recognized it. Record the cell digest
724 * as the next sendme digest only if the next cell we'll send on the circuit
725 * is expected to be a SENDME. */
726void
727sendme_record_received_cell_digest(circuit_t *circ, crypt_path_t *cpath)
728{
729 tor_assert(circ);
730
731 /* Only record if the next cell is expected to be a SENDME. */
732 if (!circuit_sendme_cell_is_next(cpath ? cpath->deliver_window :
733 circ->deliver_window,
734 sendme_get_inc_count(circ, cpath))) {
735 return;
736 }
737
738 if (cpath) {
739 /* Record incoming digest. */
741 } else {
742 /* Record forward digest. */
744 }
745}
746
747/* Called once we encrypted a cell. Record the cell digest as the next sendme
748 * digest only if the next cell we expect to receive is a SENDME so we can
749 * match the digests. */
750void
751sendme_record_sending_cell_digest(circuit_t *circ, crypt_path_t *cpath)
752{
753 tor_assert(circ);
754
755 /* Only record if the next cell is expected to be a SENDME. */
756 if (!circuit_sent_cell_for_sendme(circ, cpath)) {
757 goto end;
758 }
759
760 if (cpath) {
761 /* Record the forward digest. */
763 } else {
764 /* Record the incoming digest. */
766 }
767
768 end:
769 return;
770}
size_t buf_datalen(const buf_t *buf)
Definition: buffers.c:394
Fixed-size cell structure.
circuit_t * circuit_get_by_edge_conn(edge_connection_t *conn)
Definition: circuitlist.c:1606
origin_circuit_t * TO_ORIGIN_CIRCUIT(circuit_t *x)
Definition: circuitlist.c:185
or_circuit_t * TO_OR_CIRCUIT(circuit_t *x)
Definition: circuitlist.c:173
Header file for circuitlist.c.
#define CIRCUIT_IS_ORIGIN(c)
Definition: circuitlist.h:154
void circuit_read_valid_data(origin_circuit_t *circ, uint16_t relay_body_len)
Definition: circuituse.c:3197
Header file for circuituse.c.
Header file for config.c.
int sendme_get_inc_count(const circuit_t *circ, const crypt_path_t *layer_hint)
bool circuit_sent_cell_for_sendme(const circuit_t *circ, const crypt_path_t *layer_hint)
void congestion_control_note_cell_sent(congestion_control_t *cc, const circuit_t *circ, const crypt_path_t *cpath)
int congestion_control_dispatch_cc_alg(congestion_control_t *cc, circuit_t *circ)
int congestion_control_get_package_window(const circuit_t *circ, const crypt_path_t *cpath)
Public APIs for congestion control.
int flow_control_decide_xoff(edge_connection_t *stream)
void flow_control_note_sent_data(edge_connection_t *stream, size_t len)
bool edge_uses_flow_control(const edge_connection_t *stream)
APIs for stream flow control on congestion controlled circuits.
int connection_outbuf_too_full(connection_t *conn)
Definition: connection.c:4361
Header file for connection.c.
#define CONN_TYPE_AP
Definition: connection.h:51
void cpath_sendme_record_cell_digest(crypt_path_t *cpath, bool is_foward_digest)
Definition: crypt_path.c:216
uint8_t * cpath_get_sendme_digest(crypt_path_t *cpath)
Definition: crypt_path.c:208
Header file for crypt_path.c.
Headers for di_ops.c.
#define tor_memneq(a, b, sz)
Definition: di_ops.h:21
#define DIGEST_LEN
Definition: digest_sizes.h:20
#define log_fn(severity, domain, args,...)
Definition: log.h:283
#define log_fn_ratelim(ratelim, severity, domain, args,...)
Definition: log.h:288
#define LD_EDGE
Definition: log.h:94
#define LD_APP
Definition: log.h:78
#define LD_PROTOCOL
Definition: log.h:72
#define LD_CIRC
Definition: log.h:82
#define LOG_WARN
Definition: log.h:53
#define tor_free(p)
Definition: malloc.h:56
int32_t networkstatus_get_param(const networkstatus_t *ns, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val)
Header file for networkstatus.c.
Master header file for Tor-specific functionality.
#define STREAMWINDOW_INCREMENT
Definition: or.h:404
#define STREAMWINDOW_START
Definition: or.h:401
#define RELAY_PAYLOAD_SIZE
Definition: or.h:494
#define CIRCWINDOW_START
Definition: or.h:394
#define TO_CONN(c)
Definition: or.h:612
#define CIRCWINDOW_INCREMENT
Definition: or.h:398
int connection_edge_send_command(edge_connection_t *fromconn, uint8_t relay_command, const char *payload, size_t payload_len)
Definition: relay.c:801
Header file for relay.c.
Header for relay_crypto.c.
uint8_t * relay_crypto_get_sendme_digest(relay_crypto_t *crypto)
Definition: relay_crypto.c:102
void relay_crypto_record_sendme_digest(relay_crypto_t *crypto, bool is_foward_digest)
Definition: relay_crypto.c:111
void sendme_connection_edge_consider_sending(edge_connection_t *conn)
Definition: sendme.c:373
void sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint)
Definition: sendme.c:420
STATIC bool circuit_sendme_cell_is_next(int deliver_window, int sendme_inc)
Definition: sendme.c:342
int sendme_process_circuit_level_impl(crypt_path_t *layer_hint, circuit_t *circ)
Definition: sendme.c:505
Header file for sendme.c.
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
void smartlist_del_keeporder(smartlist_t *sl, int idx)
smartlist_t * sendme_last_digests
Definition: circuit_st.h:148
int deliver_window
Definition: circuit_st.h:122
int package_window
Definition: circuit_st.h:117
struct congestion_control_t * ccontrol
Definition: circuit_st.h:250
struct congestion_control_t * ccontrol
Definition: crypt_path_st.h:89
#define STATIC
Definition: testsupport.h:32
#define tor_assert_nonfatal_unreached()
Definition: util_bug.h:177
#define tor_assert(expr)
Definition: util_bug.h:103