Skip to main content

manycastr/worker/
config.rs

1use crate::custom_module::manycastr::controller_client::ControllerClient;
2use crate::custom_module::manycastr::instruction::InstructionType;
3use crate::custom_module::manycastr::{Address, Origin};
4use local_ip_address::{local_ip, local_ipv6};
5use log::warn;
6use std::sync::Arc;
7use std::sync::atomic::AtomicBool;
8use tonic::transport::Channel;
9
10/// The worker that is run at the anycast PoPs and performs measurements as instructed by the orchestrator.
11/// The worker is responsible for establishing a connection with the orchestrator, receiving tasks, and performing measurements.
12pub struct Worker {
13    /// gRPC client to communicate with the orchestrator
14    pub(crate) grpc_client: ControllerClient<Channel>,
15    /// Hostname of the worker
16    pub(crate) hostname: String,
17    /// Whether a measurement is currently active on this worker
18    pub(crate) is_busy: Arc<AtomicBool>,
19    /// Instructions senders to the outbound probing threads, paired with their origin ID
20    pub(crate) outbound_txs: Vec<(u32, tokio::sync::mpsc::Sender<InstructionType>)>,
21    /// Join handles of the outbound probing threads, awaited on graceful end before closing inbound
22    pub(crate) outbound_handles: Vec<std::thread::JoinHandle<()>>,
23    /// Atomic boolean to signal the inbound thread to immediately stop listening for packets
24    pub(crate) abort_inbound: Arc<AtomicBool>,
25}
26
27/// Takes a list of origins, replaces any unicast placeholder addresses with the local
28/// address of the placeholder's IP version, and returns the modified list of origins.
29///
30/// Drops unicast origins when no local unicast address of that version can be found.
31///
32/// # Arguments
33/// * `origins` - A vector of Origin structs to be modified.
34///
35/// # Returns
36/// * A vector of Origin structs with unicast placeholders replaced by local addresses.
37pub fn set_unicast_origins(origins: Vec<Origin>) -> Vec<Origin> {
38    // Resolve the local addresses once (a version is looked up only when an origin needs it)
39    let mut local_v4: Option<Option<Address>> = None;
40    let mut local_v6: Option<Option<Address>> = None;
41
42    origins
43        .into_iter()
44        .filter_map(|mut o| {
45            if o.is_unicast() {
46                let is_ipv6 = o.src.expect("no src").is_v6();
47                let src_addr = if is_ipv6 {
48                    *local_v6.get_or_insert_with(|| local_ipv6().ok().map(Address::from))
49                } else {
50                    *local_v4.get_or_insert_with(|| local_ip().ok().map(Address::from))
51                };
52                match src_addr {
53                    Some(addr) => o.src = Some(addr),
54                    None => {
55                        warn!(
56                            "[Worker] No local {} address available; skipping unicast origin {}",
57                            if is_ipv6 { "IPv6" } else { "IPv4" },
58                            o.origin_id
59                        );
60                        return None;
61                    }
62                }
63            }
64            Some(o)
65        })
66        .collect()
67}