1 use bytes::{BufMut, BytesMut};
2 use frame::{Error, Frame, FrameSize, Head, Kind, StreamId};
3 
4 #[derive(Debug, Clone, Default, Eq, PartialEq)]
5 pub struct Settings {
6     flags: SettingsFlags,
7     // Fields
8     header_table_size: Option<u32>,
9     enable_push: Option<u32>,
10     max_concurrent_streams: Option<u32>,
11     initial_window_size: Option<u32>,
12     max_frame_size: Option<u32>,
13     max_header_list_size: Option<u32>,
14 }
15 
16 /// An enum that lists all valid settings that can be sent in a SETTINGS
17 /// frame.
18 ///
19 /// Each setting has a value that is a 32 bit unsigned integer (6.5.1.).
20 #[derive(Debug)]
21 pub enum Setting {
22     HeaderTableSize(u32),
23     EnablePush(u32),
24     MaxConcurrentStreams(u32),
25     InitialWindowSize(u32),
26     MaxFrameSize(u32),
27     MaxHeaderListSize(u32),
28 }
29 
30 #[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
31 pub struct SettingsFlags(u8);
32 
33 const ACK: u8 = 0x1;
34 const ALL: u8 = ACK;
35 
36 /// The default value of SETTINGS_HEADER_TABLE_SIZE
37 pub const DEFAULT_SETTINGS_HEADER_TABLE_SIZE: usize = 4_096;
38 
39 /// The default value of SETTINGS_INITIAL_WINDOW_SIZE
40 pub const DEFAULT_INITIAL_WINDOW_SIZE: u32 = 65_535;
41 
42 /// The default value of MAX_FRAME_SIZE
43 pub const DEFAULT_MAX_FRAME_SIZE: FrameSize = 16_384;
44 
45 /// INITIAL_WINDOW_SIZE upper bound
46 pub const MAX_INITIAL_WINDOW_SIZE: usize = (1 << 31) - 1;
47 
48 /// MAX_FRAME_SIZE upper bound
49 pub const MAX_MAX_FRAME_SIZE: FrameSize = (1 << 24) - 1;
50 
51 // ===== impl Settings =====
52 
53 impl Settings {
ack() -> Settings54     pub fn ack() -> Settings {
55         Settings {
56             flags: SettingsFlags::ack(),
57             ..Settings::default()
58         }
59     }
60 
is_ack(&self) -> bool61     pub fn is_ack(&self) -> bool {
62         self.flags.is_ack()
63     }
64 
initial_window_size(&self) -> Option<u32>65     pub fn initial_window_size(&self) -> Option<u32> {
66         self.initial_window_size
67     }
68 
set_initial_window_size(&mut self, size: Option<u32>)69     pub fn set_initial_window_size(&mut self, size: Option<u32>) {
70         self.initial_window_size = size;
71     }
72 
max_concurrent_streams(&self) -> Option<u32>73     pub fn max_concurrent_streams(&self) -> Option<u32> {
74         self.max_concurrent_streams
75     }
76 
set_max_concurrent_streams(&mut self, max: Option<u32>)77     pub fn set_max_concurrent_streams(&mut self, max: Option<u32>) {
78         self.max_concurrent_streams = max;
79     }
80 
max_frame_size(&self) -> Option<u32>81     pub fn max_frame_size(&self) -> Option<u32> {
82         self.max_frame_size
83     }
84 
set_max_frame_size(&mut self, size: Option<u32>)85     pub fn set_max_frame_size(&mut self, size: Option<u32>) {
86         if let Some(val) = size {
87             assert!(DEFAULT_MAX_FRAME_SIZE <= val && val <= MAX_MAX_FRAME_SIZE);
88         }
89         self.max_frame_size = size;
90     }
91 
max_header_list_size(&self) -> Option<u32>92     pub fn max_header_list_size(&self) -> Option<u32> {
93         self.max_header_list_size
94     }
95 
set_max_header_list_size(&mut self, size: Option<u32>)96     pub fn set_max_header_list_size(&mut self, size: Option<u32>) {
97         self.max_header_list_size = size;
98     }
99 
is_push_enabled(&self) -> bool100     pub fn is_push_enabled(&self) -> bool {
101         self.enable_push.unwrap_or(1) != 0
102     }
103 
set_enable_push(&mut self, enable: bool)104     pub fn set_enable_push(&mut self, enable: bool) {
105         self.enable_push = Some(enable as u32);
106     }
107 
load(head: Head, payload: &[u8]) -> Result<Settings, Error>108     pub fn load(head: Head, payload: &[u8]) -> Result<Settings, Error> {
109         use self::Setting::*;
110 
111         debug_assert_eq!(head.kind(), ::frame::Kind::Settings);
112 
113         if !head.stream_id().is_zero() {
114             return Err(Error::InvalidStreamId);
115         }
116 
117         // Load the flag
118         let flag = SettingsFlags::load(head.flag());
119 
120         if flag.is_ack() {
121             // Ensure that the payload is empty
122             if payload.len() > 0 {
123                 return Err(Error::InvalidPayloadLength);
124             }
125 
126             // Return the ACK frame
127             return Ok(Settings::ack());
128         }
129 
130         // Ensure the payload length is correct, each setting is 6 bytes long.
131         if payload.len() % 6 != 0 {
132             debug!("invalid settings payload length; len={:?}", payload.len());
133             return Err(Error::InvalidPayloadAckSettings);
134         }
135 
136         let mut settings = Settings::default();
137         debug_assert!(!settings.flags.is_ack());
138 
139         for raw in payload.chunks(6) {
140             match Setting::load(raw) {
141                 Some(HeaderTableSize(val)) => {
142                     settings.header_table_size = Some(val);
143                 },
144                 Some(EnablePush(val)) => match val {
145                     0 | 1 => {
146                         settings.enable_push = Some(val);
147                     },
148                     _ => {
149                         return Err(Error::InvalidSettingValue);
150                     },
151                 },
152                 Some(MaxConcurrentStreams(val)) => {
153                     settings.max_concurrent_streams = Some(val);
154                 },
155                 Some(InitialWindowSize(val)) => if val as usize > MAX_INITIAL_WINDOW_SIZE {
156                     return Err(Error::InvalidSettingValue);
157                 } else {
158                     settings.initial_window_size = Some(val);
159                 },
160                 Some(MaxFrameSize(val)) => {
161                     if val < DEFAULT_MAX_FRAME_SIZE || val > MAX_MAX_FRAME_SIZE {
162                         return Err(Error::InvalidSettingValue);
163                     } else {
164                         settings.max_frame_size = Some(val);
165                     }
166                 },
167                 Some(MaxHeaderListSize(val)) => {
168                     settings.max_header_list_size = Some(val);
169                 },
170                 None => {},
171             }
172         }
173 
174         Ok(settings)
175     }
176 
payload_len(&self) -> usize177     fn payload_len(&self) -> usize {
178         let mut len = 0;
179         self.for_each(|_| len += 6);
180         len
181     }
182 
encode(&self, dst: &mut BytesMut)183     pub fn encode(&self, dst: &mut BytesMut) {
184         // Create & encode an appropriate frame head
185         let head = Head::new(Kind::Settings, self.flags.into(), StreamId::zero());
186         let payload_len = self.payload_len();
187 
188         trace!("encoding SETTINGS; len={}", payload_len);
189 
190         head.encode(payload_len, dst);
191 
192         // Encode the settings
193         self.for_each(|setting| {
194             trace!("encoding setting; val={:?}", setting);
195             setting.encode(dst)
196         });
197     }
198 
for_each<F: FnMut(Setting)>(&self, mut f: F)199     fn for_each<F: FnMut(Setting)>(&self, mut f: F) {
200         use self::Setting::*;
201 
202         if let Some(v) = self.header_table_size {
203             f(HeaderTableSize(v));
204         }
205 
206         if let Some(v) = self.enable_push {
207             f(EnablePush(v));
208         }
209 
210         if let Some(v) = self.max_concurrent_streams {
211             f(MaxConcurrentStreams(v));
212         }
213 
214         if let Some(v) = self.initial_window_size {
215             f(InitialWindowSize(v));
216         }
217 
218         if let Some(v) = self.max_frame_size {
219             f(MaxFrameSize(v));
220         }
221 
222         if let Some(v) = self.max_header_list_size {
223             f(MaxHeaderListSize(v));
224         }
225     }
226 }
227 
228 impl<T> From<Settings> for Frame<T> {
from(src: Settings) -> Frame<T>229     fn from(src: Settings) -> Frame<T> {
230         Frame::Settings(src)
231     }
232 }
233 
234 // ===== impl Setting =====
235 
236 impl Setting {
237     /// Creates a new `Setting` with the correct variant corresponding to the
238     /// given setting id, based on the settings IDs defined in section
239     /// 6.5.2.
from_id(id: u16, val: u32) -> Option<Setting>240     pub fn from_id(id: u16, val: u32) -> Option<Setting> {
241         use self::Setting::*;
242 
243         match id {
244             1 => Some(HeaderTableSize(val)),
245             2 => Some(EnablePush(val)),
246             3 => Some(MaxConcurrentStreams(val)),
247             4 => Some(InitialWindowSize(val)),
248             5 => Some(MaxFrameSize(val)),
249             6 => Some(MaxHeaderListSize(val)),
250             _ => None,
251         }
252     }
253 
254     /// Creates a new `Setting` by parsing the given buffer of 6 bytes, which
255     /// contains the raw byte representation of the setting, according to the
256     /// "SETTINGS format" defined in section 6.5.1.
257     ///
258     /// The `raw` parameter should have length at least 6 bytes, since the
259     /// length of the raw setting is exactly 6 bytes.
260     ///
261     /// # Panics
262     ///
263     /// If given a buffer shorter than 6 bytes, the function will panic.
load(raw: &[u8]) -> Option<Setting>264     fn load(raw: &[u8]) -> Option<Setting> {
265         let id: u16 = ((raw[0] as u16) << 8) | (raw[1] as u16);
266         let val: u32 = unpack_octets_4!(raw, 2, u32);
267 
268         Setting::from_id(id, val)
269     }
270 
encode(&self, dst: &mut BytesMut)271     fn encode(&self, dst: &mut BytesMut) {
272         use self::Setting::*;
273 
274         let (kind, val) = match *self {
275             HeaderTableSize(v) => (1, v),
276             EnablePush(v) => (2, v),
277             MaxConcurrentStreams(v) => (3, v),
278             InitialWindowSize(v) => (4, v),
279             MaxFrameSize(v) => (5, v),
280             MaxHeaderListSize(v) => (6, v),
281         };
282 
283         dst.put_u16_be(kind);
284         dst.put_u32_be(val);
285     }
286 }
287 
288 // ===== impl SettingsFlags =====
289 
290 impl SettingsFlags {
empty() -> SettingsFlags291     pub fn empty() -> SettingsFlags {
292         SettingsFlags(0)
293     }
294 
load(bits: u8) -> SettingsFlags295     pub fn load(bits: u8) -> SettingsFlags {
296         SettingsFlags(bits & ALL)
297     }
298 
ack() -> SettingsFlags299     pub fn ack() -> SettingsFlags {
300         SettingsFlags(ACK)
301     }
302 
is_ack(&self) -> bool303     pub fn is_ack(&self) -> bool {
304         self.0 & ACK == ACK
305     }
306 }
307 
308 impl From<SettingsFlags> for u8 {
from(src: SettingsFlags) -> u8309     fn from(src: SettingsFlags) -> u8 {
310         src.0
311     }
312 }
313