use super::{Network, NetworkBackend};
use crate::link_handshake::LocalMachine;
use crate::link_open::carriers::named;
use crate::link_open::{OpenError, Stop};
use crate::link_punch::{Instruction, Puncher};
use std::net::TcpStream;
use std::sync::Arc;
use zeroize::Zeroizing;
impl Network {
pub(crate) fn incoming(&self) -> Result<(Puncher, Vec<Arc<TcpStream>>), OpenError> {
let digits = Zeroizing::new(
std::fs::read_to_string(&self.machine.identity_path)
.map_err(|_| OpenError("machine_identity_refused".to_owned()))?,
);
let mut seed = Zeroizing::new([0; 32]);
hex::decode_to_slice(digits.trim(), &mut *seed)
.map_err(|_| OpenError("machine_identity_refused".to_owned()))?;
let local = LocalMachine::new(lys_core::keys::Ed25519Identity::from_seed(&seed));
let (broker, connections) = self.broker()?;
let puncher =
self.with_puncher(|puncher| puncher.fork_listener(local, broker).map_err(named))?;
Ok((puncher, connections))
}
pub(crate) fn accept_instruction(
&self,
puncher: &mut Puncher,
word: &Instruction,
existing: Option<u32>,
) -> Result<Option<(u32, bool)>, OpenError> {
let peer = hex::encode(word.peer.ed25519_public());
if !self
.machine
.machines
.keys()
.any(|holder| self.host.recorded_machine(holder) == Some(word.peer))
{
return Err(OpenError("punch_peer_not_recorded".to_owned()));
}
if self.pending.lock().map_err(named)?.contains(&peer) {
return Ok(None);
}
let refresh = existing.is_some() && !word.opening();
let index = if let Some(index) = existing.filter(|_| refresh) {
index
} else {
let mut state = self.direct.lock().map_err(named)?;
let index = state.next;
state.next = index
.checked_add(1)
.ok_or_else(|| OpenError("direct_indices_exhausted".to_owned()))?;
index
};
let guard = self.handshakes.lock().map_err(named)?;
puncher
.answer_instruction(word, index, refresh)
.map_err(named)?;
drop(guard);
Ok(Some((index, refresh)))
}
pub(crate) fn is_stopped(&self) -> bool {
self.stopped.load(std::sync::atomic::Ordering::Acquire)
}
pub(crate) fn stop_handle(self: &Arc<Self>) -> Stop {
let network = Arc::clone(self);
Arc::new(move || network.stop())
}
}
impl NetworkBackend {
pub(crate) const fn peer(&self) -> crate::link_handshake::MachineIdentity {
self.peer
}
}