Add GoAway support
This commit is contained in:
		| @@ -1,4 +1,7 @@ | |||||||
| use frame::{Error, StreamId}; | use error::Reason; | ||||||
|  | use frame::{self, Head, Error, Kind, StreamId}; | ||||||
|  |  | ||||||
|  | use bytes::{BufMut, BigEndian}; | ||||||
|  |  | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct GoAway { | pub struct GoAway { | ||||||
| @@ -7,6 +10,10 @@ pub struct GoAway { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl GoAway { | impl GoAway { | ||||||
|  |     pub fn reason(&self) -> Reason { | ||||||
|  |         self.error_code.into() | ||||||
|  |     } | ||||||
|  |  | ||||||
|     pub fn load(payload: &[u8]) -> Result<GoAway, Error> { |     pub fn load(payload: &[u8]) -> Result<GoAway, Error> { | ||||||
|         if payload.len() < 8 { |         if payload.len() < 8 { | ||||||
|             // Invalid payload len |             // Invalid payload len | ||||||
| @@ -22,4 +29,18 @@ impl GoAway { | |||||||
|             error_code: error_code, |             error_code: error_code, | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     pub fn encode<B: BufMut>(&self, dst: &mut B) { | ||||||
|  |         trace!("encoding GO_AWAY; code={}", self.error_code); | ||||||
|  |         let head = Head::new(Kind::GoAway, 0, StreamId::zero()); | ||||||
|  |         head.encode(8, dst); | ||||||
|  |         dst.put_u32::<BigEndian>(self.last_stream_id.into()); | ||||||
|  |         dst.put_u32::<BigEndian>(self.error_code); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl<B> From<GoAway> for frame::Frame<B> { | ||||||
|  |     fn from(src: GoAway) -> Self { | ||||||
|  |         frame::Frame::GoAway(src) | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -62,6 +62,7 @@ pub enum Frame<T = Bytes> { | |||||||
|     PushPromise(PushPromise), |     PushPromise(PushPromise), | ||||||
|     Settings(Settings), |     Settings(Settings), | ||||||
|     Ping(Ping), |     Ping(Ping), | ||||||
|  |     GoAway(GoAway), | ||||||
|     WindowUpdate(WindowUpdate), |     WindowUpdate(WindowUpdate), | ||||||
|     Reset(Reset) |     Reset(Reset) | ||||||
| } | } | ||||||
| @@ -100,6 +101,7 @@ impl<T> fmt::Debug for Frame<T> { | |||||||
|             PushPromise(ref frame) => write!(fmt, "Frame::PushPromise({:?})", frame), |             PushPromise(ref frame) => write!(fmt, "Frame::PushPromise({:?})", frame), | ||||||
|             Settings(ref frame) => write!(fmt, "Frame::Settings({:?})", frame), |             Settings(ref frame) => write!(fmt, "Frame::Settings({:?})", frame), | ||||||
|             Ping(ref frame) => write!(fmt, "Frame::Ping({:?})", frame), |             Ping(ref frame) => write!(fmt, "Frame::Ping({:?})", frame), | ||||||
|  |             GoAway(ref frame) => write!(fmt, "Frame::GoAway({:?})", frame), | ||||||
|             WindowUpdate(ref frame) => write!(fmt, "Frame::WindowUpdate({:?})", frame), |             WindowUpdate(ref frame) => write!(fmt, "Frame::WindowUpdate({:?})", frame), | ||||||
|             Reset(ref frame) => write!(fmt, "Frame::Reset({:?})", frame), |             Reset(ref frame) => write!(fmt, "Frame::Reset({:?})", frame), | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -48,7 +48,7 @@ impl WindowUpdate { | |||||||
|  |  | ||||||
|     pub fn encode<B: BufMut>(&self, dst: &mut B) { |     pub fn encode<B: BufMut>(&self, dst: &mut B) { | ||||||
|         trace!("encoding WINDOW_UPDATE; id={:?}", self.stream_id); |         trace!("encoding WINDOW_UPDATE; id={:?}", self.stream_id); | ||||||
|         let head = Head::new(Kind::Ping, 0, self.stream_id); |         let head = Head::new(Kind::WindowUpdate, 0, self.stream_id); | ||||||
|         head.encode(4, dst); |         head.encode(4, dst); | ||||||
|         dst.put_u32::<BigEndian>(self.size_increment); |         dst.put_u32::<BigEndian>(self.size_increment); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -128,6 +128,12 @@ impl<T, P, B> Connection<T, P, B> | |||||||
|  |  | ||||||
|                     // TODO: ACK must be sent THEN settings applied. |                     // TODO: ACK must be sent THEN settings applied. | ||||||
|                 } |                 } | ||||||
|  |                 Some(GoAway(frame)) => { | ||||||
|  |                     // TODO: handle the last_stream_id. Also, should this be | ||||||
|  |                     // handled as an error? | ||||||
|  |                     let e = ConnectionError::Proto(frame.reason()); | ||||||
|  |                     return Ok(().into()); | ||||||
|  |                 } | ||||||
|                 Some(Ping(frame)) => { |                 Some(Ping(frame)) => { | ||||||
|                     trace!("recv PING; frame={:?}", frame); |                     trace!("recv PING; frame={:?}", frame); | ||||||
|                     self.ping_pong.recv_ping(frame); |                     self.ping_pong.recv_ping(frame); | ||||||
|   | |||||||
| @@ -64,7 +64,6 @@ impl<T> FramedRead<T> { | |||||||
|                 let _ = bytes.split_to(frame::HEADER_LEN); |                 let _ = bytes.split_to(frame::HEADER_LEN); | ||||||
|                 frame::Data::load(head, bytes)?.into() |                 frame::Data::load(head, bytes)?.into() | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             Kind::Headers => { |             Kind::Headers => { | ||||||
|                 let mut buf = Cursor::new(bytes); |                 let mut buf = Cursor::new(bytes); | ||||||
|                 buf.set_position(frame::HEADER_LEN as u64); |                 buf.set_position(frame::HEADER_LEN as u64); | ||||||
| @@ -80,16 +79,11 @@ impl<T> FramedRead<T> { | |||||||
|  |  | ||||||
|                 frame.into() |                 frame.into() | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             Kind::Reset => { |             Kind::Reset => { | ||||||
|                 frame::Reset::load(head, &bytes[frame::HEADER_LEN..])?.into() |                 frame::Reset::load(head, &bytes[frame::HEADER_LEN..])?.into() | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // TODO |  | ||||||
|  |  | ||||||
|             Kind::GoAway => { |             Kind::GoAway => { | ||||||
|                 let _todo = try!(frame::GoAway::load(&bytes[frame::HEADER_LEN..])); |                 frame::GoAway::load(&bytes[frame::HEADER_LEN..])?.into() | ||||||
|                 unimplemented!(); |  | ||||||
|             } |             } | ||||||
|             Kind::PushPromise => { |             Kind::PushPromise => { | ||||||
|                 frame::PushPromise::load(head, &bytes[frame::HEADER_LEN..])?.into() |                 frame::PushPromise::load(head, &bytes[frame::HEADER_LEN..])?.into() | ||||||
|   | |||||||
| @@ -141,6 +141,10 @@ impl<T, B> Sink for FramedWrite<T, B> | |||||||
|                 v.encode(self.buf.get_mut()); |                 v.encode(self.buf.get_mut()); | ||||||
|                 trace!("encoded settings; rem={:?}", self.buf.remaining()); |                 trace!("encoded settings; rem={:?}", self.buf.remaining()); | ||||||
|             } |             } | ||||||
|  |             Frame::GoAway(v) => { | ||||||
|  |                 v.encode(self.buf.get_mut()); | ||||||
|  |                 trace!("encoded go_away; rem={:?}", self.buf.remaining()); | ||||||
|  |             } | ||||||
|             Frame::Ping(v) => { |             Frame::Ping(v) => { | ||||||
|                 v.encode(self.buf.get_mut()); |                 v.encode(self.buf.get_mut()); | ||||||
|                 trace!("encoded ping; rem={:?}", self.buf.remaining()); |                 trace!("encoded ping; rem={:?}", self.buf.remaining()); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user