aboutsummaryrefslogtreecommitdiff
path: root/src/feature/hs/hs_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/feature/hs/hs_client.c')
-rw-r--r--src/feature/hs/hs_client.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c
index ced75109e0..d08b518d94 100644
--- a/src/feature/hs/hs_client.c
+++ b/src/feature/hs/hs_client.c
@@ -11,12 +11,15 @@
#include "core/or/or.h"
#include "app/config/config.h"
#include "core/crypto/hs_ntor.h"
+#include "core/crypto/onion_crypto.h"
#include "core/mainloop/connection.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
#include "core/or/connection_edge.h"
+#include "core/or/congestion_control_common.h"
#include "core/or/extendinfo.h"
+#include "core/or/protover.h"
#include "core/or/reasons.h"
#include "feature/client/circpathbias.h"
#include "feature/dirclient/dirclient.h"
@@ -641,6 +644,16 @@ send_introduce1(origin_circuit_t *intro_circ,
goto tran_err;
}
+ /* Check if the rendevous circuit was setup WITHOUT congestion control but if
+ * it is enabled and the service supports it. This can happen, see
+ * setup_rendezvous_circ_congestion_control() and so close rendezvous circuit
+ * so another one can be created. */
+ if (TO_CIRCUIT(rend_circ)->ccontrol == NULL && congestion_control_enabled()
+ && hs_desc_supports_congestion_control(desc)) {
+ circuit_mark_for_close(TO_CIRCUIT(rend_circ), END_CIRC_REASON_INTERNAL);
+ goto tran_err;
+ }
+
/* We need to find which intro point in the descriptor we are connected to
* on intro_circ. */
ip = find_desc_intro_point_by_ident(intro_circ->hs_ident, desc);
@@ -776,6 +789,45 @@ client_intro_circ_has_opened(origin_circuit_t *circ)
connection_ap_attach_pending(1);
}
+/** Setup the congestion control parameters on the given rendezvous circuit.
+ * This looks at the service descriptor flow control line (if any).
+ *
+ * It is possible that we are unable to set congestion control on the circuit
+ * if the descriptor can't be found. In that case, the introduction circuit
+ * can't be opened without it so a fetch will be triggered.
+ *
+ * However, if the descriptor asks for congestion control but the RP circuit
+ * doesn't have it, it will be closed and a new circuit will be opened. */
+static void
+setup_rendezvous_circ_congestion_control(origin_circuit_t *circ)
+{
+ tor_assert(circ);
+
+ /* Setup congestion control parameters on the circuit. */
+ const hs_descriptor_t *desc =
+ hs_cache_lookup_as_client(&circ->hs_ident->identity_pk);
+ if (desc == NULL) {
+ /* This is possible because between launching the circuit and the circuit
+ * ending in opened state, the descriptor could have been removed from the
+ * cache. In this case, we just can't setup congestion control. */
+ return;
+ }
+
+ /* Check if the service lists support for congestion control in its
+ * descriptor. If not, we don't setup congestion control. */
+ if (!hs_desc_supports_congestion_control(desc)) {
+ return;
+ }
+
+ /* If network doesn't enable it, do not setup. */
+ if (!congestion_control_enabled()) {
+ return;
+ }
+
+ hs_circ_setup_congestion_control(circ, desc->encrypted_data.sendme_inc,
+ desc->encrypted_data.single_onion_service);
+}
+
/** Called when a rendezvous circuit has opened. */
static void
client_rendezvous_circ_has_opened(origin_circuit_t *circ)
@@ -805,6 +857,9 @@ client_rendezvous_circ_has_opened(origin_circuit_t *circ)
log_info(LD_REND, "Rendezvous circuit has opened to %s.",
safe_str_client(extend_info_describe(rp_ei)));
+ /* Setup congestion control parameters on the circuit. */
+ setup_rendezvous_circ_congestion_control(circ);
+
/* Ignore returned value, nothing we can really do. On failure, the circuit
* will be marked for close. */
hs_circ_send_establish_rendezvous(circ);