Enforce monotonic stream IDs for push promises (#275)
Previously, monotonic stream IDs (spec 5.1.1) for push promises were not enforced. This was due to push promises going through an entirely separate code path than normally initiated streams. This patch unifies the code path for initializing streams via both HEADERS and PUSH_PROMISE. This is done by first calling `recv.open` in both cases. Closes #272
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
use codec::RecvError;
|
||||
use error::Reason;
|
||||
use frame::{Headers, StreamId};
|
||||
use proto::Open;
|
||||
|
||||
use http::{Request, Response};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
/// Either a Client or a Server
|
||||
pub trait Peer {
|
||||
pub(crate) trait Peer {
|
||||
/// Message type polled from the transport
|
||||
type Poll: fmt::Debug;
|
||||
|
||||
@@ -27,7 +28,7 @@ pub trait Peer {
|
||||
///
|
||||
/// This is used internally to avoid incurring a generic on all internal types.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum Dyn {
|
||||
pub(crate) enum Dyn {
|
||||
Client,
|
||||
Server,
|
||||
}
|
||||
@@ -61,20 +62,23 @@ impl Dyn {
|
||||
}
|
||||
|
||||
/// Returns true if the remote peer can initiate a stream with the given ID.
|
||||
pub fn ensure_can_open(&self, id: StreamId) -> Result<(), RecvError> {
|
||||
if !self.is_server() {
|
||||
trace!("Cannot open stream {:?} - not server, PROTOCOL_ERROR", id);
|
||||
// Remote is a server and cannot open streams. PushPromise is
|
||||
// registered by reserving, so does not go through this path.
|
||||
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||
}
|
||||
pub fn ensure_can_open(&self, id: StreamId, mode: Open) -> Result<(), RecvError> {
|
||||
if self.is_server() {
|
||||
// Ensure that the ID is a valid client initiated ID
|
||||
if mode.is_push_promise() || !id.is_client_initiated() {
|
||||
trace!("Cannot open stream {:?} - not client initiated, PROTOCOL_ERROR", id);
|
||||
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||
}
|
||||
|
||||
// Ensure that the ID is a valid server initiated ID
|
||||
if !id.is_client_initiated() {
|
||||
trace!("Cannot open stream {:?} - not client initiated, PROTOCOL_ERROR", id);
|
||||
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
// Ensure that the ID is a valid server initiated ID
|
||||
if !mode.is_push_promise() || !id.is_server_initiated() {
|
||||
trace!("Cannot open stream {:?} - not server initiated, PROTOCOL_ERROR", id);
|
||||
return Err(RecvError::Connection(Reason::PROTOCOL_ERROR));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user