1use std::io;
2
3use crate::frame::Frame;
4use crate::{error, frame, stream::StreamRef};
5
6#[derive(Debug)]
7pub enum Control<E> {
8 Disconnect(Reason<E>),
10 Terminated(Terminated),
12}
13
14#[derive(Debug)]
15pub enum Reason<E> {
17 Error(Error<E>),
19 ProtocolError(ConnectionError),
21 GoAway(GoAway),
23 PeerGone(PeerGone),
25}
26
27#[derive(Clone, Debug)]
28pub struct ControlAck {
29 pub(crate) frame: Option<Frame>,
30}
31
32impl<E> Control<E> {
33 pub(super) fn error(err: E, stream: Option<&StreamRef>) -> Self {
35 Control::Disconnect(Reason::Error(Error::new(err, stream)))
36 }
37
38 pub(super) fn go_away(frm: frame::GoAway) -> Self {
40 Control::Disconnect(Reason::GoAway(GoAway(frm)))
41 }
42
43 pub(super) fn peer_gone(err: Option<io::Error>) -> Self {
45 Control::Disconnect(Reason::PeerGone(PeerGone(err)))
46 }
47
48 pub(super) fn proto_error(err: error::ConnectionError) -> Self {
50 Control::Disconnect(Reason::ProtocolError(ConnectionError::new(err)))
51 }
52
53 pub(super) fn terminated() -> Self {
54 Control::Terminated(Terminated)
55 }
56
57 pub fn ack(self) -> ControlAck {
59 match self {
60 Control::Disconnect(item) => item.ack(),
61 Control::Terminated(item) => item.ack(),
62 }
63 }
64}
65
66impl<E> Reason<E> {
67 pub fn ack(self) -> ControlAck {
69 match self {
70 Reason::Error(item) => item.ack(),
71 Reason::ProtocolError(item) => item.ack(),
72 Reason::GoAway(item) => item.ack(),
73 Reason::PeerGone(item) => item.ack(),
74 }
75 }
76}
77
78#[derive(Debug)]
80pub struct Error<E> {
81 err: E,
82 goaway: frame::GoAway,
83}
84
85impl<E> Error<E> {
86 fn new(err: E, stream: Option<&StreamRef>) -> Self {
87 let goaway = if let Some(stream) = stream {
88 frame::GoAway::new(frame::Reason::INTERNAL_ERROR).set_last_stream_id(stream.id())
89 } else {
90 frame::GoAway::new(frame::Reason::INTERNAL_ERROR)
91 };
92
93 Self { err, goaway }
94 }
95
96 #[inline]
97 pub fn get_ref(&self) -> &E {
99 &self.err
100 }
101
102 #[inline]
103 #[must_use]
104 pub fn reason(mut self, reason: frame::Reason) -> Self {
106 self.goaway = self.goaway.set_reason(reason);
107 self
108 }
109
110 #[inline]
111 pub fn ack(self) -> ControlAck {
113 ControlAck {
114 frame: Some(self.goaway.into()),
115 }
116 }
117}
118
119#[derive(Debug)]
121pub struct Terminated;
122
123impl Terminated {
124 #[inline]
125 pub fn ack(self) -> ControlAck {
127 ControlAck { frame: None }
128 }
129}
130
131#[derive(Debug)]
133pub struct ConnectionError {
134 err: error::ConnectionError,
135 frm: frame::GoAway,
136}
137
138impl ConnectionError {
139 pub fn new(err: error::ConnectionError) -> Self {
140 Self {
141 frm: err.to_goaway(),
142 err,
143 }
144 }
145
146 #[inline]
147 pub fn get_ref(&self) -> &error::ConnectionError {
149 &self.err
150 }
151
152 #[inline]
153 #[must_use]
154 pub fn reason(mut self, reason: frame::Reason) -> Self {
156 self.frm = self.frm.set_reason(reason);
157 self
158 }
159
160 #[inline]
161 pub fn ack(self) -> ControlAck {
163 ControlAck {
164 frame: Some(self.frm.into()),
165 }
166 }
167}
168
169#[derive(Debug)]
170pub struct PeerGone(pub(super) Option<io::Error>);
171
172impl PeerGone {
173 pub fn err(&self) -> Option<&io::Error> {
175 self.0.as_ref()
176 }
177
178 pub fn take(&mut self) -> Option<io::Error> {
180 self.0.take()
181 }
182
183 pub fn ack(self) -> ControlAck {
184 ControlAck { frame: None }
185 }
186}
187
188#[derive(Debug)]
189pub struct GoAway(frame::GoAway);
190
191impl GoAway {
192 pub fn frame(&self) -> &frame::GoAway {
194 &self.0
195 }
196
197 pub fn ack(self) -> ControlAck {
198 ControlAck { frame: None }
199 }
200}