use ozzy_proto::{EnvelopeLimits, Opcode, Packet};
use super::{FetchOps, Reader, WireError};
use crate::flow::{Channel, FlowError, ReceiveEpoch};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ReceiveFence {
Normal(Channel),
History(FetchOps),
}
impl ReceiveFence {
pub const fn scope(self) -> crate::Scope {
match self {
Self::Normal(channel) => channel.scope,
Self::History(request) => request.scope,
}
}
pub fn validate_routing(
self,
packet: Packet<'_>,
limits: EnvelopeLimits,
) -> Result<(), WireError> {
packet
.envelope
.validate_frames(packet.metadata.len(), packet.payload.len(), limits)?;
let mut reader = Reader::new(packet.metadata);
if reader.routing_scope(packet.envelope.sender)? != self.scope() {
return Err(WireError::Scope);
}
match self {
Self::Normal(channel) => {
if packet.envelope.opcode != Opcode::PrepareFlow {
return Err(WireError::UnsupportedCommand);
}
if packet.envelope.response || packet.envelope.request_id.is_some() {
return Err(WireError::Correlation);
}
let epoch = ReceiveEpoch::new(u128::from_be_bytes(reader.bytes()?))?;
if epoch != channel.epoch {
return Err(FlowError::Channel.into());
}
Ok(())
}
Self::History(request) => {
if packet.envelope.opcode != Opcode::Ops {
return Err(WireError::UnsupportedCommand);
}
super::transfer::validate_routing(
request,
packet.envelope,
reader,
packet.payload.len(),
)
}
}
}
}