solicit/http/frame/
mod.rs

1//! The module contains the implementation of HTTP/2 frames.
2
3use std::mem;
4
5use http::StreamId;
6
7/// A helper macro that unpacks a sequence of 4 bytes found in the buffer with
8/// the given identifier, starting at the given offset, into the given integer
9/// type. Obviously, the integer type should be able to support at least 4
10/// bytes.
11///
12/// # Examples
13///
14/// ```rust
15/// let buf: [u8; 4] = [0, 0, 0, 1];
16/// assert_eq!(1u32, unpack_octets_4!(buf, 0, u32));
17/// ```
18#[macro_escape]
19macro_rules! unpack_octets_4 {
20    ($buf:ident, $offset:expr, $tip:ty) => (
21        (($buf[$offset + 0] as $tip) << 24) |
22        (($buf[$offset + 1] as $tip) << 16) |
23        (($buf[$offset + 2] as $tip) <<  8) |
24        (($buf[$offset + 3] as $tip) <<  0)
25    );
26}
27
28pub mod data;
29pub mod headers;
30pub mod settings;
31
32/// Rexports related to the `DATA` frame.
33pub use self::data::{DataFlag, DataFrame};
34/// Rexports related to the `HEADERS` frame.
35pub use self::headers::{HeadersFlag, HeadersFrame};
36/// Rexports related to the `SETTINGS` frame.
37pub use self::settings::{SettingsFlag, SettingsFrame, HttpSetting};
38
39/// An alias for the 9-byte buffer that each HTTP/2 frame header must be stored
40/// in.
41pub type FrameHeaderBuffer = [u8; 9];
42/// An alias for the 4-tuple representing the components of each HTTP/2 frame
43/// header.
44pub type FrameHeader = (u32, u8, u8, u32);
45
46/// Deconstructs a `FrameHeader` into its corresponding 4 components,
47/// represented as a 4-tuple: `(length, frame_type, flags, stream_id)`.
48///
49/// The frame `type` and `flags` components are returned as their original
50/// octet representation, rather than reinterpreted.
51pub fn unpack_header(header: &FrameHeaderBuffer) -> FrameHeader {
52    let length: u32 =
53        ((header[0] as u32) << 16) |
54        ((header[1] as u32) <<  8) |
55        ((header[2] as u32) <<  0);
56    let frame_type = header[3];
57    let flags = header[4];
58    let stream_id: u32 = unpack_octets_4!(header, 5, u32);
59
60    (length, frame_type, flags, stream_id)
61}
62
63/// Constructs a buffer of 9 bytes that represents the given `FrameHeader`.
64pub fn pack_header(header: &FrameHeader) -> FrameHeaderBuffer {
65    let &(length, frame_type, flags, stream_id) = header;
66
67    [
68        (((length >> 16) & 0x000000FF) as u8),
69        (((length >>  8) & 0x000000FF) as u8),
70        (((length >>  0) & 0x000000FF) as u8),
71        frame_type,
72        flags,
73        (((stream_id >> 24) & 0x000000FF) as u8),
74        (((stream_id >> 16) & 0x000000FF) as u8),
75        (((stream_id >>  8) & 0x000000FF) as u8),
76        (((stream_id >>  0) & 0x000000FF) as u8),
77    ]
78}
79
80/// A helper function that parses the given payload, considering it padded.
81///
82/// This means that the first byte is the length of the padding with that many
83/// 0 bytes expected to follow the actual payload.
84///
85/// # Returns
86///
87/// A slice of the given payload where the actual one is found and the length
88/// of the padding.
89///
90/// If the padded payload is invalid (e.g. the length of the padding is equal
91/// to the total length), returns `None`.
92fn parse_padded_payload<'a>(payload: &'a [u8]) -> Option<(&'a [u8], u8)> {
93    if payload.len() == 0 {
94        // We make sure not to index the payload before we're sure how
95        // large the buffer is.
96        // If this is the case, the frame is invalid as no padding
97        // length can be extracted, even though the frame should be
98        // padded.
99        return None;
100    }
101    let pad_len = payload[0] as usize;
102    if pad_len >= payload.len() {
103        // This is invalid: the padding length MUST be less than the
104        // total frame size.
105        return None;
106    }
107
108    Some((&payload[1..payload.len() - pad_len], pad_len as u8))
109}
110
111/// A trait that all HTTP/2 frame header flags need to implement.
112pub trait Flag {
113    /// Returns a bit mask that represents the flag.
114    fn bitmask(&self) -> u8;
115}
116
117/// A trait that all HTTP/2 frame structs need to implement.
118pub trait Frame: Sized {
119    /// The type that represents the flags that the particular `Frame` can take.
120    /// This makes sure that only valid `Flag`s are used with each `Frame`.
121    type FlagType: Flag;
122
123    /// Creates a new `Frame` from the given `RawFrame` (i.e. header and
124    /// payload), if possible.
125    ///
126    /// # Returns
127    ///
128    /// `None` if a valid `Frame` cannot be constructed from the given
129    /// `RawFrame`. Some reasons why this may happen is a wrong frame type in
130    /// the header, a body that cannot be decoded according to the particular
131    /// frame's rules, etc.
132    ///
133    /// Otherwise, returns a newly constructed `Frame`.
134    fn from_raw(raw_frame: RawFrame) -> Option<Self>;
135
136    /// Tests if the given flag is set for the frame.
137    fn is_set(&self, flag: Self::FlagType) -> bool;
138    /// Returns the `StreamId` of the stream to which the frame is associated
139    fn get_stream_id(&self) -> StreamId;
140    /// Returns a `FrameHeader` based on the current state of the `Frame`.
141    fn get_header(&self) -> FrameHeader;
142
143    /// Sets the given flag for the frame.
144    fn set_flag(&mut self, flag: Self::FlagType);
145
146    /// Returns a `Vec` with the serialized representation of the frame.
147    fn serialize(&self) -> Vec<u8>;
148}
149
150/// A struct that defines the format of the raw HTTP/2 frame, i.e. the frame
151/// as it is read from the wire.
152///
153/// This format is defined in section 4.1. of the HTTP/2 spec.
154///
155/// The `RawFrame` struct simply stores the raw components of an HTTP/2 frame:
156/// its header and the payload as a sequence of bytes.
157///
158/// It does not try to interpret the payload bytes, nor do any validation in
159/// terms of its validity based on the frame type given in the header.
160/// It is simply a wrapper around the two parts of an HTTP/2 frame.
161#[derive(PartialEq)]
162#[derive(Debug)]
163#[derive(Clone)]
164pub struct RawFrame {
165    /// The raw frame representation, including both the raw header representation
166    /// (in the first 9 bytes), followed by the raw payload representation.
167    raw_content: Vec<u8>,
168}
169
170impl RawFrame {
171    /// Creates a new `RawFrame` with the given `FrameHeader`. The payload is
172    /// left empty.
173    pub fn new(header: FrameHeader) -> RawFrame {
174        RawFrame::with_payload(header, Vec::new())
175    }
176
177    /// Creates a new `RawFrame` with the given header and payload.
178    /// Does not do any validation to determine whether the frame is in a correct
179    /// state as constructed.
180    pub fn with_payload(header: FrameHeader, payload: Vec<u8>) -> RawFrame {
181        let mut raw = Vec::new();
182        raw.extend(pack_header(&header).into_iter().map(|x| *x));
183        raw.extend(payload);
184
185        RawFrame {
186            raw_content: raw,
187        }
188    }
189
190    /// Creates a new `RawFrame` by parsing the given buffer.
191    ///
192    /// # Returns
193    ///
194    /// A `RawFrame` instance constructed from the given buffer.
195    ///
196    /// If the buffer cannot be parsed into a frame, which includes the payload
197    /// section having a different length than what was found in the header,
198    /// `None` is returned.
199    pub fn from_buf(buf: &[u8]) -> Option<RawFrame> {
200        if buf.len() < 9 {
201            return None;
202        }
203        let header = unpack_header(unsafe {
204            assert!(buf.len() >= 9);
205            // We just asserted that this transmute is safe.
206            mem::transmute(buf.as_ptr())
207        });
208        let payload_len = header.0 as usize;
209
210        if buf[9..].len() != payload_len {
211            return None;
212        }
213
214        Some(RawFrame {
215            raw_content: buf.to_vec(),
216        })
217    }
218
219    /// Returns a `Vec` of bytes representing the serialized (on-the-wire)
220    /// representation of this raw frame.
221    pub fn serialize(&self) -> Vec<u8> {
222        self.raw_content.clone()
223    }
224
225    /// Returns a `FrameHeader` instance corresponding to the headers of the
226    /// `RawFrame`.
227    pub fn header(&self) -> FrameHeader {
228        unpack_header(unsafe {
229            assert!(self.raw_content.len() >= 9);
230            // We just asserted that this transmute is safe.
231            mem::transmute(self.raw_content.as_ptr())
232        })
233    }
234
235    /// Returns a slice representing the payload of the `RawFrame`.
236    pub fn payload(&self) -> &[u8] {
237        &self.raw_content[9..]
238    }
239}
240
241/// Provide a conversion into a `Vec`.
242impl Into<Vec<u8>> for RawFrame {
243    fn into(self) -> Vec<u8> { self.raw_content }
244}
245
246/// Provide a conversion from a `Vec`.
247///
248/// This conversion is unchecked and could cause the resulting `RawFrame` to be an
249/// invalid HTTP/2 frame.
250impl From<Vec<u8>> for RawFrame {
251    fn from(raw: Vec<u8>) -> RawFrame { RawFrame { raw_content: raw } }
252}
253
254#[cfg(test)]
255mod tests {
256    use super::{
257        unpack_header,
258        pack_header,
259        RawFrame,
260        FrameHeader,
261        Frame,
262    };
263
264    /// Tests that the `unpack_header` function correctly returns the
265    /// components of HTTP/2 frame headers.
266    #[test]
267    fn test_unpack_header() {
268        {
269            let header = [0; 9];
270            assert_eq!((0, 0, 0, 0), unpack_header(&header));
271        }
272        {
273            let header = [0, 0, 1, 2, 3, 0, 0, 0, 4];
274            assert_eq!((1, 2, 3, 4), unpack_header(&header));
275        }
276        {
277            let header = [0, 0, 1, 200, 100, 0, 0, 0, 4];
278            assert_eq!((1, 200, 100, 4), unpack_header(&header));
279        }
280        {
281            let header = [0, 0, 1, 0, 0, 0, 0, 0, 0];
282            assert_eq!((1, 0, 0, 0), unpack_header(&header));
283        }
284        {
285            let header = [0, 1, 0, 0, 0, 0, 0, 0, 0];
286            assert_eq!((256, 0, 0, 0), unpack_header(&header));
287        }
288        {
289            let header = [1, 0, 0, 0, 0, 0, 0, 0, 0];
290            assert_eq!((256 * 256, 0, 0, 0), unpack_header(&header));
291        }
292        {
293            let header = [0, 0, 0, 0, 0, 0, 0, 0, 1];
294            assert_eq!((0, 0, 0, 1), unpack_header(&header));
295        }
296        {
297            let header = [0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 1];
298            assert_eq!(((1 << 24) - 1, 0, 0, 1), unpack_header(&header));
299        }
300        {
301            let header = [0xFF, 0xFF, 0xFF, 0, 0, 1, 1, 1, 1];
302            assert_eq!(
303                ((1 << 24) - 1, 0, 0, 1 + (1 << 8) + (1 << 16) + (1 << 24)),
304                unpack_header(&header));
305        }
306    }
307
308    /// Tests that the `pack_header` function correctly returns the buffer
309    /// corresponding to components of HTTP/2 frame headers.
310    #[test]
311    fn test_pack_header() {
312        {
313            let header = [0; 9];
314            assert_eq!(pack_header(&(0, 0, 0, 0)), header);
315        }
316        {
317            let header = [0, 0, 1, 2, 3, 0, 0, 0, 4];
318            assert_eq!(pack_header(&(1, 2, 3, 4)), header);
319        }
320        {
321            let header = [0, 0, 1, 200, 100, 0, 0, 0, 4];
322            assert_eq!(pack_header(&(1, 200, 100, 4)), header);
323        }
324        {
325            let header = [0, 0, 1, 0, 0, 0, 0, 0, 0];
326            assert_eq!(pack_header(&(1, 0, 0, 0)), header);
327        }
328        {
329            let header = [0, 1, 0, 0, 0, 0, 0, 0, 0];
330            assert_eq!(pack_header(&(256, 0, 0, 0)), header);
331        }
332        {
333            let header = [1, 0, 0, 0, 0, 0, 0, 0, 0];
334            assert_eq!(pack_header(&(256 * 256, 0, 0, 0)), header);
335        }
336        {
337            let header = [0, 0, 0, 0, 0, 0, 0, 0, 1];
338            assert_eq!(pack_header(&(0, 0, 0, 1)), header);
339        }
340        {
341            let header = [0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 1];
342            assert_eq!(pack_header(&((1 << 24) - 1, 0, 0, 1)), header);
343        }
344        {
345            let header = [0xFF, 0xFF, 0xFF, 0, 0, 1, 1, 1, 1];
346            let header_components = (
347                (1 << 24) - 1, 0, 0, 1 + (1 << 8) + (1 << 16) + (1 << 24)
348            );
349            assert_eq!(pack_header(&header_components), header);
350        }
351    }
352
353    /// Builds a test frame of the given type with the given header and
354    /// payload, by using the `Frame::from_raw` method.
355    pub fn build_test_frame<F: Frame>(header: &FrameHeader, payload: &[u8]) -> F {
356        let raw = RawFrame::with_payload(header.clone(), payload.to_vec());
357        Frame::from_raw(raw).unwrap()
358    }
359
360    /// Builds a `Vec` containing the given data as a padded HTTP/2 frame.
361    ///
362    /// It first places the length of the padding, followed by the data,
363    /// followed by `pad_len` zero bytes.
364    pub fn build_padded_frame_payload(data: &[u8], pad_len: u8) -> Vec<u8> {
365        let sz = 1 + data.len() + pad_len as usize;
366        let mut payload: Vec<u8> = Vec::with_capacity(sz);
367        payload.push(pad_len);
368        payload.extend(data.to_vec().into_iter());
369        for _ in 0..pad_len { payload.push(0); }
370
371        payload
372    }
373
374    /// Tests that the `RawFrame::with_payload` method correctly constructs a
375    /// `RawFrame` from the given parts.
376    #[test]
377    fn test_raw_frame_with_payload() {
378        // Correct frame
379        {
380            let data = b"123";
381            let header = (data.len() as u32, 0x1, 0, 1);
382
383            let raw = RawFrame::with_payload(header, data.to_vec());
384
385            assert_eq!(raw.header(), header);
386            assert_eq!(raw.payload(), data)
387        }
388        // Correct frame with trailing data
389        {
390            let data = b"123456";
391            let header = (3, 0x1, 0, 1);
392
393            let raw = RawFrame::with_payload(header, data.to_vec());
394
395            // No validation of whether the parts form a correct frame
396            assert_eq!(raw.header(), header);
397            assert_eq!(raw.payload(), data)
398        }
399        // Missing payload chunk
400        {
401            let data = b"123";
402            let header = (6, 0x1, 0, 1);
403
404            let raw = RawFrame::with_payload(header, data.to_vec());
405
406            // No validation of whether the parts form a correct frame
407            assert_eq!(raw.header(), header);
408            assert_eq!(raw.payload(), data)
409        }
410    }
411
412    /// Tests that the `RawFrame::from_buf` method correctly constructs a
413    /// `RawFrame` from a given buffer.
414    #[test]
415    fn test_raw_frame_from_buffer() {
416        // Correct frame
417        {
418            let data = b"123";
419            let header = (data.len() as u32, 0x1, 0, 1);
420            let buf = {
421                let mut buf = Vec::new();
422                buf.extend(pack_header(&header).to_vec().into_iter());
423                buf.extend(data.to_vec().into_iter());
424                buf
425            };
426
427            let raw = RawFrame::from_buf(&buf).unwrap();
428
429            assert_eq!(raw.header(), header);
430            assert_eq!(raw.payload(), data)
431        }
432        // Correct frame with trailing data
433        {
434            let data = b"123";
435            let header = (data.len() as u32, 0x1, 0, 1);
436            let buf = {
437                let mut buf = Vec::new();
438                buf.extend(pack_header(&header).to_vec().into_iter());
439                buf.extend(data.to_vec().into_iter());
440                buf.extend(vec![1, 2, 3, 4, 5].into_iter());
441                buf
442            };
443
444            assert!(RawFrame::from_buf(&buf).is_none());
445        }
446        // Missing payload chunk
447        {
448            let data = b"123";
449            let header = (data.len() as u32, 0x1, 0, 1);
450            let buf = {
451                let mut buf = Vec::new();
452                buf.extend(pack_header(&header).to_vec().into_iter());
453                buf.extend(data[..2].to_vec().into_iter());
454                buf
455            };
456
457            assert!(RawFrame::from_buf(&buf).is_none());
458        }
459        // Missing header chunk
460        {
461            let header = (0, 0x1, 0, 1);
462            let buf = {
463                let mut buf = Vec::new();
464                buf.extend(pack_header(&header)[..5].to_vec().into_iter());
465                buf
466            };
467
468            assert!(RawFrame::from_buf(&buf).is_none());
469        }
470        // Completely empty buffer
471        {
472            assert!(RawFrame::from_buf(&[]).is_none());
473        }
474    }
475
476    /// Tests that constructing a `RawFrame` from a `Vec<u8>` by using the `From<Vec<u8>>`
477    /// trait implementation works as expected.
478    #[test]
479    fn test_raw_frame_from_vec_buffer_unchecked() {
480        // Correct frame
481        {
482            let data = b"123";
483            let header = (data.len() as u32, 0x1, 0, 1);
484            let buf = {
485                let mut buf = Vec::new();
486                buf.extend(pack_header(&header).to_vec().into_iter());
487                buf.extend(data.to_vec().into_iter());
488                buf
489            };
490            let buf_clone = buf.clone();
491
492            let raw = RawFrame::from(buf);
493
494            assert_eq!(raw.header(), header);
495            assert_eq!(raw.payload(), data);
496            assert_eq!(raw.serialize(), buf_clone);
497        }
498        // Correct frame with trailing data
499        {
500            let data = b"123";
501            let header = (data.len() as u32, 0x1, 0, 1);
502            let buf = {
503                let mut buf = Vec::new();
504                buf.extend(pack_header(&header).to_vec().into_iter());
505                buf.extend(data.to_vec().into_iter());
506                buf.extend(b"12345".to_vec().into_iter());
507                buf
508            };
509            let buf_clone = buf.clone();
510
511            let raw = RawFrame::from(buf);
512
513            assert_eq!(raw.header(), header);
514            assert_eq!(raw.payload(), b"12312345");
515            assert_eq!(raw.serialize(), buf_clone);
516        }
517        // Missing payload chunk
518        {
519            let data = b"123";
520            let header = (data.len() as u32, 0x1, 0, 1);
521            let buf = {
522                let mut buf = Vec::new();
523                buf.extend(pack_header(&header).to_vec().into_iter());
524                buf.extend(data[..2].to_vec().into_iter());
525                buf
526            };
527            let buf_clone = buf.clone();
528
529            let raw = RawFrame::from(buf);
530
531            assert_eq!(raw.header(), header);
532            assert_eq!(raw.payload(), b"12");
533            assert_eq!(raw.serialize(), buf_clone);
534        }
535        // Missing header chunk
536        {
537            let header = (0, 0x1, 0, 1);
538            let buf = {
539                let mut buf = Vec::new();
540                buf.extend(pack_header(&header)[..5].to_vec().into_iter());
541                buf
542            };
543            let buf_clone = buf.clone();
544
545            let raw = RawFrame::from(buf);
546
547            assert_eq!(raw.serialize(), buf_clone);
548        }
549        // Completely empty buffer
550        {
551            assert_eq!(RawFrame::from(vec![]).serialize(), &[]);
552        }
553    }
554
555    /// Tests that the `RawFrame::serialize` method correctly serializes a
556    /// `RawFrame`.
557    #[test]
558    fn test_raw_frame_serialize() {
559        let data = b"123";
560        let header = (data.len() as u32, 0x1, 0, 1);
561        let buf = {
562            let mut buf = Vec::new();
563            buf.extend(pack_header(&header).to_vec().into_iter());
564            buf.extend(data.to_vec().into_iter());
565            buf
566        };
567        let raw = RawFrame::from_buf(&buf).unwrap();
568
569        assert_eq!(raw.serialize(), buf);
570    }
571
572    /// Tests that converting a `RawFrame` into a `Vec` works correctly.
573    #[test]
574    fn test_raw_frame_into_vec() {
575        let data = b"123";
576        let header = (data.len() as u32, 0x1, 0, 1);
577        let buf = {
578            let mut buf = Vec::new();
579            buf.extend(pack_header(&header).to_vec().into_iter());
580            buf.extend(data.to_vec().into_iter());
581            buf
582        };
583        let raw = RawFrame::from_buf(&buf).unwrap();
584
585        let serialized = raw.serialize();
586        let vec: Vec<_> = raw.into();
587        // The vector is equivalent to the original buffer?
588        assert_eq!(vec, buf);
589        // The vector and the serialized representation are also equivalent
590        assert_eq!(vec, serialized);
591    }
592}