Add test and assertion for idle state handling (#160)
This commit is contained in:
		
				
					committed by
					
						 Carl Lerche
						Carl Lerche
					
				
			
			
				
	
			
			
			
						parent
						
							b1d282799b
						
					
				
				
					commit
					8a1c4d3d52
				
			| @@ -1,7 +1,7 @@ | ||||
| use super::*; | ||||
| use super::store::Resolve; | ||||
|  | ||||
| use frame::Reason; | ||||
| use frame::{Reason, StreamId}; | ||||
|  | ||||
| use codec::UserError; | ||||
| use codec::UserError::*; | ||||
| @@ -11,9 +11,18 @@ use bytes::buf::Take; | ||||
| use std::{cmp, fmt}; | ||||
| use std::io; | ||||
|  | ||||
| /// # Warning | ||||
| /// | ||||
| /// Queued streans are ordered by stream ID, as we need to ensure that | ||||
| /// lower-numbered streams are sent headers before higher-numbered ones. | ||||
| /// This is because "idle" stream IDs – those which have been initiated but | ||||
| /// have yet to receive frames – will be implicitly closed on receipt of a | ||||
| /// frame on a higher stream ID. If these queues was not ordered by stream | ||||
| /// IDs, some mechanism would be necessary to ensure that the lowest-numberedh] | ||||
| /// idle stream is opened first. | ||||
| #[derive(Debug)] | ||||
| pub(super) struct Prioritize { | ||||
|     /// Queue of streams waiting for socket capacity to send a frame | ||||
|     /// Queue of streams waiting for socket capacity to send a frame. | ||||
|     pending_send: store::Queue<stream::NextSend>, | ||||
|  | ||||
|     /// Queue of streams waiting for window capacity to produce data. | ||||
| @@ -24,6 +33,9 @@ pub(super) struct Prioritize { | ||||
|  | ||||
|     /// Connection level flow control governing sent data | ||||
|     flow: FlowControl, | ||||
|  | ||||
|     /// Stream ID of the last stream opened. | ||||
|     last_opened_id: StreamId, | ||||
| } | ||||
|  | ||||
| pub(crate) struct Prioritized<B> { | ||||
| @@ -55,6 +67,7 @@ impl Prioritize { | ||||
|             pending_capacity: store::Queue::new(), | ||||
|             pending_open: store::Queue::new(), | ||||
|             flow: flow, | ||||
|             last_opened_id: StreamId::ZERO | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -617,6 +630,11 @@ impl Prioritize { | ||||
|  | ||||
|                     trace!("pop_frame; frame={:?}", frame); | ||||
|  | ||||
|                     if cfg!(debug_assertions) && stream.state.is_idle() { | ||||
|                         debug_assert!(stream.id > self.last_opened_id); | ||||
|                         self.last_opened_id = stream.id; | ||||
|                     } | ||||
|  | ||||
|                     if !stream.pending_send.is_empty() || stream.state.is_canceled() { | ||||
|                         // TODO: Only requeue the sender IF it is ready to send | ||||
|                         // the next frame. i.e. don't requeue it if the next | ||||
| @@ -640,6 +658,7 @@ impl Prioritize { | ||||
|         while counts.can_inc_num_send_streams() { | ||||
|             if let Some(mut stream) = self.pending_open.pop(store) { | ||||
|                 trace!("schedule_pending_open; stream={:?}", stream.id); | ||||
|  | ||||
|                 counts.inc_num_send_streams(); | ||||
|                 self.pending_send.push(&mut stream); | ||||
|                 if let Some(task) = stream.open_task.take() { | ||||
|   | ||||
| @@ -331,6 +331,13 @@ impl State { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn is_idle(&self) -> bool { | ||||
|         match self.inner { | ||||
|             Idle => true, | ||||
|             _ => false, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn ensure_recv_open(&self) -> Result<bool, proto::Error> { | ||||
|         use std::io; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user