use std::io;
use std::borrow::Cow;
use std::borrow::Borrow;
use http::{
Header,
StreamId,
HttpError,
HttpResult,
HttpScheme,
};
use http::priority::DataPrioritizer;
use http::session::Session;
use http::transport::TransportStream;
use http::frame::{
Frame,
RawFrame,
DataFrame,
DataFlag,
HeadersFrame,
HeadersFlag,
SettingsFrame,
unpack_header,
};
use hpack;
#[derive(PartialEq)]
#[derive(Debug)]
#[derive(Clone)]
pub enum HttpFrame {
DataFrame(DataFrame),
HeadersFrame(HeadersFrame),
SettingsFrame(SettingsFrame),
UnknownFrame(RawFrame),
}
impl HttpFrame {
pub fn from_raw(raw_frame: RawFrame) -> HttpResult<HttpFrame> {
let frame = match raw_frame.header().1 {
0x0 => HttpFrame::DataFrame(try!(HttpFrame::parse_frame(raw_frame))),
0x1 => HttpFrame::HeadersFrame(try!(HttpFrame::parse_frame(raw_frame))),
0x4 => HttpFrame::SettingsFrame(try!(HttpFrame::parse_frame(raw_frame))),
_ => HttpFrame::UnknownFrame(raw_frame),
};
Ok(frame)
}
#[inline]
fn parse_frame<F: Frame>(raw_frame: RawFrame) -> HttpResult<F> {
Frame::from_raw(raw_frame).ok_or(HttpError::InvalidFrame)
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum SendStatus {
Sent,
Nothing,
}
pub struct HttpConnection<S, R> where S: SendFrame, R: ReceiveFrame {
pub receiver: R,
pub sender: S,
decoder: hpack::Decoder<'static>,
encoder: hpack::Encoder<'static>,
pub scheme: HttpScheme,
}
pub trait SendFrame {
fn send_raw_frame(&mut self, frame: RawFrame) -> HttpResult<()>;
fn send_frame<F: Frame>(&mut self, frame: F) -> HttpResult<()> {
self.send_raw_frame(RawFrame::from(frame.serialize()))
}
}
impl<W> SendFrame for W where W: io::Write {
#[inline]
fn send_frame<F: Frame>(&mut self, frame: F) -> HttpResult<()> {
try!(self.write_all(&frame.serialize()));
Ok(())
}
#[inline]
fn send_raw_frame(&mut self, frame: RawFrame) -> HttpResult<()> {
let serialized: Vec<u8> = frame.into();
try!(self.write_all(&serialized));
Ok(())
}
}
pub trait ReceiveFrame {
fn recv_frame(&mut self) -> HttpResult<HttpFrame>;
}
impl<TS> ReceiveFrame for TS where TS: TransportStream {
fn recv_frame(&mut self) -> HttpResult<HttpFrame> {
let read_header_bytes = |stream: &mut TS| -> HttpResult<[u8; 9]> {
let mut buf = [0; 9];
try!(TransportStream::read_exact(stream, &mut buf));
Ok(buf)
};
let read_payload = |stream: &mut TS, len: u32| -> HttpResult<Vec<u8>> {
debug!("Trying to read {} bytes of frame payload", len);
let length = len as usize;
let mut buf: Vec<u8> = Vec::with_capacity(length);
unsafe { buf.set_len(length); }
try!(TransportStream::read_exact(stream, &mut buf));
Ok(buf)
};
let header = unpack_header(&try!(read_header_bytes(self)));
debug!("Received frame header {:?}", header);
let payload = try!(read_payload(self, header.0));
let raw_frame = RawFrame::with_payload(header, payload);
let frame = try!(HttpFrame::from_raw(raw_frame));
Ok(frame)
}
}
pub struct DataChunk<'a> {
pub data: Cow<'a, [u8]>,
pub stream_id: StreamId,
pub end_stream: EndStream,
}
impl<'a> DataChunk<'a> {
pub fn new(data: Cow<'a, [u8]>, stream_id: StreamId, end_stream: EndStream) -> DataChunk<'a> {
DataChunk {
data: data,
stream_id: stream_id,
end_stream: end_stream,
}
}
pub fn new_borrowed<D: Borrow<&'a [u8]>>(data: D, stream_id: StreamId, end_stream: EndStream)
-> DataChunk<'a> {
DataChunk {
data: Cow::Borrowed(data.borrow()),
stream_id: stream_id,
end_stream: end_stream,
}
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum EndStream {
Yes,
No,
}
impl<S, R> HttpConnection<S, R> where S: SendFrame, R: ReceiveFrame {
pub fn new(sender: S, receiver: R, scheme: HttpScheme) -> HttpConnection<S, R> {
HttpConnection {
receiver: receiver,
sender: sender,
scheme: scheme,
decoder: hpack::Decoder::new(),
encoder: hpack::Encoder::new(),
}
}
pub fn with_stream<TS>(stream: TS, scheme: HttpScheme) -> HttpConnection<TS, TS>
where TS: TransportStream {
let sender = stream.try_split().unwrap();
let receiver = stream;
HttpConnection::new(sender, receiver, scheme)
}
#[inline]
fn send_frame<F: Frame>(&mut self, frame: F) -> HttpResult<()> {
debug!("Sending frame ... {:?}", frame.get_header());
self.sender.send_frame(frame)
}
#[inline]
fn recv_frame(&mut self) -> HttpResult<HttpFrame> {
self.receiver.recv_frame()
}
pub fn send_headers<H: Into<Vec<Header>>>(&mut self,
headers: H,
stream_id: StreamId,
end_stream: EndStream) -> HttpResult<()> {
self.send_headers_inner(headers.into(), stream_id, end_stream)
}
fn send_headers_inner(&mut self,
headers: Vec<Header>,
stream_id: StreamId,
end_stream: EndStream) -> HttpResult<()> {
let headers_fragment = self.encoder.encode(&headers);
let mut frame = HeadersFrame::new(headers_fragment, stream_id);
frame.set_flag(HeadersFlag::EndHeaders);
if end_stream == EndStream::Yes {
frame.set_flag(HeadersFlag::EndStream);
}
self.send_frame(frame)
}
pub fn send_data<'a>(&mut self,
chunk: DataChunk<'a>) -> HttpResult<()> {
let DataChunk { data, stream_id, end_stream } = chunk;
self.send_data_inner(data.into_owned(), stream_id, end_stream)
}
fn send_data_inner(&mut self, data: Vec<u8>, stream_id: StreamId, end_stream: EndStream)
-> HttpResult<()>{
let mut frame = DataFrame::new(stream_id);
frame.data.extend(data);
if end_stream == EndStream::Yes {
frame.set_flag(DataFlag::EndStream);
}
self.send_frame(frame)
}
pub fn send_next_data<P: DataPrioritizer>(&mut self, prioritizer: &mut P)
-> HttpResult<SendStatus> {
let chunk = try!(prioritizer.get_next_chunk());
match chunk {
None => Ok(SendStatus::Nothing),
Some(chunk) => {
try!(self.send_data(chunk));
Ok(SendStatus::Sent)
},
}
}
pub fn expect_settings<Sess: Session>(&mut self, session: &mut Sess) -> HttpResult<()> {
let frame = self.recv_frame();
match frame {
Ok(HttpFrame::SettingsFrame(ref settings)) if !settings.is_ack() => {
debug!("Correctly received a SETTINGS frame from the server");
},
Ok(_) => return Err(HttpError::UnableToConnect),
Err(e) => return Err(e),
};
try!(self.handle_frame(frame.unwrap(), session));
Ok(())
}
pub fn handle_next_frame<Sess: Session>(&mut self, session: &mut Sess) -> HttpResult<()> {
debug!("Waiting for frame...");
let frame = match self.recv_frame() {
Ok(frame) => frame,
Err(e) => {
debug!("Encountered an HTTP/2 error, stopping.");
return Err(e);
},
};
self.handle_frame(frame, session)
}
fn handle_frame<Sess: Session>(&mut self, frame: HttpFrame, session: &mut Sess)
-> HttpResult<()> {
match frame {
HttpFrame::DataFrame(frame) => {
debug!("Data frame received");
self.handle_data_frame(frame, session)
},
HttpFrame::HeadersFrame(frame) => {
debug!("Headers frame received");
self.handle_headers_frame(frame, session)
},
HttpFrame::SettingsFrame(frame) => {
debug!("Settings frame received");
self.handle_settings_frame::<Sess>(frame, session)
},
HttpFrame::UnknownFrame(_) => {
debug!("Unknown frame received");
Ok(())
},
}
}
fn handle_data_frame<Sess: Session>(&mut self, frame: DataFrame, session: &mut Sess)
-> HttpResult<()> {
session.new_data_chunk(frame.get_stream_id(), &frame.data);
if frame.is_set(DataFlag::EndStream) {
debug!("End of stream {}", frame.get_stream_id());
session.end_of_stream(frame.get_stream_id())
}
Ok(())
}
fn handle_headers_frame<Sess: Session>(&mut self, frame: HeadersFrame, session: &mut Sess)
-> HttpResult<()> {
let headers = try!(self.decoder.decode(&frame.header_fragment)
.map_err(|e| HttpError::CompressionError(e)));
session.new_headers(frame.get_stream_id(), headers);
if frame.is_end_of_stream() {
debug!("End of stream {}", frame.get_stream_id());
session.end_of_stream(frame.get_stream_id());
}
Ok(())
}
fn handle_settings_frame<Sess: Session>(&mut self, frame: SettingsFrame, _session: &mut Session)
-> HttpResult<()> {
if !frame.is_ack() {
debug!("Sending a SETTINGS ack");
try!(self.send_frame(SettingsFrame::new_ack()));
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::borrow::Cow;
use super::{
HttpConnection,
HttpFrame,
SendFrame, ReceiveFrame,
EndStream,
DataChunk,
SendStatus,
};
use http::tests::common::{
build_mock_http_conn,
build_stub_from_frames,
StubTransportStream,
StubDataPrioritizer,
TestSession,
};
use http::frame::{
Frame, DataFrame, HeadersFrame,
SettingsFrame,
pack_header,
RawFrame,
};
use http::transport::TransportStream;
use http::{HttpError, HttpResult};
use hpack;
fn send_frame<S: SendFrame, R: ReceiveFrame>(conn: &mut HttpConnection<S, R>, frame: HttpFrame)
-> HttpResult<()> {
match frame {
HttpFrame::DataFrame(frame) => conn.send_frame(frame),
HttpFrame::SettingsFrame(frame) => conn.send_frame(frame),
HttpFrame::HeadersFrame(frame) => conn.send_frame(frame),
HttpFrame::UnknownFrame(_) => Ok(()),
}
}
#[test]
fn test_send_frame_for_io_write_individual() {
let frames: Vec<HttpFrame> = vec![
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
HttpFrame::DataFrame(DataFrame::new(1)),
HttpFrame::DataFrame(DataFrame::new(3)),
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 3)),
HttpFrame::UnknownFrame(RawFrame::from(vec![1, 2, 3, 4])),
];
for frame in frames.into_iter() {
let mut writeable = Vec::new();
let frame_serialized = match frame {
HttpFrame::DataFrame(frame) => {
let ret = frame.serialize();
writeable.send_frame(frame).unwrap();
ret
},
HttpFrame::HeadersFrame(frame) => {
let ret = frame.serialize();
writeable.send_frame(frame).unwrap();
ret
},
HttpFrame::SettingsFrame(frame) => {
let ret = frame.serialize();
writeable.send_frame(frame).unwrap();
ret
},
HttpFrame::UnknownFrame(frame) => {
let ret = frame.serialize();
writeable.send_raw_frame(frame).unwrap();
ret
},
};
assert_eq!(writeable, frame_serialized);
}
}
#[test]
fn test_send_frame_for_io_write_multiple() {
let frames: Vec<HttpFrame> = vec![
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
HttpFrame::DataFrame(DataFrame::new(1)),
HttpFrame::DataFrame(DataFrame::new(3)),
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 3)),
HttpFrame::UnknownFrame(RawFrame::from(vec![1, 2, 3, 4])),
];
let mut writeable = Vec::new();
let mut previous = 0;
for frame in frames.into_iter() {
let frame_serialized = match frame {
HttpFrame::DataFrame(frame) => {
let ret = frame.serialize();
writeable.send_frame(frame).unwrap();
ret
},
HttpFrame::HeadersFrame(frame) => {
let ret = frame.serialize();
writeable.send_frame(frame).unwrap();
ret
},
HttpFrame::SettingsFrame(frame) => {
let ret = frame.serialize();
writeable.send_frame(frame).unwrap();
ret
},
HttpFrame::UnknownFrame(frame) => {
let ret = frame.serialize();
writeable.send_raw_frame(frame).unwrap();
ret
},
};
assert_eq!(&writeable[previous..], &frame_serialized[..]);
previous = writeable.len();
}
}
#[test]
fn test_send_frame_closed_stream() {
let mut stream = StubTransportStream::with_stub_content(&vec![]);
stream.close().unwrap();
let res = stream.send_frame(HeadersFrame::new(vec![], 1));
assert!(res.is_err());
}
#[test]
fn test_recv_frame_for_transport_stream() {
let unknown_frame = RawFrame::from_buf(&{
let mut buf: Vec<u8> = Vec::new();
let header = (1u32, 10u8, 0u8, 1u32);
buf.extend(pack_header(&header).to_vec().into_iter());
buf.push(1);
buf
}).unwrap();
let frames: Vec<HttpFrame> = vec![
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
HttpFrame::DataFrame(DataFrame::new(1)),
HttpFrame::DataFrame(DataFrame::new(3)),
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 3)),
HttpFrame::UnknownFrame(unknown_frame),
];
let mut stream = StubTransportStream::with_stub_content(&build_stub_from_frames(&frames));
for frame in frames.into_iter() {
assert_eq!(frame, stream.recv_frame().unwrap());
}
assert!(stream.recv_frame().is_err());
}
#[test]
fn test_recv_frame_for_transport_stream_incomplete_frame() {
let frame = {
let mut frame = DataFrame::new(1);
frame.data = vec![1, 2, 3];
frame
};
let serialized: Vec<u8> = frame.serialize();
{
let mut stream = StubTransportStream::with_stub_content(&serialized[..5]);
assert!(stream.recv_frame().is_err());
}
{
let mut stream = StubTransportStream::with_stub_content(&serialized[..10]);
assert!(stream.recv_frame().is_err());
}
}
#[test]
fn test_recv_frame_invalid() {
let serialized = HeadersFrame::new(vec![], 0).serialize();
let mut stream = StubTransportStream::with_stub_content(&serialized);
assert_eq!(stream.recv_frame().err().unwrap(), HttpError::InvalidFrame);
}
#[test]
fn test_http_frame_from_raw() {
fn to_raw<F: Frame>(frame: F) -> RawFrame {
RawFrame::from_buf(&frame.serialize()).unwrap()
}
assert!(match HttpFrame::from_raw(to_raw(DataFrame::new(1))) {
Ok(HttpFrame::DataFrame(_)) => true,
_ => false,
});
assert!(match HttpFrame::from_raw(to_raw(HeadersFrame::new(vec![], 1))) {
Ok(HttpFrame::HeadersFrame(_)) => true,
_ => false,
});
assert!(match HttpFrame::from_raw(to_raw(SettingsFrame::new())) {
Ok(HttpFrame::SettingsFrame(_)) => true,
_ => false,
});
let unknown_frame = RawFrame::from_buf(&{
let mut buf: Vec<u8> = Vec::new();
let header = (1u32, 10u8, 0u8, 1u32);
buf.extend(pack_header(&header).to_vec().into_iter());
buf.push(1);
buf
}).unwrap();
assert!(match HttpFrame::from_raw(unknown_frame) {
Ok(HttpFrame::UnknownFrame(_)) => true,
_ => false,
});
let invalid_frame = HeadersFrame::new(vec![], 0);
assert!(HttpFrame::from_raw(to_raw(invalid_frame)).is_err());
}
#[test]
fn test_read_single_frame() {
let frames: Vec<HttpFrame> = vec![
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
];
let mut conn = build_mock_http_conn(frames.clone());
let actual: Vec<_> = (0..frames.len()).map(|_| conn.recv_frame().ok().unwrap())
.collect();
assert_eq!(actual, frames);
}
#[test]
fn test_read_multiple_frames() {
let frames: Vec<HttpFrame> = vec![
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
HttpFrame::DataFrame(DataFrame::new(1)),
HttpFrame::DataFrame(DataFrame::new(3)),
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 3)),
];
let mut conn = build_mock_http_conn(frames.clone());
let actual: Vec<_> = (0..frames.len()).map(|_| conn.recv_frame().ok().unwrap())
.collect();
assert_eq!(actual, frames);
}
#[test]
fn test_read_no_data() {
let mut conn = build_mock_http_conn(vec![]);
let res = conn.recv_frame();
assert!(match res.err().unwrap() {
HttpError::IoError(_) => true,
_ => false,
});
}
#[test]
fn test_read_past_eof() {
let frames: Vec<HttpFrame> = vec![
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
];
let mut conn = build_mock_http_conn(frames.clone());
let _: Vec<_> = (0..frames.len()).map(|_| conn.recv_frame().ok().unwrap())
.collect();
let res = conn.recv_frame();
assert!(match res.err().unwrap() {
HttpError::IoError(_) => true,
_ => false,
});
}
#[test]
fn test_read_unknown_frame() {
let unknown_frame = RawFrame::from_buf(&{
let mut buf: Vec<u8> = Vec::new();
let header = (1u32, 10u8, 0u8, 1u32);
buf.extend(pack_header(&header).to_vec().into_iter());
buf.push(1);
buf
}).unwrap();
let mut conn = build_mock_http_conn(vec![HttpFrame::UnknownFrame(unknown_frame)]);
assert!(match conn.recv_frame() {
Ok(HttpFrame::UnknownFrame(_)) => true,
_ => false,
});
}
#[test]
fn test_write_single_frame() {
let frames: Vec<HttpFrame> = vec![
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
];
let expected = frames.clone();
let mut conn = build_mock_http_conn(vec![]);
for frame in frames.into_iter() {
send_frame(&mut conn, frame).unwrap();
}
assert_eq!(expected, conn.sender.sent);
}
#[test]
fn test_send_next_data() {
fn expect_chunk(expected: &[u8], frame: &HttpFrame) {
let frame = match frame {
&HttpFrame::DataFrame(ref frame) => frame,
_ => panic!("Expected a data frame"),
};
assert_eq!(expected, &frame.data[..]);
}
let mut conn = build_mock_http_conn(vec![]);
let chunks = vec![
vec![1, 2, 3, 4],
vec![5, 6],
vec![7],
vec![],
];
let mut prioritizer = StubDataPrioritizer::new(chunks.clone());
for chunk in chunks.iter() {
assert_eq!(SendStatus::Sent, conn.send_next_data(&mut prioritizer).unwrap());
expect_chunk(&chunk, conn.sender.sent.last().unwrap());
}
assert_eq!(SendStatus::Nothing, conn.send_next_data(&mut prioritizer).unwrap());
}
#[test]
fn test_write_multiple_frames() {
let frames: Vec<HttpFrame> = vec![
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
HttpFrame::DataFrame(DataFrame::new(1)),
HttpFrame::DataFrame(DataFrame::new(3)),
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 3)),
];
let expected = frames.clone();
let mut conn = build_mock_http_conn(vec![]);
for frame in frames.into_iter() {
send_frame(&mut conn, frame).unwrap();
}
assert_eq!(expected, conn.sender.sent);
}
#[test]
fn test_send_headers_single_frame() {
fn assert_correct_headers(headers: &[(Vec<u8>, Vec<u8>)], frame: &HeadersFrame) {
let buf = &frame.header_fragment;
let frame_headers = hpack::Decoder::new().decode(buf).unwrap();
assert_eq!(headers, &frame_headers[..]);
}
let headers: Vec<(Vec<u8>, Vec<u8>)> = vec![
(b":method".to_vec(), b"GET".to_vec()),
(b":scheme".to_vec(), b"http".to_vec()),
];
{
let mut conn = build_mock_http_conn(vec![]);
conn.send_headers(&headers[..], 1, EndStream::Yes).unwrap();
assert_eq!(conn.sender.sent.len(), 1);
let frame = match conn.sender.sent.remove(0) {
HttpFrame::HeadersFrame(frame) => frame,
_ => panic!("Headers frame not sent"),
};
assert!(frame.is_headers_end());
assert!(frame.is_end_of_stream());
assert_correct_headers(&headers, &frame);
}
{
let mut conn = build_mock_http_conn(vec![]);
conn.send_headers(&headers[..], 1, EndStream::No).unwrap();
assert_eq!(conn.sender.sent.len(), 1);
let frame = match conn.sender.sent.remove(0) {
HttpFrame::HeadersFrame(frame) => frame,
_ => panic!("Headers frame not sent"),
};
assert!(frame.is_headers_end());
assert!(!frame.is_end_of_stream());
assert_correct_headers(&headers, &frame);
}
{
let mut conn = build_mock_http_conn(vec![]);
conn.send_headers(headers.clone(), 1, EndStream::Yes).unwrap();
assert_eq!(conn.sender.sent.len(), 1);
let frame = match conn.sender.sent.remove(0) {
HttpFrame::HeadersFrame(frame) => frame,
_ => panic!("Headers frame not sent"),
};
assert!(frame.is_headers_end());
assert!(frame.is_end_of_stream());
assert_correct_headers(&headers, &frame);
}
}
#[test]
fn test_send_data_single_frame() {
{
let mut conn = build_mock_http_conn(vec![]);
let data: &[u8] = b"1234";
conn.send_data(DataChunk::new_borrowed(data, 1, EndStream::No)).unwrap();
assert_eq!(conn.sender.sent.len(), 1);
let frame = match conn.sender.sent.remove(0) {
HttpFrame::DataFrame(frame) => frame,
_ => panic!("Data frame not sent"),
};
assert_eq!(&frame.data[..], data);
assert!(!frame.is_end_of_stream());
}
{
let mut conn = build_mock_http_conn(vec![]);
let data: &[u8] = b"1234";
conn.send_data(DataChunk::new_borrowed(data, 1, EndStream::Yes)).unwrap();
assert_eq!(conn.sender.sent.len(), 1);
let frame = match conn.sender.sent.remove(0) {
HttpFrame::DataFrame(frame) => frame,
_ => panic!("Data frame not sent"),
};
assert_eq!(&frame.data[..], data);
assert!(frame.is_end_of_stream());
}
{
let mut conn = build_mock_http_conn(vec![]);
let data: &[u8] = b"1234";
let chunk = DataChunk {
data: Cow::Owned(data.to_vec()),
stream_id: 1,
end_stream: EndStream::Yes,
};
conn.send_data(chunk).unwrap();
assert_eq!(conn.sender.sent.len(), 1);
let frame = match conn.sender.sent.remove(0) {
HttpFrame::DataFrame(frame) => frame,
_ => panic!("Data frame not sent"),
};
assert_eq!(&frame.data[..], data);
assert!(frame.is_end_of_stream());
}
}
#[test]
fn test_http_conn_notifies_session_header() {
let frames: Vec<HttpFrame> = vec![
HttpFrame::HeadersFrame(HeadersFrame::new(vec![], 1)),
];
let mut conn = build_mock_http_conn(frames);
let mut session = TestSession::new();
conn.handle_next_frame(&mut session).unwrap();
assert_eq!(session.curr_header, 1);
assert_eq!(session.curr_chunk, 0);
}
#[test]
fn test_http_conn_notifies_session_data() {
let frames: Vec<HttpFrame> = vec![
HttpFrame::DataFrame(DataFrame::new(1)),
];
let mut conn = build_mock_http_conn(frames);
let mut session = TestSession::new();
conn.handle_next_frame(&mut session).unwrap();
assert_eq!(session.curr_header, 0);
assert_eq!(session.curr_chunk, 1);
}
#[test]
fn test_http_conn_session_gets_headers_data_values() {
let headers = vec![(b":method".to_vec(), b"GET".to_vec())];
let frames: Vec<HttpFrame> = vec![
HttpFrame::HeadersFrame(HeadersFrame::new(
hpack::Encoder::new().encode(&headers),
1)),
HttpFrame::DataFrame(DataFrame::new(1)), {
let mut frame = DataFrame::new(1);
frame.data = b"1234".to_vec();
HttpFrame::DataFrame(frame)
},
];
let mut conn = build_mock_http_conn(frames);
let mut session = TestSession::new_verify(
vec![headers],
vec![b"".to_vec(), b"1234".to_vec()]);
conn.handle_next_frame(&mut session).unwrap();
conn.handle_next_frame(&mut session).unwrap();
conn.handle_next_frame(&mut session).unwrap();
assert_eq!(session.curr_chunk, 2);
assert_eq!(session.curr_header, 1);
}
#[test]
fn test_http_conn_expect_settings() {
{
let frames = vec![HttpFrame::SettingsFrame(SettingsFrame::new())];
let mut conn = build_mock_http_conn(frames);
assert!(conn.expect_settings(&mut TestSession::new()).is_ok());
}
{
let frames = vec![HttpFrame::DataFrame(DataFrame::new(1))];
let mut conn = build_mock_http_conn(frames);
assert!(conn.expect_settings(&mut TestSession::new()).is_err());
}
{
let frames = vec![HttpFrame::SettingsFrame(SettingsFrame::new_ack())];
let mut conn = build_mock_http_conn(frames);
assert!(conn.expect_settings(&mut TestSession::new()).is_err());
}
}
}