commit 33c3059c8233fb9a3076c8452f7cea00412ccdfb
parent 61aa4c3657b43e11414f8c607aadfad87eea40fd
Author: Mike Perry <mikeperry-git@torproject.org>
Date: Thu, 20 Apr 2023 20:55:17 +0000
Handle infinite loop with only one bridge (or snowflake).
Diffstat:
3 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c
@@ -35,6 +35,7 @@
#include "core/or/conflux_st.h"
#include "feature/nodelist/nodelist.h"
+#include "feature/client/bridges.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
@@ -1150,6 +1151,14 @@ conflux_add_guards_to_exclude_list(const origin_circuit_t *orig_circ,
return;
}
+ /* If there is only one bridge, then only issue a warn once that
+ * at least two bridges are best for conflux. Exempt Snowflake
+ * from this warn */
+ if (get_options()->UseBridges && !conflux_can_exclude_used_bridges()) {
+ /* Do not build any exclude lists; not enough bridges */
+ return;
+ }
+
/* A linked set exists, use it. */
const conflux_t *cfx = linked_pool_get(circ->conflux_pending_nonce, true);
if (cfx) {
diff --git a/src/feature/client/bridges.c b/src/feature/client/bridges.c
@@ -140,6 +140,41 @@ bridge_list_get(void)
}
/**
+ * Returns true if there are enough bridges to make a conflux set
+ * without re-using the same bridge.
+ */
+bool
+conflux_can_exclude_used_bridges(void)
+{
+ if (smartlist_len(bridge_list_get()) == 1) {
+ static bool warned_once = false;
+ bridge_info_t *bridge = smartlist_get(bridge_list_get(), 0);
+ tor_assert(bridge);
+
+ /* Snowflake is a special case. With one snowflake bridge,
+ * you are load balanced among many back-end bridges.
+ * So we do not need to warn the user for it. */
+ if (bridge->transport_name &&
+ strcasecmp(bridge->transport_name, "snowflake") == 0) {
+ return false;
+ }
+
+ if (!warned_once) {
+ log_warn(LD_CIRC, "Only one bridge (transport: '%s') is configured. "
+ "You should have at least two for conflux, "
+ "for any transport that is not 'snowflake'.",
+ bridge->transport_name ?
+ bridge->transport_name : "vanilla");
+ warned_once = true;
+ }
+
+ return false;
+ }
+
+ return true;
+}
+
+/**
* Given a <b>bridge</b>, return a pointer to its RSA identity digest, or
* NULL if we don't know one for it.
*/
diff --git a/src/feature/client/bridges.h b/src/feature/client/bridges.h
@@ -67,6 +67,7 @@ MOCK_DECL(download_status_t *, get_bridge_dl_status_by_id,
(const char *digest));
void bridges_free_all(void);
+bool conflux_can_exclude_used_bridges(void);
#ifdef TOR_BRIDGES_PRIVATE
STATIC void clear_bridge_list(void);