mirror of
https://github.com/chatmail/core.git
synced 2026-09-22 13:01:21 +03:00
feat: try fasted relays to attempt first configure on
This commit is contained in:
@@ -546,7 +546,7 @@ impl CommandApi {
|
||||
ctx.add_transport_from_qr(&qr).await
|
||||
}
|
||||
|
||||
/// Adds an initial transport on a randomly chosen chatmail relay
|
||||
/// Adds an initial transport on the chatmail relay that answers fastest
|
||||
/// and lets the profile add further ones in the background.
|
||||
///
|
||||
/// A `DCACCOUNT:` or `DCLOGIN:` `qr` code adds a single transport
|
||||
|
||||
@@ -141,7 +141,7 @@ class Account:
|
||||
|
||||
@futuremethod
|
||||
def init_transports(self, qr: Optional[str] = None):
|
||||
"""Add an initial transport on a randomly chosen chatmail relay.
|
||||
"""Add an initial transport on the chatmail relay that answers fastest.
|
||||
|
||||
The profile then adds further ones in the background.
|
||||
A ``DCACCOUNT:`` or ``DCLOGIN:`` ``qr`` code adds a single transport
|
||||
|
||||
@@ -11,11 +11,13 @@ use deltachat_contact_tools::addr_normalize;
|
||||
use rand::distr::{Alphanumeric, SampleString};
|
||||
use rand::seq::{IndexedRandom, SliceRandom};
|
||||
use rusqlite::Transaction;
|
||||
use tokio::task::JoinSet;
|
||||
|
||||
use crate::config::{self, Config};
|
||||
use crate::configure::{EnteredLoginParam, configure};
|
||||
use crate::log::{LogExt, warn};
|
||||
use crate::login_param::{EnteredCertificateChecks, EnteredImapLoginParam};
|
||||
use crate::net::{connect_tcp, proxy::ProxyConfig};
|
||||
use crate::{context::Context, tools::time};
|
||||
|
||||
/// The target number of transports.
|
||||
@@ -57,19 +59,41 @@ pub(crate) async fn add_relay_candidates(context: &Context, addrs: &[String]) ->
|
||||
/// All candidates are probed at once with a TCP connection to their HTTPS port
|
||||
/// and configured in the order in which the connections complete,
|
||||
/// stopping at the first success. Candidates that fail the probe are skipped.
|
||||
/// Answering TCP fastest is used as a network proximity measure,
|
||||
/// which keeps latency low for initial onboarding,
|
||||
/// and it avoids relays that are down or black-holing traffic.
|
||||
pub(crate) async fn add_transport_from_candidates(
|
||||
context: &Context,
|
||||
skip_network: bool,
|
||||
) -> Result<()> {
|
||||
let mut candidates = triable_relay_candidates(context, time()).await?;
|
||||
candidates.shuffle(&mut rand::rng());
|
||||
let mut last_err = format_err!("No relay candidates");
|
||||
let mut probes = JoinSet::new();
|
||||
let proxy_config = ProxyConfig::load(context).await?;
|
||||
let load_cache = false;
|
||||
for host in candidates {
|
||||
let ctx = context.clone();
|
||||
let proxy_config = proxy_config.clone();
|
||||
probes.spawn(async move {
|
||||
let res = match proxy_config {
|
||||
_ if skip_network => Ok(()),
|
||||
Some(proxy) => proxy.connect(&ctx, &host, 443, load_cache).await.map(drop),
|
||||
None => connect_tcp(&ctx, &host, 443, load_cache).await.map(drop),
|
||||
};
|
||||
(host, res)
|
||||
});
|
||||
}
|
||||
|
||||
// We patiently try each candidate in turn which might take a while
|
||||
// if many hosts are unreachable but eventually succeeds if one candidate works.
|
||||
let mut last_err = format_err!("No relay candidates");
|
||||
let mark_as_autorelay = true;
|
||||
for host in &candidates {
|
||||
let param = login_param_from_host(host, mark_as_autorelay);
|
||||
while let Some(res) = probes.join_next().await {
|
||||
let (host, res) = res?;
|
||||
if let Err(err) = res {
|
||||
warn!(context, "Failed to connect to relay {host}: {err:#}.");
|
||||
last_err = err;
|
||||
continue;
|
||||
}
|
||||
let param = login_param_from_host(&host, mark_as_autorelay);
|
||||
match configure(context, ¶m, skip_network).await {
|
||||
Ok(()) => {
|
||||
info!(context, "Added a transport on relay {host}.");
|
||||
|
||||
@@ -56,7 +56,7 @@ async fn test_add_transport_from_candidates_failure() -> Result<()> {
|
||||
mark_defaults_tried(t, time()).await?;
|
||||
save_relay_candidates(t, &["bad host", "worse host"], 0).await?;
|
||||
|
||||
let skip_network = false;
|
||||
let skip_network = true;
|
||||
let err = add_transport_from_candidates(t, skip_network)
|
||||
.await
|
||||
.unwrap_err();
|
||||
|
||||
@@ -189,7 +189,7 @@ impl Context {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds an initial transport on a randomly chosen chatmail relay
|
||||
/// Adds an initial transport on the chatmail relay that answers fastest
|
||||
/// and lets the profile add further ones in the background.
|
||||
///
|
||||
/// A `DCACCOUNT:` or `DCLOGIN:` `qr` code adds a single transport
|
||||
|
||||
Reference in New Issue
Block a user