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 AppError(AppError<E>),
15 ConnectionError(ConnectionError),
17 GoAway(GoAway),
19 PeerGone(PeerGone),
21 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 pub(super) fn error(err: E) -> Self {
34 Control::AppError(AppError::new(err, None))
35 }
36
37 pub(super) fn app_error(err: E, stream: StreamRef) -> Self {
39 Control::AppError(AppError::new(err, Some(stream)))
40 }
41
42 pub(super) fn go_away(frm: frame::GoAway) -> Self {
44 Control::GoAway(GoAway(frm))
45 }
46
47 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 pub(super) fn proto_error(err: error::ConnectionError) -> Self {
58 Control::ConnectionError(ConnectionError::new(err))
59 }
60
61 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#[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 pub fn get_ref(&self) -> &E {
93 &self.err
94 }
95
96 #[inline]
97 pub fn reason(mut self, reason: Reason) -> Self {
99 self.reason = reason;
100 self
101 }
102
103 #[inline]
104 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#[derive(Debug)]
122pub struct Terminated;
123
124impl Terminated {
125 #[inline]
126 pub fn ack(self) -> ControlAck {
128 ControlAck {
129 frame: None,
130 disconnect: true,
131 }
132 }
133}
134
135#[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 pub fn get_ref(&self) -> &error::ConnectionError {
153 &self.err
154 }
155
156 #[inline]
157 pub fn reason(mut self, reason: Reason) -> Self {
159 self.frm = self.frm.set_reason(reason);
160 self
161 }
162
163 #[inline]
164 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 pub fn err(&self) -> Option<&io::Error> {
179 self.0.as_ref()
180 }
181
182 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 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}