1use std::{
6 cmp,
7 fmt,
8 ops::{
9 Deref,
10 RangeInclusive,
11 },
12};
13
14use bitflags::bitflags;
15use bytes::Bytes;
16
17use crate::{
18 constrained::*,
19 errors::{
20 Error,
21 InvalidHeader,
22 },
23};
24
25pub const WNDINC_MAX: u32 = 0x7FFFFFFF;
26pub const STREAMID_MAX: u32 = 0x7FFFFFFF;
27pub const LENGTH_MAX: u32 = 0x00FFFFFF;
28pub const ERROR_MAX: u32 = u32::MAX;
29
30constrained_num!(StreamID, u32, 0..=STREAMID_MAX, clamp, mask);
31constrained_num!(WndInc, u32, 0..=WNDINC_MAX, clamp, mask);
32constrained_num!(Length, u32, 0..=LENGTH_MAX, clamp);
33constrained_num!(ErrorCode, u32, 0..=ERROR_MAX);
34
35bitflags! {
36 #[derive(Default)]
37 pub struct Flags: u8 {
38 const FIN = 0b0001;
39 const SYN = 0b0010;
40 }
41}
42
43#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
44pub struct Header {
45 pub length: Length,
46 pub typ: HeaderType,
47 pub flags: Flags,
48 pub stream_id: StreamID,
49}
50
51#[derive(Debug, Eq, PartialEq, Clone)]
52pub struct Frame {
53 pub header: Header,
54 pub body: Body,
55}
56
57impl From<Body> for Frame {
58 fn from(mut other: Body) -> Self {
59 let typ = other.header_type();
60 other.clamp_len();
61 let length = Length::clamp(other.len() as u32);
62 Frame {
63 header: Header {
64 length,
65 typ,
66 ..Default::default()
67 },
68 body: other,
69 }
70 }
71}
72
73impl Frame {
74 pub fn is_fin(&self) -> bool {
75 self.header.flags.contains(Flags::FIN)
76 }
77 pub fn is_syn(&self) -> bool {
78 self.header.flags.contains(Flags::SYN)
79 }
80 pub fn fin(mut self) -> Frame {
81 self.header.flags.set(Flags::FIN, true);
82 self
83 }
84 pub fn syn(mut self) -> Frame {
85 self.header.flags.set(Flags::SYN, true);
86 self
87 }
88 pub fn stream_id(mut self, id: StreamID) -> Frame {
89 self.header.stream_id = id;
90 self
91 }
92
93 pub fn rst(stream_id: StreamID, error: Error) -> Frame {
94 let length = Length::clamp(4);
95 Frame {
96 header: Header {
97 length,
98 stream_id,
99 typ: HeaderType::Rst,
100 ..Default::default()
101 },
102 body: Body::Rst(error),
103 }
104 }
105 pub fn goaway(last_stream_id: StreamID, error: Error, mut message: Bytes) -> Frame {
106 let length = Length::clamp(message.len() as u32);
107 message = message.slice(..*length as usize);
108 Frame {
109 header: Header {
110 length,
111 typ: HeaderType::GoAway,
112 ..Default::default()
113 },
114 body: Body::GoAway {
115 last_stream_id,
116 error,
117 message,
118 },
119 }
120 }
121}
122
123#[derive(Clone, Copy, Debug, PartialEq, Eq)]
124pub enum HeaderType {
125 Rst,
126 Data,
127 WndInc,
128 GoAway,
129 Invalid(u8),
130}
131
132impl Default for HeaderType {
133 fn default() -> Self {
134 HeaderType::Invalid(255)
135 }
136}
137
138impl From<u8> for HeaderType {
139 fn from(other: u8) -> HeaderType {
140 match other {
141 0 => HeaderType::Rst,
142 1 => HeaderType::Data,
143 2 => HeaderType::WndInc,
144 3 => HeaderType::GoAway,
145 t => HeaderType::Invalid(t),
146 }
147 }
148}
149
150impl From<HeaderType> for u8 {
151 fn from(other: HeaderType) -> u8 {
152 match other {
153 HeaderType::Rst => 0,
154 HeaderType::Data => 1,
155 HeaderType::WndInc => 2,
156 HeaderType::GoAway => 3,
157 HeaderType::Invalid(t) => t,
158 }
159 }
160}
161
162#[derive(Debug, Clone, Eq, PartialEq)]
163pub enum Body {
164 Rst(Error),
165 Data(Bytes),
166 WndInc(WndInc),
167 GoAway {
168 last_stream_id: StreamID,
169 error: Error,
170 message: Bytes,
171 },
172 Invalid {
173 error: InvalidHeader,
174 body: Bytes,
175 },
176}
177
178impl Default for Body {
179 fn default() -> Self {
180 Body::Data(Default::default())
181 }
182}
183
184impl Body {
185 pub fn header_type(&self) -> HeaderType {
186 match self {
187 Body::Data(_) => HeaderType::Data,
188 Body::GoAway { .. } => HeaderType::GoAway,
189 Body::WndInc(_) => HeaderType::WndInc,
190 Body::Rst(_) => HeaderType::Rst,
191 Body::Invalid { .. } => HeaderType::Invalid(0xff),
192 }
193 }
194
195 pub fn len(&self) -> usize {
196 match self {
197 Body::Data(bs) => bs.len(),
198 Body::GoAway { .. } => 8,
199 Body::WndInc(_) => 4,
200 Body::Rst(_) => 4,
201 Body::Invalid { body, .. } => body.len(),
202 }
203 }
204
205 pub fn clamp_len(&mut self) {
206 match self {
207 Body::Data(bs) => *bs = bs.slice(0..cmp::min(LENGTH_MAX as usize, bs.len())),
208 Body::Invalid { body, .. } => {
209 *body = body.slice(0..cmp::min(LENGTH_MAX as usize, body.len()))
210 }
211 _ => {}
212 }
213 }
214}