use std::io;
use crate::frame::{Frame, Reason, Reset};
use crate::{error, frame, stream::StreamRef};
#[derive(Debug)]
pub enum ControlMessage<E> {
AppError(AppError<E>),
ConnectionError(ConnectionError),
GoAway(GoAway),
PeerGone(PeerGone),
Terminated(Terminated),
}
#[derive(Clone, Debug)]
pub struct ControlResult {
pub(crate) frame: Option<Frame>,
pub(crate) disconnect: bool,
}
impl<E> ControlMessage<E> {
pub(super) fn app_error(err: E, stream: StreamRef) -> Self {
ControlMessage::AppError(AppError::new(err, stream))
}
pub(super) fn go_away(frm: frame::GoAway) -> Self {
ControlMessage::GoAway(GoAway(frm))
}
pub(super) fn peer_gone(err: Option<io::Error>) -> Self {
ControlMessage::PeerGone(PeerGone(err))
}
pub(super) fn terminated() -> Self {
ControlMessage::Terminated(Terminated)
}
pub(super) fn proto_error(err: error::ConnectionError) -> Self {
ControlMessage::ConnectionError(ConnectionError::new(err))
}
pub fn ack(self) -> ControlResult {
match self {
ControlMessage::AppError(item) => item.ack(),
ControlMessage::ConnectionError(item) => item.ack(),
ControlMessage::GoAway(item) => item.ack(),
ControlMessage::PeerGone(item) => item.ack(),
ControlMessage::Terminated(item) => item.ack(),
}
}
}
#[derive(Debug)]
pub struct AppError<E> {
err: E,
reason: Reason,
stream: StreamRef,
}
impl<E> AppError<E> {
fn new(err: E, stream: StreamRef) -> Self {
Self {
err,
stream,
reason: Reason::CANCEL,
}
}
#[inline]
pub fn get_ref(&self) -> &E {
&self.err
}
#[inline]
pub fn reason(mut self, reason: Reason) -> Self {
self.reason = reason;
self
}
#[inline]
pub fn ack(self) -> ControlResult {
ControlResult {
frame: Some(Reset::new(self.stream.id(), self.reason).into()),
disconnect: false,
}
}
}
#[derive(Debug)]
pub struct Terminated;
impl Terminated {
#[inline]
pub fn ack(self) -> ControlResult {
ControlResult {
frame: None,
disconnect: true,
}
}
}
#[derive(Debug)]
pub struct ConnectionError {
err: error::ConnectionError,
frm: frame::GoAway,
}
impl ConnectionError {
pub fn new(err: error::ConnectionError) -> Self {
Self {
frm: err.to_goaway(),
err,
}
}
#[inline]
pub fn get_ref(&self) -> &error::ConnectionError {
&self.err
}
#[inline]
pub fn reason(mut self, reason: Reason) -> Self {
self.frm = self.frm.set_reason(reason);
self
}
#[inline]
pub fn ack(self) -> ControlResult {
ControlResult {
frame: Some(self.frm.into()),
disconnect: true,
}
}
}
#[derive(Debug)]
pub struct PeerGone(pub(super) Option<io::Error>);
impl PeerGone {
pub fn err(&self) -> Option<&io::Error> {
self.0.as_ref()
}
pub fn take(&mut self) -> Option<io::Error> {
self.0.take()
}
pub fn ack(self) -> ControlResult {
ControlResult {
frame: None,
disconnect: true,
}
}
}
#[derive(Debug)]
pub struct GoAway(frame::GoAway);
impl GoAway {
pub fn frame(&self) -> &frame::GoAway {
&self.0
}
pub fn ack(self) -> ControlResult {
ControlResult {
frame: None,
disconnect: true,
}
}
}