ntex_h2/
control.rs

1use std::io;
2
3use crate::frame::{Frame, Reason, Reset};
4use crate::{error, frame, stream::StreamRef};
5
6#[doc(hidden)]
7pub type ControlMessage<E> = Control<E>;
8#[doc(hidden)]
9pub type ControlResult = ControlAck;
10
11#[derive(Debug)]
12pub enum Control<E> {
13    /// Application level error from publish service
14    AppError(AppError<E>),
15    /// Protocol level error
16    ConnectionError(ConnectionError),
17    /// Remote GoAway is received
18    GoAway(GoAway),
19    /// Peer is gone
20    PeerGone(PeerGone),
21    /// Protocol dispatcher is terminated
22    Terminated(Terminated),
23}
24
25#[derive(Clone, Debug)]
26pub struct ControlAck {
27    pub(crate) frame: Option<Frame>,
28    pub(crate) disconnect: bool,
29}
30
31impl<E> Control<E> {
32    /// Create a new `Control` message for app level errors
33    pub(super) fn error(err: E) -> Self {
34        Control::AppError(AppError::new(err, None))
35    }
36
37    /// Create a new `Control` message for app level errors
38    pub(super) fn app_error(err: E, stream: StreamRef) -> Self {
39        Control::AppError(AppError::new(err, Some(stream)))
40    }
41
42    /// Create a new `Control` message from GOAWAY packet.
43    pub(super) fn go_away(frm: frame::GoAway) -> Self {
44        Control::GoAway(GoAway(frm))
45    }
46
47    /// Create a new `Control` message from DISCONNECT packet.
48    pub(super) fn peer_gone(err: Option<io::Error>) -> Self {
49        Control::PeerGone(PeerGone(err))
50    }
51
52    pub(super) fn terminated() -> Self {
53        Control::Terminated(Terminated)
54    }
55
56    /// Create a new `Control` message for protocol level errors
57    pub(super) fn proto_error(err: error::ConnectionError) -> Self {
58        Control::ConnectionError(ConnectionError::new(err))
59    }
60
61    /// Default ack impl
62    pub fn ack(self) -> ControlAck {
63        match self {
64            Control::AppError(item) => item.ack(),
65            Control::ConnectionError(item) => item.ack(),
66            Control::GoAway(item) => item.ack(),
67            Control::PeerGone(item) => item.ack(),
68            Control::Terminated(item) => item.ack(),
69        }
70    }
71}
72
73/// Service level error
74#[derive(Debug)]
75pub struct AppError<E> {
76    err: E,
77    reason: Reason,
78    stream: Option<StreamRef>,
79}
80
81impl<E> AppError<E> {
82    fn new(err: E, stream: Option<StreamRef>) -> Self {
83        Self {
84            err,
85            stream,
86            reason: Reason::CANCEL,
87        }
88    }
89
90    #[inline]
91    /// Returns reference to mqtt error
92    pub fn get_ref(&self) -> &E {
93        &self.err
94    }
95
96    #[inline]
97    /// Set reason code for go away packet
98    pub fn reason(mut self, reason: Reason) -> Self {
99        self.reason = reason;
100        self
101    }
102
103    #[inline]
104    /// Ack service error, return disconnect packet and close connection.
105    pub fn ack(self) -> ControlAck {
106        if let Some(ref stream) = self.stream {
107            ControlAck {
108                frame: Some(Reset::new(stream.id(), self.reason).into()),
109                disconnect: false,
110            }
111        } else {
112            ControlAck {
113                frame: None,
114                disconnect: true,
115            }
116        }
117    }
118}
119
120/// Dispatcher has been terminated
121#[derive(Debug)]
122pub struct Terminated;
123
124impl Terminated {
125    #[inline]
126    /// convert packet to a result
127    pub fn ack(self) -> ControlAck {
128        ControlAck {
129            frame: None,
130            disconnect: true,
131        }
132    }
133}
134
135/// Protocol level error
136#[derive(Debug)]
137pub struct ConnectionError {
138    err: error::ConnectionError,
139    frm: frame::GoAway,
140}
141
142impl ConnectionError {
143    pub fn new(err: error::ConnectionError) -> Self {
144        Self {
145            frm: err.to_goaway(),
146            err,
147        }
148    }
149
150    #[inline]
151    /// Returns reference to a protocol error
152    pub fn get_ref(&self) -> &error::ConnectionError {
153        &self.err
154    }
155
156    #[inline]
157    /// Set reason code for go away packet
158    pub fn reason(mut self, reason: Reason) -> Self {
159        self.frm = self.frm.set_reason(reason);
160        self
161    }
162
163    #[inline]
164    /// Ack protocol error, return disconnect packet and close connection.
165    pub fn ack(self) -> ControlAck {
166        ControlAck {
167            frame: Some(self.frm.into()),
168            disconnect: true,
169        }
170    }
171}
172
173#[derive(Debug)]
174pub struct PeerGone(pub(super) Option<io::Error>);
175
176impl PeerGone {
177    /// Returns error reference
178    pub fn err(&self) -> Option<&io::Error> {
179        self.0.as_ref()
180    }
181
182    /// Take error
183    pub fn take(&mut self) -> Option<io::Error> {
184        self.0.take()
185    }
186
187    pub fn ack(self) -> ControlAck {
188        ControlAck {
189            frame: None,
190            disconnect: true,
191        }
192    }
193}
194
195#[derive(Debug)]
196pub struct GoAway(frame::GoAway);
197
198impl GoAway {
199    /// Returns error reference
200    pub fn frame(&self) -> &frame::GoAway {
201        &self.0
202    }
203
204    pub fn ack(self) -> ControlAck {
205        ControlAck {
206            frame: None,
207            disconnect: true,
208        }
209    }
210}