Streams receiving peer reset clear pending send (#238)
Because streams that were being peer reset were not clearing pending send frames / buffered_send_data, they were not being counted towards the concurrency limit.
This commit is contained in:
		
				
					committed by
					
						 Sean McArthur
						Sean McArthur
					
				
			
			
				
	
			
			
			
						parent
						
							267789da92
						
					
				
				
					commit
					f8baeb7211
				
			| @@ -555,6 +555,9 @@ impl Prioritize { | ||||
|         while let Some(frame) = stream.pending_send.pop_front(buffer) { | ||||
|             trace!("dropping; frame={:?}", frame); | ||||
|         } | ||||
|  | ||||
|         stream.buffered_send_data = 0; | ||||
|         stream.requested_send_capacity = 0; | ||||
|     } | ||||
|  | ||||
|     fn pop_frame<B>( | ||||
| @@ -574,6 +577,14 @@ impl Prioritize { | ||||
|                 Some(mut stream) => { | ||||
|                     trace!("pop_frame; stream={:?}", stream.id); | ||||
|  | ||||
|                     // If the stream receives a RESET from the peer, it may have | ||||
|                     // had data buffered to be sent, but all the frames are cleared | ||||
|                     // in clear_queue(). Instead of doing O(N) traversal through queue | ||||
|                     // to remove, lets just ignore peer_reset streams here. | ||||
|                     if stream.state.is_peer_reset() { | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     // It's possible that this stream, besides having data to send, | ||||
|                     // is also queued to send a reset, and thus is already in the queue | ||||
|                     // to wait for "some time" after a reset. | ||||
|   | ||||
| @@ -588,16 +588,12 @@ impl Recv { | ||||
|     } | ||||
|  | ||||
|     /// Handle remote sending an explicit RST_STREAM. | ||||
|     pub fn recv_reset( | ||||
|         &mut self, | ||||
|         frame: frame::Reset, | ||||
|         stream: &mut Stream, | ||||
|     ) -> Result<(), RecvError> { | ||||
|     pub fn recv_reset(&mut self, frame: frame::Reset, stream: &mut Stream) { | ||||
|         // Notify the stream | ||||
|         stream.state.recv_reset(frame.reason()); | ||||
|  | ||||
|         stream.notify_send(); | ||||
|         stream.notify_recv(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     /// Handle a received error | ||||
|   | ||||
| @@ -283,6 +283,15 @@ impl Send { | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     pub fn recv_reset<B>( | ||||
|         &mut self, | ||||
|         buffer: &mut Buffer<Frame<B>>, | ||||
|         stream: &mut store::Ptr | ||||
|     ) { | ||||
|         // Clear all pending outbound frames | ||||
|         self.prioritize.clear_queue(buffer, stream); | ||||
|     } | ||||
|  | ||||
|     pub fn recv_err<B>( | ||||
|         &mut self, | ||||
|         buffer: &mut Buffer<Frame<B>>, | ||||
|   | ||||
| @@ -301,6 +301,13 @@ impl State { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn is_peer_reset(&self) -> bool { | ||||
|         match self.inner { | ||||
|             Closed(Cause::Proto(_)) => true, | ||||
|             _ => false, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Returns true if the stream is already reset. | ||||
|     pub fn is_reset(&self) -> bool { | ||||
|         match self.inner { | ||||
|   | ||||
| @@ -255,10 +255,14 @@ where | ||||
|             }, | ||||
|         }; | ||||
|  | ||||
|         let mut send_buffer = self.send_buffer.inner.lock().unwrap(); | ||||
|         let send_buffer = &mut *send_buffer; | ||||
|  | ||||
|         let actions = &mut me.actions; | ||||
|  | ||||
|         me.counts.transition(stream, |_, stream| { | ||||
|             actions.recv.recv_reset(frame, stream)?; | ||||
|             actions.recv.recv_reset(frame, stream); | ||||
|             actions.send.recv_reset(send_buffer, stream); | ||||
|             assert!(stream.state.is_closed()); | ||||
|             Ok(()) | ||||
|         }) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user