use async_std::{sync::Arc, task};
use netmod::Recipient;
use crate::core::{Collector, Dispatch, DriverMap, Journal, RouteTable, RouteType};
pub(crate) struct Switch {
routes: Arc<RouteTable>,
journal: Arc<Journal>,
dispatch: Arc<Dispatch>,
collector: Arc<Collector>,
drivers: Arc<DriverMap>,
}
impl Switch {
pub(crate) fn new(
routes: Arc<RouteTable>,
journal: Arc<Journal>,
dispatch: Arc<Dispatch>,
collector: Arc<Collector>,
drivers: Arc<DriverMap>,
) -> Arc<Self> {
Arc::new(Self {
routes,
journal,
dispatch,
collector,
drivers,
})
}
pub(crate) fn run(self: Arc<Self>) {
let _: Vec<_> = (0..self.drivers.len())
.into_iter()
.map(|i| {
let switch = Arc::clone(&self);
task::spawn(switch.run_inner(i))
})
.collect();
}
async fn run_inner(self: Arc<Self>, id: usize) {
let ep: &mut _ = unsafe { self.drivers.get_mut(id) };
loop {
let (f, t) = match ep.next().await {
Ok(f) => f,
_ => continue,
};
use {Recipient::*, RouteType::*};
match f.recipient {
Flood => {
let seqid = f.seqid.seqid; if self.journal.unique(&seqid).await {
self.dispatch.reflood(f, t).await
}
}
User(id) => match self.routes.reachable(id).await {
Some(Local) => self.collector.queue(f).await,
Some(Remote(_)) => self.dispatch.send(f).await,
None => self.journal.queue(f).await,
},
}
}
}
}