solicit/http/
connection.rs

1//! The module contains the implementation of an HTTP/2 connection.
2//!
3//! This provides an API to read and write raw HTTP/2 frames, as well as a way to hook into
4//! higher-level events arising on an HTTP/2 connection, such as the receipt of headers on a
5//! particular stream or a new data chunk.
6//!
7//! The `SendFrame` and `ReceiveFrame` traits are the API to sending and receiving frames off of an
8//! HTTP/2 connection. The module includes default implementations of those traits for `io::Write`
9//! and `solicit::http::transport::TransportStream` types.
10//!
11//! The `HttpConnection` struct builds on top of these traits and provides an API for sending
12//! messages of a higher level to the peer (such as writing data or headers, while automatically
13//! handling the framing and header encoding), as well as for handling incoming events of that
14//! type. The `Session` trait is the bridge between the connection layer (i.e. the
15//! `HttpConnection`) and the higher layers that handle these events and pass them on to the
16//! application.
17
18use std::io;
19use std::borrow::Cow;
20use std::borrow::Borrow;
21
22use http::{
23    Header,
24    StreamId,
25    HttpError,
26    HttpResult,
27    HttpScheme,
28};
29use http::priority::DataPrioritizer;
30use http::session::Session;
31use http::transport::TransportStream;
32use http::frame::{
33    Frame,
34    RawFrame,
35    DataFrame,
36    DataFlag,
37    HeadersFrame,
38    HeadersFlag,
39    SettingsFrame,
40    unpack_header,
41};
42use hpack;
43
44/// An enum representing all frame variants that can be returned by an
45/// `HttpConnection`.
46///
47/// The variants wrap the appropriate `Frame` implementation.
48#[derive(PartialEq)]
49#[derive(Debug)]
50#[derive(Clone)]
51pub enum HttpFrame {
52    DataFrame(DataFrame),
53    HeadersFrame(HeadersFrame),
54    SettingsFrame(SettingsFrame),
55    UnknownFrame(RawFrame),
56}
57
58impl HttpFrame {
59    pub fn from_raw(raw_frame: RawFrame) -> HttpResult<HttpFrame> {
60        let frame = match raw_frame.header().1 {
61            0x0 => HttpFrame::DataFrame(try!(HttpFrame::parse_frame(raw_frame))),
62            0x1 => HttpFrame::HeadersFrame(try!(HttpFrame::parse_frame(raw_frame))),
63            0x4 => HttpFrame::SettingsFrame(try!(HttpFrame::parse_frame(raw_frame))),
64            _ => HttpFrame::UnknownFrame(raw_frame),
65        };
66
67        Ok(frame)
68    }
69
70    /// A helper method that parses the given `RawFrame` into the given `Frame`
71    /// implementation.
72    ///
73    /// # Returns
74    ///
75    /// Failing to decode the given `Frame` from the `raw_frame`, an
76    /// `HttpError::InvalidFrame` error is returned.
77    #[inline]
78    fn parse_frame<F: Frame>(raw_frame: RawFrame) -> HttpResult<F> {
79        // TODO: The reason behind being unable to decode the frame should be
80        //       extracted to allow an appropriate connection-level action to be
81        //       taken (e.g. responding with a PROTOCOL_ERROR).
82        Frame::from_raw(raw_frame).ok_or(HttpError::InvalidFrame)
83    }
84}
85
86/// The enum represents the success status of the operation of sending a next data chunk on an
87/// HTTP/2 connection.
88#[derive(Clone, Copy, PartialEq, Debug)]
89pub enum SendStatus {
90    /// Indicates that a DATA frame was successfully sent
91    Sent,
92    /// Indicates that nothing was sent, but that no errors occurred.
93    ///
94    /// This is the case when none of the streams had any data to write.
95    Nothing,
96}
97
98/// The struct implements the HTTP/2 connection level logic.
99///
100/// This means that the struct is a bridge between the low level raw frame reads/writes (i.e. what
101/// the `SendFrame` and `ReceiveFrame` traits do) and the higher session-level logic.
102///
103/// Therefore, it provides an API that exposes higher-level write operations, such as writing
104/// headers or data, that take care of all the underlying frame construction that is required.
105///
106/// Similarly, it provides an API for handling events that arise from receiving frames, without
107/// requiring the higher level to directly look at the frames themselves, rather only the semantic
108/// content within the frames.
109pub struct HttpConnection<S, R> where S: SendFrame, R: ReceiveFrame {
110    /// The instance handling the reading of frames.
111    pub receiver: R,
112    /// The instance handling the writing of frames.
113    pub sender: S,
114    /// HPACK decoder used to decode incoming headers before passing them on to the session.
115    decoder: hpack::Decoder<'static>,
116    /// The HPACK encoder used to encode headers before sending them on this connection.
117    encoder: hpack::Encoder<'static>,
118    /// The scheme of the connection
119    pub scheme: HttpScheme,
120}
121
122/// A trait that should be implemented by types that can provide the functionality
123/// of sending HTTP/2 frames.
124pub trait SendFrame {
125    /// Sends the given raw frame.
126    fn send_raw_frame(&mut self, frame: RawFrame) -> HttpResult<()>;
127    /// Sends the given concrete frame.
128    ///
129    /// A default implementation based on the `send_raw_frame` method is provided.
130    fn send_frame<F: Frame>(&mut self, frame: F) -> HttpResult<()> {
131        self.send_raw_frame(RawFrame::from(frame.serialize()))
132    }
133}
134
135/// A blanket implementation of `SendFrame` is possible for any type that is also an
136/// `io::Write`.
137impl<W> SendFrame for W where W: io::Write {
138    #[inline]
139    fn send_frame<F: Frame>(&mut self, frame: F) -> HttpResult<()> {
140        try!(self.write_all(&frame.serialize()));
141        Ok(())
142    }
143
144    #[inline]
145    fn send_raw_frame(&mut self, frame: RawFrame) -> HttpResult<()> {
146        let serialized: Vec<u8> = frame.into();
147        try!(self.write_all(&serialized));
148        Ok(())
149    }
150}
151
152/// A trait that should be implemented by types that can provide the functionality
153/// of receiving HTTP/2 frames.
154pub trait ReceiveFrame {
155    /// Return a new `HttpFrame` instance. Unknown frames can be wrapped in the
156    /// `HttpFrame::UnknownFrame` variant (i.e. their `RawFrame` representation).
157    fn recv_frame(&mut self) -> HttpResult<HttpFrame>;
158}
159
160/// A blanket implementation of the trait for `TransportStream`s.
161impl<TS> ReceiveFrame for TS where TS: TransportStream {
162    fn recv_frame(&mut self) -> HttpResult<HttpFrame> {
163        // A helper function that reads the header of an HTTP/2 frame.
164        // Simply reads the next 9 octets (and no more than 9).
165        let read_header_bytes = |stream: &mut TS| -> HttpResult<[u8; 9]> {
166            let mut buf = [0; 9];
167            try!(TransportStream::read_exact(stream, &mut buf));
168
169            Ok(buf)
170        };
171        // A helper function that reads the payload of a frame with the given length.
172        // Reads exactly the length of the frame from the given stream.
173        let read_payload = |stream: &mut TS, len: u32| -> HttpResult<Vec<u8>> {
174            debug!("Trying to read {} bytes of frame payload", len);
175            let length = len as usize;
176            let mut buf: Vec<u8> = Vec::with_capacity(length);
177            // This is completely safe since we *just* allocated the vector with
178            // the same capacity.
179            unsafe { buf.set_len(length); }
180            try!(TransportStream::read_exact(stream, &mut buf));
181
182            Ok(buf)
183        };
184
185        let header = unpack_header(&try!(read_header_bytes(self)));
186        debug!("Received frame header {:?}", header);
187
188        let payload = try!(read_payload(self, header.0));
189        let raw_frame = RawFrame::with_payload(header, payload);
190
191        // TODO: The reason behind being unable to decode the frame should be
192        //       extracted to allow an appropriate connection-level action to be
193        //       taken (e.g. responding with a PROTOCOL_ERROR).
194        let frame = try!(HttpFrame::from_raw(raw_frame));
195        Ok(frame)
196    }
197}
198
199/// The struct represents a chunk of data that should be sent to the peer on a particular stream.
200pub struct DataChunk<'a> {
201    /// The data that should be sent.
202    pub data: Cow<'a, [u8]>,
203    /// The ID of the stream on which the data should be sent.
204    pub stream_id: StreamId,
205    /// Whether the data chunk will also end the stream.
206    pub end_stream: EndStream,
207}
208
209impl<'a> DataChunk<'a> {
210    /// Creates a new `DataChunk`.
211    ///
212    /// **Note:** `IntoCow` is unstable and there's no implementation of `Into<Cow<'a, [u8]>>` for
213    /// the fundamental types, making this a bit of a clunky API. Once such an `Into` impl is
214    /// added, this can be made generic over the trait for some ergonomic improvements.
215    pub fn new(data: Cow<'a, [u8]>, stream_id: StreamId, end_stream: EndStream) -> DataChunk<'a> {
216        DataChunk {
217            data: data,
218            stream_id: stream_id,
219            end_stream: end_stream,
220        }
221    }
222
223    /// Creates a new `DataChunk` from a borrowed slice. This method should become obsolete if we
224    /// can take an `Into<Cow<_, _>>` without using unstable features.
225    pub fn new_borrowed<D: Borrow<&'a [u8]>>(data: D, stream_id: StreamId, end_stream: EndStream)
226            -> DataChunk<'a> {
227        DataChunk {
228            data: Cow::Borrowed(data.borrow()),
229            stream_id: stream_id,
230            end_stream: end_stream,
231        }
232    }
233}
234
235/// An enum indicating whether the `HttpConnection` send operation should end the stream.
236#[derive(Clone, Copy, PartialEq, Debug)]
237pub enum EndStream {
238    /// The stream should be closed
239    Yes,
240    /// The stream should still be kept open
241    No,
242}
243
244impl<S, R> HttpConnection<S, R> where S: SendFrame, R: ReceiveFrame {
245    /// Creates a new `HttpConnection` that will use the given sender and receiver instances
246    /// for writing and reading frames, respectively.
247    pub fn new(sender: S, receiver: R, scheme: HttpScheme) -> HttpConnection<S, R> {
248        HttpConnection {
249            receiver: receiver,
250            sender: sender,
251            scheme: scheme,
252            decoder: hpack::Decoder::new(),
253            encoder: hpack::Encoder::new(),
254        }
255    }
256
257    /// Creates a new `HttpConnection` that will use the given stream as its
258    /// underlying transport layer.
259    ///
260    /// This constructor is provided as a convenience when the underlying IO of the
261    /// HTTP/2 connection should be based on the `TransportStream` interface.
262    ///
263    /// The scheme of the connection is also provided.
264    pub fn with_stream<TS>(stream: TS, scheme: HttpScheme) -> HttpConnection<TS, TS>
265            where TS: TransportStream {
266        let sender = stream.try_split().unwrap();
267        let receiver = stream;
268        HttpConnection::new(sender, receiver, scheme)
269    }
270
271    /// Sends the given frame to the peer.
272    ///
273    /// # Returns
274    ///
275    /// Any IO errors raised by the underlying transport layer are wrapped in a
276    /// `HttpError::IoError` variant and propagated upwards.
277    ///
278    /// If the frame is successfully written, returns a unit Ok (`Ok(())`).
279    #[inline]
280    fn send_frame<F: Frame>(&mut self, frame: F) -> HttpResult<()> {
281        debug!("Sending frame ... {:?}", frame.get_header());
282        self.sender.send_frame(frame)
283    }
284
285    /// Reads a new frame from the transport layer.
286    ///
287    /// # Returns
288    ///
289    /// Any IO errors raised by the underlying transport layer are wrapped in a
290    /// `HttpError::IoError` variant and propagated upwards.
291    ///
292    /// If the frame type is unknown the `RawFrame` is wrapped into a
293    /// `HttpFrame::UnknownFrame` variant and returned.
294    ///
295    /// If the frame type is recognized, but the frame cannot be successfully
296    /// decoded, the `HttpError::InvalidFrame` variant is returned. For now,
297    /// invalid frames are not further handled by informing the peer (e.g.
298    /// sending PROTOCOL_ERROR) nor can the exact reason behind failing to
299    /// decode the frame be extracted.
300    ///
301    /// If a frame is successfully read and parsed, returns the frame wrapped
302    /// in the appropriate variant of the `HttpFrame` enum.
303    #[inline]
304    fn recv_frame(&mut self) -> HttpResult<HttpFrame> {
305        self.receiver.recv_frame()
306    }
307
308    /// A helper function that inserts the frames required to send the given headers onto the
309    /// `SendFrame` stream.
310    ///
311    /// The `HttpConnection` performs the HPACK encoding of the header block using an internal
312    /// encoder.
313    ///
314    /// # Parameters
315    ///
316    /// - `headers` - a headers list that should be sent.
317    /// - `stream_id` - the ID of the stream on which the headers will be sent. The connection
318    ///   performs no checks as to whether the stream is a valid identifier.
319    /// - `end_stream` - whether the stream should be closed from the peer's side immediately
320    ///   after sending the headers
321    pub fn send_headers<H: Into<Vec<Header>>>(&mut self,
322                                              headers: H,
323                                              stream_id: StreamId,
324                                              end_stream: EndStream) -> HttpResult<()> {
325        self.send_headers_inner(headers.into(), stream_id, end_stream)
326    }
327
328    /// A private helper method: the non-generic implementation of the `send_headers` method.
329    fn send_headers_inner(&mut self,
330                          headers: Vec<Header>,
331                          stream_id: StreamId,
332                          end_stream: EndStream) -> HttpResult<()> {
333        let headers_fragment = self.encoder.encode(&headers);
334        // For now, sending header fragments larger than 16kB is not supported
335        // (i.e. the encoded representation cannot be split into CONTINUATION
336        // frames).
337        let mut frame = HeadersFrame::new(headers_fragment, stream_id);
338        frame.set_flag(HeadersFlag::EndHeaders);
339
340        if end_stream == EndStream::Yes {
341            frame.set_flag(HeadersFlag::EndStream);
342        }
343
344        self.send_frame(frame)
345    }
346
347    /// A helper function that inserts a frame representing the given data into the `SendFrame`
348    /// stream.
349    ///
350    /// The `HttpConnection` itself does not track the flow control window and will happily send
351    /// data that exceeds a particular stream's or the connection's flow control window size.
352    ///
353    /// # Parameters
354    ///
355    /// - `data` - the data that should be sent on the connection
356    /// - `stream_id` - the ID of the stream on which the data will be sent
357    /// - `end_stream` - whether the stream should be closed from the peer's side immediately after
358    ///   sending the data (i.e. the last data frame closes the stream).
359    pub fn send_data<'a>(&mut self,
360                         chunk: DataChunk<'a>) -> HttpResult<()> {
361        let DataChunk { data, stream_id, end_stream } = chunk;
362        self.send_data_inner(data.into_owned(), stream_id, end_stream)
363    }
364
365    /// A private helepr method: the non-generic implementation of the `send_data` method.
366    fn send_data_inner(&mut self, data: Vec<u8>, stream_id: StreamId, end_stream: EndStream)
367            -> HttpResult<()>{
368        // TODO Validate that the given data can fit into the maximum frame size allowed by the
369        //      current settings.
370        let mut frame = DataFrame::new(stream_id);
371        frame.data.extend(data);
372        if end_stream == EndStream::Yes {
373            frame.set_flag(DataFlag::EndStream);
374        }
375
376        self.send_frame(frame)
377    }
378
379    /// Sends the chunk of data provided by the given `DataPrioritizer`.
380    ///
381    /// # Returns
382    ///
383    /// Returns the status of the operation. If the provider does not currently have any data that
384    /// could be sent, returns `SendStatus::Nothing`. If any data is sent, returns
385    /// `SendStatus::Sent`.
386    pub fn send_next_data<P: DataPrioritizer>(&mut self, prioritizer: &mut P)
387            -> HttpResult<SendStatus> {
388        let chunk = try!(prioritizer.get_next_chunk());
389        match chunk {
390            None => Ok(SendStatus::Nothing),
391            Some(chunk) => {
392                try!(self.send_data(chunk));
393                Ok(SendStatus::Sent)
394            },
395        }
396    }
397    /// The method processes the next incoming frame, expecting it to be a SETTINGS frame.
398    /// Additionally, the frame cannot be an ACK settings frame, but rather it should contain the
399    /// peer's settings.
400    ///
401    /// The method can be used when the receipt of the peer's preface needs to be asserted.
402    ///
403    /// If the received frame is not a SETTINGS frame, an `HttpError::UnableToConnect` variant is
404    /// returned. (TODO: Change this variant's name, as it is a byproduct of this method's legacy)
405    pub fn expect_settings<Sess: Session>(&mut self, session: &mut Sess) -> HttpResult<()> {
406        let frame = self.recv_frame();
407        match frame {
408            Ok(HttpFrame::SettingsFrame(ref settings)) if !settings.is_ack() => {
409                debug!("Correctly received a SETTINGS frame from the server");
410            },
411            // Wrong frame received...
412            Ok(_) => return Err(HttpError::UnableToConnect),
413            // Already an error -- propagate that.
414            Err(e) => return Err(e),
415        };
416        try!(self.handle_frame(frame.unwrap(), session));
417        Ok(())
418    }
419
420    /// Handles the next frame incoming on the `ReceiveFrame` instance.
421    ///
422    /// The `HttpConnection` takes care of parsing the frame and extracting the semantics behind it
423    /// and passes this on to the higher level by invoking (possibly multiple) callbacks on the
424    /// given `Session` instance. For information on which events can be passed to the session,
425    /// check out the `Session` trait.
426    ///
427    /// If the handling is successful, a unit `Ok` is returned; all HTTP and IO errors are
428    /// propagated.
429    pub fn handle_next_frame<Sess: Session>(&mut self, session: &mut Sess) -> HttpResult<()> {
430        debug!("Waiting for frame...");
431        let frame = match self.recv_frame() {
432            Ok(frame) => frame,
433            Err(e) => {
434                debug!("Encountered an HTTP/2 error, stopping.");
435                return Err(e);
436            },
437        };
438
439        self.handle_frame(frame, session)
440    }
441
442    /// Private helper method that actually handles a received frame.
443    fn handle_frame<Sess: Session>(&mut self, frame: HttpFrame, session: &mut Sess)
444            -> HttpResult<()> {
445        match frame {
446            HttpFrame::DataFrame(frame) => {
447                debug!("Data frame received");
448                self.handle_data_frame(frame, session)
449            },
450            HttpFrame::HeadersFrame(frame) => {
451                debug!("Headers frame received");
452                self.handle_headers_frame(frame, session)
453            },
454            HttpFrame::SettingsFrame(frame) => {
455                debug!("Settings frame received");
456                self.handle_settings_frame::<Sess>(frame, session)
457            },
458            HttpFrame::UnknownFrame(_) => {
459                debug!("Unknown frame received");
460                // We simply drop any unknown frames...
461                // TODO Signal this to the session so that a hook is available
462                //      for implementing frame-level protocol extensions.
463                Ok(())
464            },
465        }
466    }
467
468    /// Private helper method that handles a received `DataFrame`.
469    fn handle_data_frame<Sess: Session>(&mut self, frame: DataFrame, session: &mut Sess)
470            -> HttpResult<()> {
471        session.new_data_chunk(frame.get_stream_id(), &frame.data);
472
473        if frame.is_set(DataFlag::EndStream) {
474            debug!("End of stream {}", frame.get_stream_id());
475            session.end_of_stream(frame.get_stream_id())
476        }
477
478        Ok(())
479    }
480
481    /// Private helper method that handles a received `HeadersFrame`.
482    fn handle_headers_frame<Sess: Session>(&mut self, frame: HeadersFrame, session: &mut Sess)
483            -> HttpResult<()> {
484        let headers = try!(self.decoder.decode(&frame.header_fragment)
485                                       .map_err(|e| HttpError::CompressionError(e)));
486        session.new_headers(frame.get_stream_id(), headers);
487
488        if frame.is_end_of_stream() {
489            debug!("End of stream {}", frame.get_stream_id());
490            session.end_of_stream(frame.get_stream_id());
491        }
492
493        Ok(())
494    }
495
496    /// Private helper method that handles a received `SettingsFrame`.
497    fn handle_settings_frame<Sess: Session>(&mut self, frame: SettingsFrame, _session: &mut Session)
498            -> HttpResult<()> {
499        if !frame.is_ack() {
500            // TODO: Actually handle the settings change before sending out the ACK
501            //       sending out the ACK.
502            debug!("Sending a SETTINGS ack");
503            try!(self.send_frame(SettingsFrame::new_ack()));
504        }
505
506        Ok(())
507    }
508}
509
510#[cfg(test)]
511mod tests {
512    use std::borrow::Cow;
513
514    use super::{
515        HttpConnection,
516        HttpFrame,
517        SendFrame, ReceiveFrame,
518        EndStream,
519        DataChunk,
520        SendStatus,
521    };
522
523    use http::tests::common::{
524        build_mock_http_conn,
525        build_stub_from_frames,
526        StubTransportStream,
527        StubDataPrioritizer,
528        TestSession,
529    };
530    use http::frame::{
531        Frame, DataFrame, HeadersFrame,
532        SettingsFrame,
533        pack_header,
534        RawFrame,
535    };
536    use http::transport::TransportStream;
537    use http::{HttpError, HttpResult};
538    use hpack;
539
540    /// A helper function that performs a `send_frame` operation on the given
541    /// `HttpConnection` by providing the frame instance wrapped in the given
542    /// `HttpFrame`.
543    ///
544    /// If the `HttpFrame` variant is `HttpFrame::UnknownFrame`, nothing will
545    /// be sent and an `Ok(())` is returned.
546    fn send_frame<S: SendFrame, R: ReceiveFrame>(conn: &mut HttpConnection<S, R>, frame: HttpFrame)
547            -> HttpResult<()> {
548        match frame {
549            HttpFrame::DataFrame(frame) => conn.send_frame(frame),
550            HttpFrame::SettingsFrame(frame) => conn.send_frame(frame),
551            HttpFrame::HeadersFrame(frame) => conn.send_frame(frame),
552            HttpFrame::UnknownFrame(_) => Ok(()),
553        }
554    }
555
556    /// Tests the implementation of the `SendFrame` for `io::Write` types when
557    /// writing individual frames.
558    #[test]
559    fn test_send_frame_for_io_write_individual() {
560        let frames: Vec<HttpFrame> = vec![
561            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
562            HttpFrame::DataFrame(DataFrame::new(1)),
563            HttpFrame::DataFrame(DataFrame::new(3)),
564            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 3)),
565            HttpFrame::UnknownFrame(RawFrame::from(vec![1, 2, 3, 4])),
566        ];
567        for frame in frames.into_iter() {
568            let mut writeable = Vec::new();
569            let frame_serialized = match frame {
570                HttpFrame::DataFrame(frame) => {
571                    let ret = frame.serialize();
572                    writeable.send_frame(frame).unwrap();
573                    ret
574                },
575                HttpFrame::HeadersFrame(frame) => {
576                    let ret = frame.serialize();
577                    writeable.send_frame(frame).unwrap();
578                    ret
579                },
580                HttpFrame::SettingsFrame(frame) => {
581                    let ret = frame.serialize();
582                    writeable.send_frame(frame).unwrap();
583                    ret
584                },
585                HttpFrame::UnknownFrame(frame) => {
586                    let ret = frame.serialize();
587                    writeable.send_raw_frame(frame).unwrap();
588                    ret
589                },
590            };
591            assert_eq!(writeable, frame_serialized);
592        }
593    }
594
595    /// Tests the implementation of the `SendFrame` for `io::Write` types when multiple
596    /// frames are written to the same stream.
597    #[test]
598    fn test_send_frame_for_io_write_multiple() {
599        let frames: Vec<HttpFrame> = vec![
600            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
601            HttpFrame::DataFrame(DataFrame::new(1)),
602            HttpFrame::DataFrame(DataFrame::new(3)),
603            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 3)),
604            HttpFrame::UnknownFrame(RawFrame::from(vec![1, 2, 3, 4])),
605        ];
606        let mut writeable = Vec::new();
607        let mut previous = 0;
608        for frame in frames.into_iter() {
609            let frame_serialized = match frame {
610                HttpFrame::DataFrame(frame) => {
611                    let ret = frame.serialize();
612                    writeable.send_frame(frame).unwrap();
613                    ret
614                },
615                HttpFrame::HeadersFrame(frame) => {
616                    let ret = frame.serialize();
617                    writeable.send_frame(frame).unwrap();
618                    ret
619                },
620                HttpFrame::SettingsFrame(frame) => {
621                    let ret = frame.serialize();
622                    writeable.send_frame(frame).unwrap();
623                    ret
624                },
625                HttpFrame::UnknownFrame(frame) => {
626                    let ret = frame.serialize();
627                    writeable.send_raw_frame(frame).unwrap();
628                    ret
629                },
630            };
631            assert_eq!(&writeable[previous..], &frame_serialized[..]);
632            previous = writeable.len();
633        }
634    }
635
636    /// Tests that trying to send a frame on a closed transport stream results in an error.
637    /// (i.e. an error returned by the underlying `io::Write` is propagated).
638    #[test]
639    fn test_send_frame_closed_stream() {
640        let mut stream = StubTransportStream::with_stub_content(&vec![]);
641        stream.close().unwrap();
642
643        let res = stream.send_frame(HeadersFrame::new(vec![], 1));
644
645        assert!(res.is_err());
646    }
647
648    /// Tests that the implementation of `ReceiveFrame` for `TransportStream` types
649    /// works correctly.
650    #[test]
651    fn test_recv_frame_for_transport_stream() {
652        let unknown_frame = RawFrame::from_buf(&{
653            let mut buf: Vec<u8> = Vec::new();
654            // Frame type 10 with a payload of length 1 on stream 1
655            let header = (1u32, 10u8, 0u8, 1u32);
656            buf.extend(pack_header(&header).to_vec().into_iter());
657            buf.push(1);
658            buf
659        }).unwrap();
660        let frames: Vec<HttpFrame> = vec![
661            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
662            HttpFrame::DataFrame(DataFrame::new(1)),
663            HttpFrame::DataFrame(DataFrame::new(3)),
664            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 3)),
665            HttpFrame::UnknownFrame(unknown_frame),
666        ];
667        let mut stream = StubTransportStream::with_stub_content(&build_stub_from_frames(&frames));
668
669        for frame in frames.into_iter() {
670            assert_eq!(frame, stream.recv_frame().unwrap());
671        }
672        // Attempting to read after EOF yields an error
673        assert!(stream.recv_frame().is_err());
674    }
675
676    /// Tests that the implementation of `ReceiveFrame` for `TransportStream` types
677    /// works correctly when faced with an incomplete frame.
678    #[test]
679    fn test_recv_frame_for_transport_stream_incomplete_frame() {
680        let frame = {
681            let mut frame = DataFrame::new(1);
682            frame.data = vec![1, 2, 3];
683            frame
684        };
685        let serialized: Vec<u8> = frame.serialize();
686
687        {
688            // Incomplete header
689            let mut stream = StubTransportStream::with_stub_content(&serialized[..5]);
690
691            assert!(stream.recv_frame().is_err());
692        }
693        {
694            // Incomplete data
695            let mut stream = StubTransportStream::with_stub_content(&serialized[..10]);
696
697            assert!(stream.recv_frame().is_err());
698        }
699    }
700
701    /// Tests that when an invalid, yet syntactically correct, frame is read from the stream,
702    /// a corresponding error is returned.
703    #[test]
704    fn test_recv_frame_invalid() {
705        // A DATA header which is attached to stream 0
706        let serialized = HeadersFrame::new(vec![], 0).serialize();
707        let mut stream = StubTransportStream::with_stub_content(&serialized);
708
709        assert_eq!(stream.recv_frame().err().unwrap(), HttpError::InvalidFrame);
710    }
711
712    /// Tests that the `HttpFrame::from_raw` method correctly recognizes the frame
713    /// type from the header and returns the corresponding variant.
714    #[test]
715    fn test_http_frame_from_raw() {
716        fn to_raw<F: Frame>(frame: F) -> RawFrame {
717            RawFrame::from_buf(&frame.serialize()).unwrap()
718        }
719
720        assert!(match HttpFrame::from_raw(to_raw(DataFrame::new(1))) {
721            Ok(HttpFrame::DataFrame(_)) => true,
722            _ => false,
723        });
724
725        assert!(match HttpFrame::from_raw(to_raw(HeadersFrame::new(vec![], 1))) {
726            Ok(HttpFrame::HeadersFrame(_)) => true,
727            _ => false,
728        });
729
730        assert!(match HttpFrame::from_raw(to_raw(SettingsFrame::new())) {
731            Ok(HttpFrame::SettingsFrame(_)) => true,
732            _ => false,
733        });
734
735        let unknown_frame = RawFrame::from_buf(&{
736            let mut buf: Vec<u8> = Vec::new();
737            // Frame type 10 with a payload of length 1 on stream 1
738            let header = (1u32, 10u8, 0u8, 1u32);
739            buf.extend(pack_header(&header).to_vec().into_iter());
740            buf.push(1);
741            buf
742        }).unwrap();
743        assert!(match HttpFrame::from_raw(unknown_frame) {
744            Ok(HttpFrame::UnknownFrame(_)) => true,
745            _ => false,
746        });
747
748        // Invalid since it's headers on stream 0
749        let invalid_frame = HeadersFrame::new(vec![], 0);
750        assert!(HttpFrame::from_raw(to_raw(invalid_frame)).is_err());
751    }
752
753    /// Tests that it is possible to read a single frame from the stream.
754    #[test]
755    fn test_read_single_frame() {
756        let frames: Vec<HttpFrame> = vec![
757            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
758        ];
759        let mut conn = build_mock_http_conn(frames.clone());
760
761        let actual: Vec<_> = (0..frames.len()).map(|_| conn.recv_frame().ok().unwrap())
762                                      .collect();
763
764        assert_eq!(actual, frames);
765    }
766
767    /// Tests that multiple frames are correctly read from the stream.
768    #[test]
769    fn test_read_multiple_frames() {
770        let frames: Vec<HttpFrame> = vec![
771            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
772            HttpFrame::DataFrame(DataFrame::new(1)),
773            HttpFrame::DataFrame(DataFrame::new(3)),
774            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 3)),
775        ];
776        let mut conn = build_mock_http_conn(frames.clone());
777
778        let actual: Vec<_> = (0..frames.len()).map(|_| conn.recv_frame().ok().unwrap())
779                                      .collect();
780
781        assert_eq!(actual, frames);
782    }
783
784    /// Tests that when reading from a stream that initially contains no data,
785    /// an `IoError` is returned.
786    #[test]
787    fn test_read_no_data() {
788        let mut conn = build_mock_http_conn(vec![]);
789
790        let res = conn.recv_frame();
791
792        assert!(match res.err().unwrap() {
793            HttpError::IoError(_) => true,
794            _ => false,
795        });
796    }
797
798    /// Tests that a read past the end of file (stream) results in an `IoError`.
799    #[test]
800    fn test_read_past_eof() {
801        let frames: Vec<HttpFrame> = vec![
802            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
803        ];
804        let mut conn = build_mock_http_conn(frames.clone());
805
806        let _: Vec<_> = (0..frames.len()).map(|_| conn.recv_frame().ok().unwrap())
807                                      .collect();
808        let res = conn.recv_frame();
809
810        assert!(match res.err().unwrap() {
811            HttpError::IoError(_) => true,
812            _ => false,
813        });
814    }
815
816    /// Tests that when reading a frame with a header that indicates an unknown frame type, the
817    /// frame is still returned wrapped in an `HttpFrame::UnknownFrame` variant.
818    #[test]
819    fn test_read_unknown_frame() {
820        let unknown_frame = RawFrame::from_buf(&{
821            let mut buf: Vec<u8> = Vec::new();
822            // Frame type 10 with a payload of length 1 on stream 1
823            let header = (1u32, 10u8, 0u8, 1u32);
824            buf.extend(pack_header(&header).to_vec().into_iter());
825            buf.push(1);
826            buf
827        }).unwrap();
828        let mut conn = build_mock_http_conn(vec![HttpFrame::UnknownFrame(unknown_frame)]);
829
830        // Unknown frame
831        assert!(match conn.recv_frame() {
832            Ok(HttpFrame::UnknownFrame(_)) => true,
833            _ => false,
834        });
835    }
836
837    /// Tests that it is possible to write a single frame to the connection.
838    #[test]
839    fn test_write_single_frame() {
840        let frames: Vec<HttpFrame> = vec![
841            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
842        ];
843        let expected = frames.clone();
844        let mut conn = build_mock_http_conn(vec![]);
845
846        for frame in frames.into_iter() {
847            send_frame(&mut conn, frame).unwrap();
848        }
849
850        assert_eq!(expected, conn.sender.sent);
851    }
852
853    #[test]
854    fn test_send_next_data() {
855        fn expect_chunk(expected: &[u8], frame: &HttpFrame) {
856            let frame = match frame {
857                &HttpFrame::DataFrame(ref frame) => frame,
858                _ => panic!("Expected a data frame"),
859            };
860            assert_eq!(expected, &frame.data[..]);
861        }
862        let mut conn = build_mock_http_conn(vec![]);
863        let chunks = vec![
864            vec![1, 2, 3, 4],
865            vec![5, 6],
866            vec![7],
867            vec![],
868        ];
869        let mut prioritizer = StubDataPrioritizer::new(chunks.clone());
870
871        // Send as many chunks as we've given the prioritizer
872        for chunk in chunks.iter() {
873            assert_eq!(SendStatus::Sent, conn.send_next_data(&mut prioritizer).unwrap());
874            expect_chunk(&chunk, conn.sender.sent.last().unwrap());
875        }
876        // Nothing to send any more
877        assert_eq!(SendStatus::Nothing, conn.send_next_data(&mut prioritizer).unwrap());
878    }
879
880    /// Tests that multiple frames are correctly written to the stream.
881    #[test]
882    fn test_write_multiple_frames() {
883        let frames: Vec<HttpFrame> = vec![
884            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
885            HttpFrame::DataFrame(DataFrame::new(1)),
886            HttpFrame::DataFrame(DataFrame::new(3)),
887            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 3)),
888        ];
889        let expected = frames.clone();
890        let mut conn = build_mock_http_conn(vec![]);
891
892        for frame in frames.into_iter() {
893            send_frame(&mut conn, frame).unwrap();
894        }
895
896        assert_eq!(expected, conn.sender.sent);
897    }
898
899    /// Tests that `HttpConnection::send_headers` correctly sends the given headers when they can
900    /// fit into a single frame's payload.
901    #[test]
902    fn test_send_headers_single_frame() {
903        fn assert_correct_headers(headers: &[(Vec<u8>, Vec<u8>)], frame: &HeadersFrame) {
904            let buf = &frame.header_fragment;
905            let frame_headers = hpack::Decoder::new().decode(buf).unwrap();
906            assert_eq!(headers, &frame_headers[..]);
907        }
908        let headers: Vec<(Vec<u8>, Vec<u8>)> = vec![
909            (b":method".to_vec(), b"GET".to_vec()),
910            (b":scheme".to_vec(), b"http".to_vec()),
911        ];
912        {
913            let mut conn = build_mock_http_conn(vec![]);
914
915            // Headers when the stream should be closed
916            conn.send_headers(&headers[..], 1, EndStream::Yes).unwrap();
917
918            // Only 1 frame sent?
919            assert_eq!(conn.sender.sent.len(), 1);
920            // The headers frame?
921            let frame = match conn.sender.sent.remove(0) {
922                HttpFrame::HeadersFrame(frame) => frame,
923                _ => panic!("Headers frame not sent"),
924            };
925            // We sent a headers frame with end of headers and end of stream flags
926            assert!(frame.is_headers_end());
927            assert!(frame.is_end_of_stream());
928            // And the headers were also correct -- just for good measure.
929            assert_correct_headers(&headers, &frame);
930        }
931        {
932            let mut conn = build_mock_http_conn(vec![]);
933
934            // Headers when the stream should be left open
935            conn.send_headers(&headers[..], 1, EndStream::No).unwrap();
936
937            // Only 1 frame sent?
938            assert_eq!(conn.sender.sent.len(), 1);
939            // The headers frame?
940            let frame = match conn.sender.sent.remove(0) {
941                HttpFrame::HeadersFrame(frame) => frame,
942                _ => panic!("Headers frame not sent"),
943            };
944            assert!(frame.is_headers_end());
945            // ...but it's not the end of the stream
946            assert!(!frame.is_end_of_stream());
947            assert_correct_headers(&headers, &frame);
948        }
949        {
950            let mut conn = build_mock_http_conn(vec![]);
951
952            // Make sure it's all peachy when we give a `Vec` instead of a slice
953            conn.send_headers(headers.clone(), 1, EndStream::Yes).unwrap();
954
955            // Only 1 frame sent?
956            assert_eq!(conn.sender.sent.len(), 1);
957            // The headers frame?
958            let frame = match conn.sender.sent.remove(0) {
959                HttpFrame::HeadersFrame(frame) => frame,
960                _ => panic!("Headers frame not sent"),
961            };
962            // We sent a headers frame with end of headers and end of stream flags
963            assert!(frame.is_headers_end());
964            assert!(frame.is_end_of_stream());
965            // And the headers were also correct -- just for good measure.
966            assert_correct_headers(&headers, &frame);
967        }
968    }
969
970    /// Tests that `HttpConnection::send_data` correctly sends the given data when it can fit into
971    /// a single frame's payload.
972    #[test]
973    fn test_send_data_single_frame() {
974        {
975            // Data shouldn't end the stream...
976            let mut conn = build_mock_http_conn(vec![]);
977            let data: &[u8] = b"1234";
978
979            conn.send_data(DataChunk::new_borrowed(data, 1, EndStream::No)).unwrap();
980
981            // Only 1 frame sent?
982            assert_eq!(conn.sender.sent.len(), 1);
983            // A data frame?
984            let frame = match conn.sender.sent.remove(0) {
985                HttpFrame::DataFrame(frame) => frame,
986                _ => panic!("Data frame not sent"),
987            };
988            assert_eq!(&frame.data[..], data);
989            assert!(!frame.is_end_of_stream());
990        }
991        {
992            // Data should end the stream...
993            let mut conn = build_mock_http_conn(vec![]);
994            let data: &[u8] = b"1234";
995
996            conn.send_data(DataChunk::new_borrowed(data, 1, EndStream::Yes)).unwrap();
997
998            // Only 1 frame sent?
999            assert_eq!(conn.sender.sent.len(), 1);
1000            // A data frame?
1001            let frame = match conn.sender.sent.remove(0) {
1002                HttpFrame::DataFrame(frame) => frame,
1003                _ => panic!("Data frame not sent"),
1004            };
1005            assert_eq!(&frame.data[..], data);
1006            assert!(frame.is_end_of_stream());
1007        }
1008        {
1009            // given a `Vec` we're good too?
1010            let mut conn = build_mock_http_conn(vec![]);
1011            let data: &[u8] = b"1234";
1012            let chunk = DataChunk {
1013                data: Cow::Owned(data.to_vec()),
1014                stream_id: 1,
1015                end_stream: EndStream::Yes,
1016            };
1017
1018            conn.send_data(chunk).unwrap();
1019
1020            // Only 1 frame sent?
1021            assert_eq!(conn.sender.sent.len(), 1);
1022            // A data frame?
1023            let frame = match conn.sender.sent.remove(0) {
1024                HttpFrame::DataFrame(frame) => frame,
1025                _ => panic!("Data frame not sent"),
1026            };
1027            assert_eq!(&frame.data[..], data);
1028            assert!(frame.is_end_of_stream());
1029        }
1030    }
1031
1032    /// Tests that the `HttpConnection` correctly notifies the session on a
1033    /// new headers frame, with no continuation.
1034    #[test]
1035    fn test_http_conn_notifies_session_header() {
1036        let frames: Vec<HttpFrame> = vec![
1037            HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
1038        ];
1039        let mut conn = build_mock_http_conn(frames);
1040        let mut session = TestSession::new();
1041
1042        conn.handle_next_frame(&mut session).unwrap();
1043
1044        // A poor man's mock...
1045        // The header callback was called
1046        assert_eq!(session.curr_header, 1);
1047        // ...no chunks were seen.
1048        assert_eq!(session.curr_chunk, 0);
1049    }
1050
1051    /// Tests that the `HttpConnection` correctly notifies the session on
1052    /// a new data chunk.
1053    #[test]
1054    fn test_http_conn_notifies_session_data() {
1055        let frames: Vec<HttpFrame> = vec![
1056            HttpFrame::DataFrame(DataFrame::new(1)),
1057        ];
1058        let mut conn = build_mock_http_conn(frames);
1059        let mut session = TestSession::new();
1060
1061        conn.handle_next_frame(&mut session).unwrap();
1062
1063        // A poor man's mock...
1064        // The header callback was not called
1065        assert_eq!(session.curr_header, 0);
1066        // and exactly one chunk seen.
1067        assert_eq!(session.curr_chunk, 1);
1068    }
1069
1070    /// Tests that the session gets the correct values for the headers and data
1071    /// from the `HttpConnection` when multiple frames are handled.
1072    #[test]
1073    fn test_http_conn_session_gets_headers_data_values() {
1074        let headers = vec![(b":method".to_vec(), b"GET".to_vec())];
1075        let frames: Vec<HttpFrame> = vec![
1076            HttpFrame::HeadersFrame(HeadersFrame::new(
1077                    hpack::Encoder::new().encode(&headers),
1078                    1)),
1079            HttpFrame::DataFrame(DataFrame::new(1)), {
1080                let mut frame = DataFrame::new(1);
1081                frame.data = b"1234".to_vec();
1082                HttpFrame::DataFrame(frame)
1083            },
1084        ];
1085        let mut conn = build_mock_http_conn(frames);
1086        let mut session = TestSession::new_verify(
1087                vec![headers],
1088                vec![b"".to_vec(), b"1234".to_vec()]);
1089
1090        conn.handle_next_frame(&mut session).unwrap();
1091        conn.handle_next_frame(&mut session).unwrap();
1092        conn.handle_next_frame(&mut session).unwrap();
1093
1094        // Two chunks and one header processed?
1095        assert_eq!(session.curr_chunk, 2);
1096        assert_eq!(session.curr_header, 1);
1097    }
1098
1099    /// Tests that the `HttpConnection::expect_settings` method works correctly.
1100    #[test]
1101    fn test_http_conn_expect_settings() {
1102        {
1103            // The next frame is indeed a settings frame.
1104            let frames = vec![HttpFrame::SettingsFrame(SettingsFrame::new())];
1105            let mut conn = build_mock_http_conn(frames);
1106            assert!(conn.expect_settings(&mut TestSession::new()).is_ok());
1107        }
1108        {
1109            // The next frame is a data frame...
1110            let frames = vec![HttpFrame::DataFrame(DataFrame::new(1))];
1111            let mut conn = build_mock_http_conn(frames);
1112            assert!(conn.expect_settings(&mut TestSession::new()).is_err());
1113        }
1114        {
1115            // The next frame is an ACK settings frame
1116            let frames = vec![HttpFrame::SettingsFrame(SettingsFrame::new_ack())];
1117            let mut conn = build_mock_http_conn(frames);
1118            assert!(conn.expect_settings(&mut TestSession::new()).is_err());
1119        }
1120    }
1121}