notify stream refs when the connection receives EOF (#176)
This commit is contained in:
		| @@ -277,8 +277,8 @@ where | |||||||
|                     // TODO: handle |                     // TODO: handle | ||||||
|                 }, |                 }, | ||||||
|                 None => { |                 None => { | ||||||
|                     // TODO: Is this correct? |  | ||||||
|                     trace!("codec closed"); |                     trace!("codec closed"); | ||||||
|  |                     self.streams.recv_eof(); | ||||||
|                     return Ok(Async::Ready(())); |                     return Ok(Async::Ready(())); | ||||||
|                 }, |                 }, | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -497,6 +497,11 @@ impl Recv { | |||||||
|         stream.notify_recv(); |         stream.notify_recv(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     pub fn recv_eof(&mut self, stream: &mut Stream) { | ||||||
|  |         stream.state.recv_eof(); | ||||||
|  |         stream.notify_recv(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     fn next_stream_id(&self) -> Result<StreamId, RecvError> { |     fn next_stream_id(&self) -> Result<StreamId, RecvError> { | ||||||
|         if let Ok(id) = self.next_stream_id { |         if let Ok(id) = self.next_stream_id { | ||||||
|             Ok(id) |             Ok(id) | ||||||
|   | |||||||
| @@ -223,6 +223,16 @@ impl State { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     pub fn recv_eof(&mut self) { | ||||||
|  |         match self.inner { | ||||||
|  |             Closed(..) => {}, | ||||||
|  |             s => { | ||||||
|  |                 trace!("recv_eof; state={:?}", s); | ||||||
|  |                 self.inner = Closed(Some(Cause::Io)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /// Indicates that the local side will not send more data to the local. |     /// Indicates that the local side will not send more data to the local. | ||||||
|     pub fn send_close(&mut self) { |     pub fn send_close(&mut self) { | ||||||
|         match self.inner { |         match self.inner { | ||||||
|   | |||||||
| @@ -272,6 +272,23 @@ where | |||||||
|         actions.conn_error = Some(err); |         actions.conn_error = Some(err); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     pub fn recv_eof(&mut self) { | ||||||
|  |         let mut me = self.inner.lock().unwrap(); | ||||||
|  |         let me = &mut *me; | ||||||
|  |  | ||||||
|  |         let actions = &mut me.actions; | ||||||
|  |         let counts = &mut me.counts; | ||||||
|  |  | ||||||
|  |         me.store | ||||||
|  |             .for_each(|stream| { | ||||||
|  |                 counts.transition(stream, |_, stream| { | ||||||
|  |                     actions.recv.recv_eof(stream); | ||||||
|  |                     Ok::<_, ()>(()) | ||||||
|  |                 }) | ||||||
|  |             }) | ||||||
|  |             .expect("recv_eof"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     pub fn last_processed_id(&self) -> StreamId { |     pub fn last_processed_id(&self) -> StreamId { | ||||||
|         self.inner.lock().unwrap().actions.recv.last_processed_id() |         self.inner.lock().unwrap().actions.recv.last_processed_id() | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -319,6 +319,49 @@ fn request_with_connection_headers() { | |||||||
|     client.join(srv).wait().expect("wait"); |     client.join(srv).wait().expect("wait"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[test] | ||||||
|  | fn connection_close_notifies_response_future() { | ||||||
|  |     let _ = ::env_logger::init(); | ||||||
|  |     let (io, srv) = mock::new(); | ||||||
|  |  | ||||||
|  |     let srv = srv.assert_client_handshake() | ||||||
|  |         .unwrap() | ||||||
|  |         .recv_settings() | ||||||
|  |         .recv_frame( | ||||||
|  |             frames::headers(1) | ||||||
|  |                 .request("GET", "https://http2.akamai.com/") | ||||||
|  |                 .eos(), | ||||||
|  |         ) | ||||||
|  |         // don't send any response, just close | ||||||
|  |         .close(); | ||||||
|  |  | ||||||
|  |     let client = Client::handshake(io) | ||||||
|  |         .expect("handshake") | ||||||
|  |         .and_then(|(mut client, conn)| { | ||||||
|  |             let request = Request::builder() | ||||||
|  |                 .uri("https://http2.akamai.com/") | ||||||
|  |                 .body(()) | ||||||
|  |                 .unwrap(); | ||||||
|  |  | ||||||
|  |             let req = client | ||||||
|  |                 .send_request(request, true) | ||||||
|  |                 .expect("send_request1") | ||||||
|  |                 .0 | ||||||
|  |                 .then(|res| { | ||||||
|  |                     let err = res.expect_err("response"); | ||||||
|  |                     assert_eq!( | ||||||
|  |                         err.to_string(), | ||||||
|  |                         "broken pipe" | ||||||
|  |                     ); | ||||||
|  |                     Ok(()) | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             conn.expect("conn").join(req) | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |     client.join(srv).wait().expect("wait"); | ||||||
|  | } | ||||||
|  |  | ||||||
| #[test] | #[test] | ||||||
| fn sending_request_on_closed_connection() { | fn sending_request_on_closed_connection() { | ||||||
|     let _ = ::env_logger::init(); |     let _ = ::env_logger::init(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user