Handle infinite loop with only one bridge (or snowflake).

This commit is contained in:
Mike Perry 2023-04-20 20:55:17 +00:00
parent 61aa4c3657
commit 33c3059c82
3 changed files with 45 additions and 0 deletions

View File

@ -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) {

View File

@ -139,6 +139,41 @@ bridge_list_get(void)
return bridge_list;
}
/**
* 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.

View File

@ -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);