90 lines
3.2 KiB
Rust
90 lines
3.2 KiB
Rust
use crate::common::network_startup::get_connections;
|
|
use crate::log::{error, info};
|
|
use crate::miner::flag::{
|
|
clear_mining_stop_request, set_mining_state, set_node_mode, MiningState, NodeMode,
|
|
};
|
|
use crate::records::memory::response_channels::Command;
|
|
use crate::rpc::client::handshake::connect_and_handshake;
|
|
use crate::rpc::client::structs::Connect;
|
|
use crate::sled::Db;
|
|
use crate::sleep;
|
|
use crate::wallets::structures::Wallet;
|
|
use crate::Arc;
|
|
use crate::Duration;
|
|
use crate::Mutex;
|
|
|
|
pub async fn handle_connections(
|
|
db: Db,
|
|
wallet: Arc<Wallet>,
|
|
map: Arc<Mutex<Command>>,
|
|
) -> Result<(), String> {
|
|
// A zero outgoing limit means this node should not open any bootstrap
|
|
// connection during startup.
|
|
let outgoing_connections = crate::Settings::load()
|
|
.map(|settings| settings.outgoing_connections)
|
|
.unwrap_or(0);
|
|
if outgoing_connections == 0 {
|
|
info!("OUTGOING_CONNECTIONS is 0; skipping startup bootstrap.");
|
|
set_node_mode(NodeMode::Normal);
|
|
clear_mining_stop_request();
|
|
set_mining_state(MiningState::Idle);
|
|
return Ok(());
|
|
}
|
|
|
|
// try the configured bootstrap peers one by one until a
|
|
// handshake succeeds or the list is exhausted
|
|
let filtered_servers = get_connections().await;
|
|
let mut last_error: Option<String> = None;
|
|
|
|
for server in filtered_servers {
|
|
// build the outbound handshake request using cloned
|
|
// shared state so each attempt can run independently
|
|
let db_clone = db.clone();
|
|
|
|
// parse the configured peer string once before spawning
|
|
// the outbound connection attempt
|
|
let socket_address = server.parse().expect("Failed to parse the socket address");
|
|
|
|
// Clone the Arc for use in other async functions
|
|
let map_clone = Arc::clone(&map);
|
|
|
|
let first: bool = true;
|
|
let connect_params = Connect {
|
|
addr: socket_address,
|
|
db: db_clone,
|
|
node_ip: server.to_string(),
|
|
wallet: wallet.clone(),
|
|
map: map_clone,
|
|
first,
|
|
};
|
|
|
|
let err_string = match connect_and_handshake(connect_params).await {
|
|
Ok(()) => {
|
|
info!("Connected to {server}");
|
|
return Ok(());
|
|
}
|
|
Err(err) => err.to_string(),
|
|
};
|
|
|
|
// A peer can reject us because it already has this connection recorded.
|
|
// In that case retrying other bootstrap peers would not fix the local duplicate state.
|
|
if err_string.contains("The connection is already in the connection manager Please wait 10 minutes and try again") {
|
|
return Err(err_string);
|
|
}
|
|
error!("Error connecting to {server}: {err_string}");
|
|
last_error = Some(err_string.clone());
|
|
sleep(Duration::from_secs(5)).await;
|
|
}
|
|
|
|
if let Some(err) = last_error {
|
|
info!("No bootstrap peers connected during startup: {err}");
|
|
} else {
|
|
info!("No bootstrap peers connected during startup.");
|
|
}
|
|
// Startup can continue as a standalone node even if no bootstrap peer is reachable.
|
|
set_node_mode(NodeMode::Normal);
|
|
clear_mining_stop_request();
|
|
set_mining_state(MiningState::Idle);
|
|
Ok(())
|
|
}
|