mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-08-01 01:11:58 +00:00
Fix multiplex waking and make it so that inbound streams can be handled concurrently with negotiating the outbound stream
This commit is contained in:
@@ -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" }
|
@@ -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);
|
||||
|
||||
|
@@ -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 = {
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user