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(ref 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 pub fn reason(mut self, reason: frame::Reason) -> Self {
105 self.goaway = self.goaway.set_reason(reason);
106 self
107 }
108
109 #[inline]
110 pub fn ack(self) -> ControlAck {
112 ControlAck {
113 frame: Some(self.goaway.into()),
114 }
115 }
116}
117
118#[derive(Debug)]
120pub struct Terminated;
121
122impl Terminated {
123 #[inline]
124 pub fn ack(self) -> ControlAck {
126 ControlAck { frame: None }
127 }
128}
129
130#[derive(Debug)]
132pub struct ConnectionError {
133 err: error::ConnectionError,
134 frm: frame::GoAway,
135}
136
137impl ConnectionError {
138 pub fn new(err: error::ConnectionError) -> Self {
139 Self {
140 frm: err.to_goaway(),
141 err,
142 }
143 }
144
145 #[inline]
146 pub fn get_ref(&self) -> &error::ConnectionError {
148 &self.err
149 }
150
151 #[inline]
152 pub fn reason(mut self, reason: frame::Reason) -> Self {
154 self.frm = self.frm.set_reason(reason);
155 self
156 }
157
158 #[inline]
159 pub fn ack(self) -> ControlAck {
161 ControlAck {
162 frame: Some(self.frm.into()),
163 }
164 }
165}
166
167#[derive(Debug)]
168pub struct PeerGone(pub(super) Option<io::Error>);
169
170impl PeerGone {
171 pub fn err(&self) -> Option<&io::Error> {
173 self.0.as_ref()
174 }
175
176 pub fn take(&mut self) -> Option<io::Error> {
178 self.0.take()
179 }
180
181 pub fn ack(self) -> ControlAck {
182 ControlAck { frame: None }
183 }
184}
185
186#[derive(Debug)]
187pub struct GoAway(frame::GoAway);
188
189impl GoAway {
190 pub fn frame(&self) -> &frame::GoAway {
192 &self.0
193 }
194
195 pub fn ack(self) -> ControlAck {
196 ControlAck { frame: None }
197 }
198}