Fix multiplex waking and make it so that inbound streams can be handled concurrently with negotiating the outbound stream

This commit is contained in:
Vurich
2017-12-14 17:37:32 +01:00
parent 5ddda08170
commit 19f0c8f3ef
12 changed files with 914 additions and 301 deletions

View File

@@ -15,3 +15,4 @@ rand = "0.3.17"
libp2p-swarm = { path = "../libp2p-swarm" }
varint = { path = "../varint-rs" }
error-chain = "0.11.0"
futures-mutex = { path = "../futures-mutex" }

View File

@@ -23,6 +23,7 @@ extern crate bytes;
#[macro_use]
extern crate error_chain;
extern crate futures;
extern crate futures_mutex;
extern crate libp2p_swarm as swarm;
extern crate num_bigint;
extern crate num_traits;
@@ -42,7 +43,7 @@ use futures::future::{self, FutureResult};
use header::MultiplexHeader;
use swarm::muxing::StreamMuxer;
use swarm::{ConnectionUpgrade, Endpoint};
use parking_lot::Mutex;
use futures_mutex::Mutex;
use read::{read_stream, MultiplexReadState};
use shared::{buf_from_slice, ByteBuf, MultiplexShared};
use std::iter;
@@ -74,7 +75,7 @@ pub struct Substream<T> {
impl<T> Drop for Substream<T> {
fn drop(&mut self) {
let mut lock = self.state.lock();
let mut lock = self.state.lock().wait().expect("This should never fail");
lock.close_stream(self.id);
}
@@ -110,9 +111,9 @@ impl<T> Substream<T> {
// TODO: We always zero the buffer, we should delegate to the inner stream.
impl<T: AsyncRead> Read for Substream<T> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut lock = match self.state.try_lock() {
Some(lock) => lock,
None => return Err(io::ErrorKind::WouldBlock.into()),
let mut lock = match self.state.poll_lock() {
Async::Ready(lock) => lock,
Async::NotReady => return Err(io::ErrorKind::WouldBlock.into()),
};
read_stream(&mut lock, (self.id, buf))
@@ -123,7 +124,10 @@ impl<T: AsyncRead> AsyncRead for Substream<T> {}
impl<T: AsyncWrite> Write for Substream<T> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let mut lock = self.state.try_lock().ok_or(io::ErrorKind::WouldBlock)?;
let mut lock = match self.state.poll_lock() {
Async::Ready(lock) => lock,
Async::NotReady => return Err(io::ErrorKind::WouldBlock.into()),
};
let mut buffer = self.buffer
.take()
@@ -143,11 +147,12 @@ impl<T: AsyncWrite> Write for Substream<T> {
}
fn flush(&mut self) -> io::Result<()> {
self.state
.try_lock()
.ok_or(io::ErrorKind::WouldBlock)?
.stream
.flush()
let mut lock = match self.state.poll_lock() {
Async::Ready(lock) => lock,
Async::NotReady => return Err(io::ErrorKind::WouldBlock.into()),
};
lock.stream.flush()
}
}
@@ -167,9 +172,9 @@ impl<T: AsyncRead> Future for InboundFuture<T> {
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let mut lock = match self.state.try_lock() {
Some(lock) => lock,
None => return Ok(Async::NotReady),
let mut lock = match self.state.poll_lock() {
Async::Ready(lock) => lock,
Async::NotReady => return Ok(Async::NotReady),
};
// Attempt to make progress, but don't block if we can't
@@ -217,7 +222,7 @@ impl<T> OutboundFuture<T> {
}
fn nonce_to_id(id: usize, end: Endpoint) -> u32 {
id as u32 * 2 + if end == Endpoint::Dialer { 50 } else { 0 }
id as u32 * 2 + if end == Endpoint::Dialer { 0 } else { 1 }
}
impl<T: AsyncWrite> Future for OutboundFuture<T> {
@@ -225,9 +230,9 @@ impl<T: AsyncWrite> Future for OutboundFuture<T> {
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let mut lock = match self.state.try_lock() {
Some(lock) => lock,
None => return Ok(Async::NotReady),
let mut lock = match self.state.poll_lock() {
Async::Ready(lock) => lock,
Async::NotReady => return Ok(Async::NotReady),
};
loop {
@@ -380,7 +385,7 @@ mod tests {
Some(id.to_string())
);
let stream = io::Cursor::new(mplex.state.lock().stream.get_ref().clone());
let stream = io::Cursor::new(mplex.state.lock().wait().unwrap().stream.get_ref().clone());
let mplex = Multiplex::listen(stream);
@@ -422,7 +427,7 @@ mod tests {
);
}
let stream = io::Cursor::new(mplex.state.lock().stream.get_ref().clone());
let stream = io::Cursor::new(mplex.state.lock().wait().unwrap().stream.get_ref().clone());
let mplex = Multiplex::listen(stream);

View File

@@ -116,7 +116,7 @@ pub fn read_stream<'a, O: Into<Option<(u32, &'a mut [u8])>>, T: AsyncRead>(
let header = if let Some(header) = header {
header
} else {
return Ok(0);
return Ok(on_block.unwrap_or(0));
};
let MultiplexHeader {
@@ -183,7 +183,7 @@ pub fn read_stream<'a, O: Into<Option<(u32, &'a mut [u8])>>, T: AsyncRead>(
let length = if let Some(length) = length {
length
} else {
return Ok(0);
return Ok(on_block.unwrap_or(0));
};
lock.read_state = match next {
@@ -208,7 +208,8 @@ pub fn read_stream<'a, O: Into<Option<(u32, &'a mut [u8])>>, T: AsyncRead>(
let is_open = lock.open_streams
.get(&substream_id)
.map(SubstreamMetadata::open)
.unwrap_or_else(|| lock.to_open.contains_key(&substream_id));
.unwrap_or(false);
//.unwrap_or_else(|| lock.to_open.contains_key(&substream_id));
if is_open {
Some(MultiplexReadState::ParsingMessageBody {
@@ -286,20 +287,16 @@ pub fn read_stream<'a, O: Into<Option<(u32, &'a mut [u8])>>, T: AsyncRead>(
if remaining_bytes == 0 {
lock.read_state = None;
return on_block;
} else if substream_id == *id {
let number_read = *on_block.as_ref().unwrap_or(&0);
if buf.len() == 0 {
return Ok(0);
} else if number_read >= buf.len() {
if number_read >= buf.len() {
lock.read_state = Some(ParsingMessageBody {
substream_id,
remaining_bytes,
});
return on_block;
return Ok(number_read);
}
let read_result = {

View File

@@ -92,6 +92,10 @@ pub fn write_stream<T: AsyncWrite>(
let id = write_request.header.substream_id;
if buf.get_ref().len() as u64 - buf.position() == 0 {
return Ok(0);
}
match (request.request_type, write_request.request_type) {
(RequestType::Substream, RequestType::Substream) if request.header.substream_id != id => {
use std::mem;