Remove P generic from type

This commit is contained in:
Carl Lerche
2017-08-08 22:11:11 -07:00
parent 6a84a93f2e
commit 26df3a3698
6 changed files with 129 additions and 137 deletions

View File

@@ -15,9 +15,6 @@ pub struct Handshake<T, B: IntoBuf = Bytes> {
inner: Box<Future<Item = Client<T, B>, Error = ConnectionError>>,
}
#[derive(Debug)]
pub(crate) struct Peer;
/// Marker type indicating a client peer
pub struct Client<T, B: IntoBuf> {
connection: Connection<T, Peer, B>,
@@ -25,19 +22,22 @@ pub struct Client<T, B: IntoBuf> {
#[derive(Debug)]
pub struct Stream<B: IntoBuf> {
inner: proto::StreamRef<Peer, B::Buf>,
inner: proto::StreamRef<B::Buf>,
}
#[derive(Debug)]
pub struct Body<B: IntoBuf> {
inner: proto::StreamRef<Peer, B::Buf>,
inner: proto::StreamRef<B::Buf>,
}
#[derive(Debug)]
pub struct Chunk<B: IntoBuf> {
inner: proto::Chunk<Peer, B::Buf>,
inner: proto::Chunk<B::Buf>,
}
#[derive(Debug)]
pub(crate) struct Peer;
impl<T> Client<T, Bytes>
where T: AsyncRead + AsyncWrite + 'static,
{
@@ -160,7 +160,7 @@ impl<B: IntoBuf> Stream<B> {
pub fn send_data(&mut self, data: B, end_of_stream: bool)
-> Result<(), ConnectionError>
{
self.inner.send_data(data.into_buf(), end_of_stream)
self.inner.send_data::<Peer>(data.into_buf(), end_of_stream)
}
/// Send trailers

View File

@@ -19,7 +19,7 @@ pub struct Connection<T, P, B: IntoBuf = Bytes> {
// TODO: Remove <B>
ping_pong: PingPong<B::Buf>,
settings: Settings,
streams: Streams<P, B::Buf>,
streams: Streams<B::Buf>,
_phantom: PhantomData<P>,
}
@@ -31,7 +31,7 @@ impl<T, P, B> Connection<T, P, B>
{
pub fn new(codec: Codec<T, B::Buf>) -> Connection<T, P, B> {
// TODO: Actually configure
let streams = Streams::new(streams::Config {
let streams = Streams::new::<P>(streams::Config {
max_remote_initiated: None,
init_remote_window_sz: DEFAULT_INITIAL_WINDOW_SIZE,
max_local_initiated: None,
@@ -123,7 +123,7 @@ impl<T, P, B> Connection<T, P, B>
Some(Headers(frame)) => {
trace!("recv HEADERS; frame={:?}", frame);
if let Some(frame) = try!(self.streams.recv_headers(frame)) {
if let Some(frame) = try!(self.streams.recv_headers::<P>(frame)) {
unimplemented!();
}
@@ -138,15 +138,15 @@ impl<T, P, B> Connection<T, P, B>
}
Some(Data(frame)) => {
trace!("recv DATA; frame={:?}", frame);
try!(self.streams.recv_data(frame));
try!(self.streams.recv_data::<P>(frame));
}
Some(Reset(frame)) => {
trace!("recv RST_STREAM; frame={:?}", frame);
try!(self.streams.recv_reset(frame));
try!(self.streams.recv_reset::<P>(frame));
}
Some(PushPromise(frame)) => {
trace!("recv PUSH_PROMISE; frame={:?}", frame);
self.streams.recv_push_promise(frame)?;
self.streams.recv_push_promise::<P>(frame)?;
}
Some(Settings(frame)) => {
trace!("recv SETTINGS; frame={:?}", frame);
@@ -263,7 +263,7 @@ impl<T, B> Connection<T, client::Peer, B>
{
/// Initialize a new HTTP/2.0 stream and send the message.
pub fn send_request(&mut self, request: Request<()>, end_of_stream: bool)
-> Result<StreamRef<client::Peer, B::Buf>, ConnectionError>
-> Result<StreamRef<B::Buf>, ConnectionError>
{
self.streams.send_request(request, end_of_stream)
}

View File

@@ -8,7 +8,7 @@ use std::collections::VecDeque;
use std::marker::PhantomData;
#[derive(Debug)]
pub(super) struct Recv<P, B> {
pub(super) struct Recv<B> {
/// Maximum number of remote initiated streams
max_streams: Option<usize>,
@@ -31,7 +31,7 @@ pub(super) struct Recv<P, B> {
/// Refused StreamId, this represents a frame that must be sent out.
refused: Option<StreamId>,
_p: PhantomData<(P, B)>,
_p: PhantomData<(B)>,
}
#[derive(Debug)]
@@ -46,10 +46,7 @@ struct Indices {
tail: store::Key,
}
impl<P, B> Recv<P, B>
where P: Peer,
B: Buf,
{
impl<B> Recv<B> where B: Buf {
pub fn new(config: &Config) -> Self {
Recv {
max_streams: config.max_remote_initiated,
@@ -66,10 +63,12 @@ impl<P, B> Recv<P, B>
/// Update state reflecting a new, remotely opened stream
///
/// Returns the stream state if successful. `None` if refused
pub fn open(&mut self, id: StreamId) -> Result<Option<Stream<B>>, ConnectionError> {
pub fn open<P: Peer>(&mut self, id: StreamId)
-> Result<Option<Stream<B>>, ConnectionError>
{
assert!(self.refused.is_none());
try!(self.ensure_can_open(id));
try!(self.ensure_can_open::<P>(id));
if !self.can_inc_num_streams() {
self.refused = Some(id);
@@ -79,8 +78,28 @@ impl<P, B> Recv<P, B>
Ok(Some(Stream::new(id)))
}
pub fn poll_response(&mut self, stream: &mut store::Ptr<B>)
-> Poll<Response<()>, ConnectionError> {
// If the buffer is not empty, then the first frame must be a HEADERS
// frame or the user violated the contract.
match stream.pending_recv.pop_front(&mut self.buffer) {
Some(Frame::Headers(v)) => {
// TODO: This error should probably be caught on receipt of the
// frame vs. now.
Ok(client::Peer::convert_poll_message(v)?.into())
}
Some(frame) => unimplemented!(),
None => {
stream.state.ensure_recv_open()?;
stream.recv_task = Some(task::current());
Ok(Async::NotReady)
}
}
}
/// Transition the stream state based on receiving headers
pub fn recv_headers(&mut self,
pub fn recv_headers<P: Peer>(&mut self,
frame: frame::Headers,
stream: &mut store::Ptr<B>)
-> Result<Option<frame::Headers>, ConnectionError>
@@ -155,11 +174,13 @@ impl<P, B> Recv<P, B>
Ok(())
}
pub fn recv_push_promise(&mut self, frame: frame::PushPromise, stream: &mut store::Ptr<B>)
pub fn recv_push_promise<P: Peer>(&mut self,
frame: frame::PushPromise,
stream: &mut store::Ptr<B>)
-> Result<(), ConnectionError>
{
// First, make sure that the values are legit
self.ensure_can_reserve(frame.promised_id())?;
self.ensure_can_reserve::<P>(frame.promised_id())?;
// Make sure that the stream state is valid
stream.state.ensure_recv_open()?;
@@ -241,7 +262,9 @@ impl<P, B> Recv<P, B>
}
/// Returns true if the remote peer can initiate a stream with the given ID.
fn ensure_can_open(&self, id: StreamId) -> Result<(), ConnectionError> {
fn ensure_can_open<P: Peer>(&self, id: StreamId)
-> Result<(), ConnectionError>
{
if !P::is_server() {
// Remote is a server and cannot open streams. PushPromise is
// registered by reserving, so does not go through this path.
@@ -257,7 +280,9 @@ impl<P, B> Recv<P, B>
}
/// Returns true if the remote peer can reserve a stream with the given ID.
fn ensure_can_reserve(&self, promised_id: StreamId) -> Result<(), ConnectionError> {
fn ensure_can_reserve<P: Peer>(&self, promised_id: StreamId)
-> Result<(), ConnectionError>
{
// TODO: Are there other rules?
if P::is_server() {
// The remote is a client and cannot reserve
@@ -400,27 +425,3 @@ impl<P, B> Recv<P, B>
unimplemented!();
}
}
impl<B> Recv<client::Peer, B>
where B: Buf,
{
pub fn poll_response(&mut self, stream: &mut store::Ptr<B>)
-> Poll<Response<()>, ConnectionError> {
// If the buffer is not empty, then the first frame must be a HEADERS
// frame or the user violated the contract.
match stream.pending_recv.pop_front(&mut self.buffer) {
Some(Frame::Headers(v)) => {
// TODO: This error should probably be caught on receipt of the
// frame vs. now.
Ok(client::Peer::convert_poll_message(v)?.into())
}
Some(frame) => unimplemented!(),
None => {
stream.state.ensure_recv_open()?;
stream.recv_task = Some(task::current());
Ok(Async::NotReady)
}
}
}
}

View File

@@ -10,7 +10,7 @@ use std::collections::VecDeque;
use std::marker::PhantomData;
#[derive(Debug)]
pub(super) struct Send<P, B> {
pub(super) struct Send<B> {
/// Maximum number of locally initiated streams
max_streams: Option<usize>,
@@ -36,15 +36,12 @@ pub(super) struct Send<P, B> {
/// be notified later. Access to poll_window_update must not be shared across tasks,
/// as we only track a single task (and *not* i.e. a task per stream id).
blocked: Option<task::Task>,
_p: PhantomData<P>,
}
impl<P, B> Send<P, B>
where P: Peer,
B: Buf,
{
pub fn new(config: &Config) -> Self {
impl<B> Send<B> where B: Buf {
/// Create a new `Send`
pub fn new<P: Peer>(config: &Config) -> Self {
let next_stream_id = if P::is_server() {
2
} else {
@@ -60,15 +57,16 @@ impl<P, B> Send<P, B>
prioritize: Prioritize::new(),
pending_window_updates: VecDeque::new(),
blocked: None,
_p: PhantomData,
}
}
/// Update state reflecting a new, locally opened stream
///
/// Returns the stream state if successful. `None` if refused
pub fn open(&mut self) -> Result<Stream<B>, ConnectionError> {
try!(self.ensure_can_open());
pub fn open<P: Peer>(&mut self)
-> Result<Stream<B>, ConnectionError>
{
try!(self.ensure_can_open::<P>());
if let Some(max) = self.max_streams {
if max <= self.num_streams {
@@ -229,7 +227,7 @@ impl<P, B> Send<P, B>
}
/// Returns true if the local actor can initiate a stream with the given ID.
fn ensure_can_open(&self) -> Result<(), ConnectionError> {
fn ensure_can_open<P: Peer>(&self) -> Result<(), ConnectionError> {
if P::is_server() {
// Servers cannot open streams. PushPromise must first be reserved.
return Err(UnexpectedFrameType.into());

View File

@@ -2,28 +2,28 @@ use client;
use proto::*;
use super::*;
use std::marker::PhantomData;
use std::sync::{Arc, Mutex};
// TODO: All the VecDeques should become linked lists using the State
// values.
#[derive(Debug)]
pub struct Streams<P, B> {
inner: Arc<Mutex<Inner<P, B>>>,
pub struct Streams<B> {
inner: Arc<Mutex<Inner<B>>>,
}
/// Reference to the stream state
#[derive(Debug)]
pub struct StreamRef<P, B> {
inner: Arc<Mutex<Inner<P, B>>>,
pub struct StreamRef<B> {
inner: Arc<Mutex<Inner<B>>>,
key: store::Key,
}
#[derive(Debug)]
pub struct Chunk<P, B>
where P: Peer,
B: Buf,
pub struct Chunk<B>
where B: Buf,
{
inner: Arc<Mutex<Inner<P, B>>>,
inner: Arc<Mutex<Inner<B>>>,
recv: recv::Chunk,
}
@@ -32,30 +32,29 @@ pub struct Chunk<P, B>
///
/// TODO: better name
#[derive(Debug)]
struct Inner<P, B> {
actions: Actions<P, B>,
struct Inner<B> {
actions: Actions<B>,
store: Store<B>,
}
#[derive(Debug)]
struct Actions<P, B> {
struct Actions<B> {
/// Manages state transitions initiated by receiving frames
recv: Recv<P, B>,
recv: Recv<B>,
/// Manages state transitions initiated by sending frames
send: Send<P, B>,
send: Send<B>,
}
impl<P, B> Streams<P, B>
where P: Peer,
B: Buf,
impl<B> Streams<B>
where B: Buf,
{
pub fn new(config: Config) -> Self {
pub fn new<P: Peer>(config: Config) -> Self {
Streams {
inner: Arc::new(Mutex::new(Inner {
actions: Actions {
recv: Recv::new(&config),
send: Send::new(&config),
send: Send::new::<P>(&config),
},
store: Store::new(),
})),
@@ -63,7 +62,7 @@ impl<P, B> Streams<P, B>
}
/// Process inbound headers
pub fn recv_headers(&mut self, frame: frame::Headers)
pub fn recv_headers<P: Peer>(&mut self, frame: frame::Headers)
-> Result<Option<frame::Headers>, ConnectionError>
{
let id = frame.stream_id();
@@ -81,7 +80,7 @@ impl<P, B> Streams<P, B>
return Err(ProtocolError.into());
}
match try!(me.actions.recv.open(id)) {
match try!(me.actions.recv.open::<P>(id)) {
Some(stream) => e.insert(stream),
None => return Ok(None),
}
@@ -90,7 +89,7 @@ impl<P, B> Streams<P, B>
let stream = me.store.resolve(key);
me.actions.transition(stream, |actions, stream| {
me.actions.transition::<P, _, _>(stream, |actions, stream| {
if frame.is_trailers() {
unimplemented!();
/*
@@ -102,12 +101,12 @@ impl<P, B> Streams<P, B>
try!(me.actions.recv.recv_eos(stream));
*/
} else {
actions.recv.recv_headers(frame, stream)
actions.recv.recv_headers::<P>(frame, stream)
}
})
}
pub fn recv_data(&mut self, frame: frame::Data)
pub fn recv_data<P: Peer>(&mut self, frame: frame::Data)
-> Result<(), ConnectionError>
{
let mut me = self.inner.lock().unwrap();
@@ -120,12 +119,12 @@ impl<P, B> Streams<P, B>
None => return Err(ProtocolError.into()),
};
me.actions.transition(stream, |actions, stream| {
me.actions.transition::<P, _, _>(stream, |actions, stream| {
actions.recv.recv_data(frame, stream)
})
}
pub fn recv_reset(&mut self, frame: frame::Reset)
pub fn recv_reset<P: Peer>(&mut self, frame: frame::Reset)
-> Result<(), ConnectionError>
{
let mut me = self.inner.lock().unwrap();
@@ -139,7 +138,7 @@ impl<P, B> Streams<P, B>
None => return Ok(()),
};
me.actions.transition(stream, |actions, stream| {
me.actions.transition::<P, _, _>(stream, |actions, stream| {
actions.recv.recv_reset(frame, stream)?;
assert!(stream.state.is_closed());
Ok(())
@@ -173,7 +172,7 @@ impl<P, B> Streams<P, B>
Ok(())
}
pub fn recv_push_promise(&mut self, frame: frame::PushPromise)
pub fn recv_push_promise<P: Peer>(&mut self, frame: frame::PushPromise)
-> Result<(), ConnectionError>
{
let mut me = self.inner.lock().unwrap();
@@ -186,7 +185,7 @@ impl<P, B> Streams<P, B>
None => return Err(ProtocolError.into()),
};
me.actions.recv.recv_push_promise(frame, &mut stream)
me.actions.recv.recv_push_promise::<P>(frame, &mut stream)
}
pub fn send_headers(&mut self, headers: frame::Headers)
@@ -274,11 +273,11 @@ impl<P, B> Streams<P, B>
}
}
impl<B> Streams<client::Peer, B>
impl<B> Streams<B>
where B: Buf,
{
pub fn send_request(&mut self, request: Request<()>, end_of_stream: bool)
-> Result<StreamRef<client::Peer, B>, ConnectionError>
-> Result<StreamRef<B>, ConnectionError>
{
// TODO: There is a hazard with assigning a stream ID before the
// prioritize layer. If prioritization reorders new streams, this
@@ -290,7 +289,7 @@ impl<B> Streams<client::Peer, B>
let me = &mut *me;
// Initialize a new stream. This fails if the connection is at capacity.
let mut stream = me.actions.send.open()?;
let mut stream = me.actions.send.open::<client::Peer>()?;
// Convert the message
let headers = client::Peer::convert_send_message(
@@ -316,11 +315,10 @@ impl<B> Streams<client::Peer, B>
// ===== impl StreamRef =====
impl<P, B> StreamRef<P, B>
where P: Peer,
B: Buf,
impl<B> StreamRef<B>
where B: Buf,
{
pub fn send_data(&mut self, data: B, end_of_stream: bool)
pub fn send_data<P: Peer>(&mut self, data: B, end_of_stream: bool)
-> Result<(), ConnectionError>
{
let mut me = self.inner.lock().unwrap();
@@ -331,13 +329,22 @@ impl<P, B> StreamRef<P, B>
// Create the data frame
let frame = frame::Data::from_buf(stream.id, data, end_of_stream);
me.actions.transition(stream, |actions, stream| {
me.actions.transition::<P, _, _>(stream, |actions, stream| {
// Send the data frame
actions.send.send_data(frame, stream)
})
}
pub fn poll_data(&mut self) -> Poll<Option<Chunk<P, B>>, ConnectionError> {
pub fn poll_response(&mut self) -> Poll<Response<()>, ConnectionError> {
let mut me = self.inner.lock().unwrap();
let me = &mut *me;
let mut stream = me.store.resolve(self.key);
me.actions.recv.poll_response(&mut stream)
}
pub fn poll_data(&mut self) -> Poll<Option<Chunk<B>>, ConnectionError> {
let recv = {
let mut me = self.inner.lock().unwrap();
let me = &mut *me;
@@ -359,22 +366,7 @@ impl<P, B> StreamRef<P, B>
}
}
impl<B> StreamRef<client::Peer, B>
where B: Buf,
{
pub fn poll_response(&mut self) -> Poll<Response<()>, ConnectionError> {
let mut me = self.inner.lock().unwrap();
let me = &mut *me;
let mut stream = me.store.resolve(self.key);
me.actions.recv.poll_response(&mut stream)
}
}
impl<P, B> Clone for StreamRef<P, B> {
impl<B> Clone for StreamRef<B> {
fn clone(&self) -> Self {
StreamRef {
inner: self.inner.clone(),
@@ -385,9 +377,8 @@ impl<P, B> Clone for StreamRef<P, B> {
// ===== impl Chunk =====
impl<P, B> Chunk<P, B>
where P: Peer,
B: Buf,
impl<B> Chunk<B>
where B: Buf,
{
// TODO: Come up w/ a better API
pub fn pop_bytes(&mut self) -> Option<Bytes> {
@@ -398,9 +389,8 @@ impl<P, B> Chunk<P, B>
}
}
impl<P, B> Drop for Chunk<P, B>
where P: Peer,
B: Buf,
impl<B> Drop for Chunk<B>
where B: Buf,
{
fn drop(&mut self) {
let mut me = self.inner.lock().unwrap();
@@ -413,32 +403,32 @@ impl<P, B> Drop for Chunk<P, B>
// ===== impl Actions =====
impl<P, B> Actions<P, B>
where P: Peer,
B: Buf,
impl<B> Actions<B>
where B: Buf,
{
fn dec_num_streams(&mut self, id: StreamId) {
if self.is_local_init(id) {
fn dec_num_streams<P: Peer>(&mut self, id: StreamId) {
if self.is_local_init::<P>(id) {
self.send.dec_num_streams();
} else {
self.recv.dec_num_streams();
}
}
fn is_local_init(&self, id: StreamId) -> bool {
fn is_local_init<P: Peer>(&self, id: StreamId) -> bool {
assert!(!id.is_zero());
P::is_server() == id.is_server_initiated()
}
fn transition<F, U>(&mut self, mut stream: store::Ptr<B>, f: F) -> U
fn transition<P, F, U>(&mut self, mut stream: store::Ptr<B>, f: F) -> U
where F: FnOnce(&mut Self, &mut store::Ptr<B>) -> U,
P: Peer,
{
let is_counted = stream.state.is_counted();
let ret = f(self, &mut stream);
if is_counted && stream.state.is_closed() {
self.dec_num_streams(stream.id);
self.dec_num_streams::<P>(stream.id);
}
ret

View File

@@ -1,5 +1,3 @@
#![allow(warnings)]
use {frame, proto, Peer, ConnectionError, StreamId};
use http;
@@ -12,14 +10,19 @@ use std::fmt;
/// In progress H2 connection binding
pub struct Handshake<T, B: IntoBuf = Bytes> {
// TODO: unbox
inner: Box<Future<Item = Connection<T, B>, Error = ConnectionError>>,
inner: Box<Future<Item = Server<T, B>, Error = ConnectionError>>,
}
/// Marker type indicating a client peer
#[derive(Debug)]
pub struct Server;
pub struct Server<T, B: IntoBuf> {
connection: Connection<T, Peer, B>,
}
pub type Connection<T, B = Bytes> = super::Connection<T, Server, B>;
#[derive(Debug)]
pub struct Stream<B: IntoBuf> {
inner: proto::StreamRef<Peer, B::Buf>,
}
/// Flush a Sink
struct Flush<T> {