use tor_cell::relaycell::msg::AnyRelayMsg;
use tor_cell::relaycell::{AnyRelayMsgOuter, RelayMsg, UnparsedRelayMsg};
use crate::{Error, Result};
use crate::client::reactor::MetaCellDisposition;
use super::HopLocation;
pub trait MsgHandler {
fn handle_msg(&mut self, msg: AnyRelayMsg) -> Result<MetaCellDisposition>;
}
#[cfg_attr(feature = "send-control-msg", visibility::make(pub))]
pub(crate) struct UserMsgHandler<T> {
hop: HopLocation,
handler: T,
}
impl<T> UserMsgHandler<T> {
pub(crate) fn new(hop: HopLocation, handler: T) -> Self {
Self { hop, handler }
}
}
impl<T: MsgHandler + Send> super::reactor::MetaCellHandler for UserMsgHandler<T> {
fn expected_hop(&self) -> HopLocation {
self.hop
}
fn handle_msg(
&mut self,
msg: UnparsedRelayMsg,
_reactor: &mut super::reactor::circuit::Circuit,
) -> Result<MetaCellDisposition> {
let cell: AnyRelayMsgOuter = msg.decode().map_err(|err| Error::BytesErr {
object: "cell for message handler",
err,
})?;
let (stream_id, msg) = cell.into_streamid_and_msg();
if stream_id.is_some() {
return Err(Error::CircProto(format!(
"Invalid message type {} received with stream ID",
msg.cmd()
)));
}
self.handler.handle_msg(msg)
}
}