use crate::circuit::HOPS;
use crate::circuit::circhop::{CircHopInbound, HopSettings};
use crate::circuit::reactor::stream::StreamMsg;
use crate::congestion::CongestionControl;
use crate::{HopNum, Result};
use std::sync::{Arc, Mutex};
use futures::channel::mpsc;
use smallvec::SmallVec;
use tor_cell::relaycell::RelayCellDecoder;
use tor_error::internal;
pub(crate) struct CircHop {
pub(crate) tx: Option<mpsc::Sender<StreamMsg>>,
pub(crate) ccontrol: Arc<Mutex<CongestionControl>>,
pub(crate) inbound: CircHopInbound,
pub(crate) settings: HopSettings,
}
#[derive(Default)]
pub(crate) struct CircHopList {
hops: SmallVec<[CircHop; HOPS]>,
}
impl CircHopList {
pub(crate) fn get(&self, hop: Option<HopNum>) -> Option<&CircHop> {
self.hops.get(Self::index(hop))
}
pub(crate) fn get_mut(&mut self, hop: Option<HopNum>) -> Option<&mut CircHop> {
self.hops.get_mut(Self::index(hop))
}
pub(crate) fn add_hop(&mut self, settings: HopSettings) -> Result<()> {
let hop_num = self.hops.len();
debug_assert_eq!(hop_num, usize::from(self.num_hops()));
if hop_num == usize::from(u8::MAX) {
return Err(internal!("cannot add more hops to a circuit with `u8::MAX` hops").into());
}
let relay_format = settings.relay_crypt_protocol().relay_cell_format();
let inbound = CircHopInbound::new(RelayCellDecoder::new(relay_format), &settings);
let ccontrol = Arc::new(Mutex::new(CongestionControl::new(&settings.ccontrol)));
self.hops.push(CircHop {
inbound,
ccontrol,
settings,
tx: None,
});
Ok(())
}
fn num_hops(&self) -> u8 {
self.hops
.len()
.try_into()
.expect("`hops.len()` has more than `u8::MAX` hops")
}
fn index(hop: Option<HopNum>) -> usize {
hop.map(usize::from).unwrap_or_default()
}
}