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