Skip to content

Commit f195925

Browse files
authored
multistream-select: Less allocations. (#800)
1 parent aedf9c0 commit f195925

File tree

9 files changed

+460
-365
lines changed

9 files changed

+460
-365
lines changed

core/src/upgrade/apply.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ type NameWrapIter<I> =
224224
std::iter::Map<I, fn(<I as Iterator>::Item) -> NameWrap<<I as Iterator>::Item>>;
225225

226226
/// Wrapper type to expose an `AsRef<[u8]>` impl for all types implementing `ProtocolName`.
227+
#[derive(Clone)]
227228
struct NameWrap<N>(N);
228229

229230
impl<N: ProtocolName> AsRef<[u8]> for NameWrap<N> {

core/src/upgrade/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ impl<T: AsRef<[u8]>> ProtocolName for T {
9191
/// or both.
9292
pub trait UpgradeInfo {
9393
/// Opaque type representing a negotiable protocol.
94-
type Info: ProtocolName;
94+
type Info: ProtocolName + Clone;
9595
/// Iterator returned by `protocol_info`.
9696
type InfoIter: IntoIterator<Item = Self::Info>;
9797

misc/multistream-select/src/dialer_select.rs

Lines changed: 186 additions & 106 deletions
Large diffs are not rendered by default.

misc/multistream-select/src/length_delimited.rs

Lines changed: 65 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,30 @@
1818
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1919
// DEALINGS IN THE SOFTWARE.
2020

21+
use bytes::Bytes;
2122
use futures::{Async, Poll, Sink, StartSend, Stream};
2223
use smallvec::SmallVec;
23-
use std::{io::{Error as IoError, ErrorKind as IoErrorKind}, marker::PhantomData, u16};
24-
use tokio_codec::FramedWrite;
24+
use std::{io, u16};
25+
use tokio_codec::{Encoder, FramedWrite};
2526
use tokio_io::{AsyncRead, AsyncWrite};
26-
use unsigned_varint::codec::UviBytes;
27+
use unsigned_varint::decode;
2728

2829
/// `Stream` and `Sink` wrapping some `AsyncRead + AsyncWrite` object to read
2930
/// and write unsigned-varint prefixed frames.
3031
///
3132
/// We purposely only support a frame length of under 64kiB. Frames mostly consist
3233
/// in a short protocol name, which is highly unlikely to be more than 64kiB long.
33-
pub struct LengthDelimited<I, S> {
34+
pub struct LengthDelimited<R, C> {
3435
// The inner socket where data is pulled from.
35-
inner: FramedWrite<S, UviBytes>,
36+
inner: FramedWrite<R, C>,
3637
// Intermediary buffer where we put either the length of the next frame of data, or the frame
3738
// of data itself before it is returned.
3839
// Must always contain enough space to read data from `inner`.
3940
internal_buffer: SmallVec<[u8; 64]>,
4041
// Number of bytes within `internal_buffer` that contain valid data.
4142
internal_buffer_pos: usize,
4243
// State of the decoder.
43-
state: State,
44-
marker: PhantomData<I>,
44+
state: State
4545
}
4646

4747
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -52,24 +52,21 @@ enum State {
5252
ReadingData { frame_len: u16 },
5353
}
5454

55-
impl<I, S> LengthDelimited<I, S>
55+
impl<R, C> LengthDelimited<R, C>
5656
where
57-
S: AsyncWrite
57+
R: AsyncWrite,
58+
C: Encoder
5859
{
59-
pub fn new(inner: S) -> LengthDelimited<I, S> {
60-
let mut encoder = UviBytes::default();
61-
encoder.set_max_len(usize::from(u16::MAX));
62-
60+
pub fn new(inner: R, codec: C) -> LengthDelimited<R, C> {
6361
LengthDelimited {
64-
inner: FramedWrite::new(inner, encoder),
62+
inner: FramedWrite::new(inner, codec),
6563
internal_buffer: {
6664
let mut v = SmallVec::new();
6765
v.push(0);
6866
v
6967
},
7068
internal_buffer_pos: 0,
71-
state: State::ReadingLength,
72-
marker: PhantomData,
69+
state: State::ReadingLength
7370
}
7471
}
7572

@@ -85,20 +82,19 @@ where
8582
/// the modifiers provided by the `futures` crate) will always leave the object in a state in
8683
/// which `into_inner()` will not panic.
8784
#[inline]
88-
pub fn into_inner(self) -> S {
85+
pub fn into_inner(self) -> R {
8986
assert_eq!(self.state, State::ReadingLength);
9087
assert_eq!(self.internal_buffer_pos, 0);
9188
self.inner.into_inner()
9289
}
9390
}
9491

95-
impl<I, S> Stream for LengthDelimited<I, S>
92+
impl<R, C> Stream for LengthDelimited<R, C>
9693
where
97-
S: AsyncRead,
98-
I: for<'r> From<&'r [u8]>,
94+
R: AsyncRead
9995
{
100-
type Item = I;
101-
type Error = IoError;
96+
type Item = Bytes;
97+
type Error = io::Error;
10298

10399
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
104100
loop {
@@ -107,23 +103,21 @@ where
107103

108104
match self.state {
109105
State::ReadingLength => {
110-
match self.inner
111-
.get_mut()
112-
.read(&mut self.internal_buffer[self.internal_buffer_pos..])
113-
{
106+
let slice = &mut self.internal_buffer[self.internal_buffer_pos..];
107+
match self.inner.get_mut().read(slice) {
114108
Ok(0) => {
115109
// EOF
116110
if self.internal_buffer_pos == 0 {
117111
return Ok(Async::Ready(None));
118112
} else {
119-
return Err(IoError::new(IoErrorKind::BrokenPipe, "unexpected eof"));
113+
return Err(io::ErrorKind::UnexpectedEof.into());
120114
}
121115
}
122116
Ok(n) => {
123117
debug_assert_eq!(n, 1);
124118
self.internal_buffer_pos += n;
125119
}
126-
Err(ref err) if err.kind() == IoErrorKind::WouldBlock => {
120+
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
127121
return Ok(Async::NotReady);
128122
}
129123
Err(err) => {
@@ -136,7 +130,10 @@ where
136130
if (*self.internal_buffer.last().unwrap_or(&0) & 0x80) == 0 {
137131
// End of length prefix. Most of the time we will switch to reading data,
138132
// but we need to handle a few corner cases first.
139-
let frame_len = decode_length_prefix(&self.internal_buffer);
133+
let (frame_len, _) = decode::u16(&self.internal_buffer).map_err(|e| {
134+
log::debug!("invalid length prefix: {}", e);
135+
io::Error::new(io::ErrorKind::InvalidData, "invalid length prefix")
136+
})?;
140137

141138
if frame_len >= 1 {
142139
self.state = State::ReadingData { frame_len };
@@ -154,33 +151,22 @@ where
154151
}
155152
} else if self.internal_buffer_pos >= 2 {
156153
// Length prefix is too long. See module doc for info about max frame len.
157-
return Err(IoError::new(
158-
IoErrorKind::InvalidData,
159-
"frame length too long",
160-
));
154+
return Err(io::Error::new(io::ErrorKind::InvalidData, "frame length too long"));
161155
} else {
162156
// Prepare for next read.
163157
self.internal_buffer.push(0);
164158
}
165159
}
166-
167160
State::ReadingData { frame_len } => {
168-
match self.inner
169-
.get_mut()
170-
.read(&mut self.internal_buffer[self.internal_buffer_pos..])
171-
{
172-
Ok(0) => {
173-
return Err(IoError::new(IoErrorKind::BrokenPipe, "unexpected eof"));
174-
}
161+
let slice = &mut self.internal_buffer[self.internal_buffer_pos..];
162+
match self.inner.get_mut().read(slice) {
163+
Ok(0) => return Err(io::ErrorKind::UnexpectedEof.into()),
175164
Ok(n) => self.internal_buffer_pos += n,
176-
Err(ref err) if err.kind() == IoErrorKind::WouldBlock => {
177-
return Ok(Async::NotReady);
178-
}
179-
Err(err) => {
180-
return Err(err);
165+
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
166+
return Ok(Async::NotReady)
181167
}
168+
Err(err) => return Err(err)
182169
};
183-
184170
if self.internal_buffer_pos >= frame_len as usize {
185171
// Finished reading the frame of data.
186172
self.state = State::ReadingLength;
@@ -196,12 +182,13 @@ where
196182
}
197183
}
198184

199-
impl<I, S> Sink for LengthDelimited<I, S>
185+
impl<R, C> Sink for LengthDelimited<R, C>
200186
where
201-
S: AsyncWrite
187+
R: AsyncWrite,
188+
C: Encoder
202189
{
203-
type SinkItem = <FramedWrite<S, UviBytes> as Sink>::SinkItem;
204-
type SinkError = <FramedWrite<S, UviBytes> as Sink>::SinkError;
190+
type SinkItem = <FramedWrite<R, C> as Sink>::SinkItem;
191+
type SinkError = <FramedWrite<R, C> as Sink>::SinkError;
205192

206193
#[inline]
207194
fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
@@ -219,42 +206,25 @@ where
219206
}
220207
}
221208

222-
fn decode_length_prefix(buf: &[u8]) -> u16 {
223-
debug_assert!(buf.len() <= 2);
224-
225-
let mut sum = 0u16;
226-
227-
for &byte in buf.iter().rev() {
228-
let byte = byte & 0x7f;
229-
sum <<= 7;
230-
debug_assert!(sum.checked_add(u16::from(byte)).is_some());
231-
sum += u16::from(byte);
232-
}
233-
234-
sum
235-
}
236-
237209
#[cfg(test)]
238210
mod tests {
239211
use futures::{Future, Stream};
240212
use crate::length_delimited::LengthDelimited;
241-
use std::io::Cursor;
242-
use std::io::ErrorKind;
213+
use std::io::{Cursor, ErrorKind};
214+
use unsigned_varint::codec::UviBytes;
243215

244216
#[test]
245217
fn basic_read() {
246218
let data = vec![6, 9, 8, 7, 6, 5, 4];
247-
let framed = LengthDelimited::<Vec<u8>, _>::new(Cursor::new(data));
248-
219+
let framed = LengthDelimited::new(Cursor::new(data), UviBytes::<Vec<_>>::default());
249220
let recved = framed.collect().wait().unwrap();
250221
assert_eq!(recved, vec![vec![9, 8, 7, 6, 5, 4]]);
251222
}
252223

253224
#[test]
254225
fn basic_read_two() {
255226
let data = vec![6, 9, 8, 7, 6, 5, 4, 3, 9, 8, 7];
256-
let framed = LengthDelimited::<Vec<u8>, _>::new(Cursor::new(data));
257-
227+
let framed = LengthDelimited::new(Cursor::new(data), UviBytes::<Vec<_>>::default());
258228
let recved = framed.collect().wait().unwrap();
259229
assert_eq!(recved, vec![vec![9, 8, 7, 6, 5, 4], vec![9, 8, 7]]);
260230
}
@@ -266,8 +236,7 @@ mod tests {
266236
let frame = (0..len).map(|n| (n & 0xff) as u8).collect::<Vec<_>>();
267237
let mut data = vec![(len & 0x7f) as u8 | 0x80, (len >> 7) as u8];
268238
data.extend(frame.clone().into_iter());
269-
let framed = LengthDelimited::<Vec<u8>, _>::new(Cursor::new(data));
270-
239+
let framed = LengthDelimited::new(Cursor::new(data), UviBytes::<Vec<_>>::default());
271240
let recved = framed
272241
.into_future()
273242
.map(|(m, _)| m)
@@ -281,24 +250,24 @@ mod tests {
281250
fn packet_len_too_long() {
282251
let mut data = vec![0x81, 0x81, 0x1];
283252
data.extend((0..16513).map(|_| 0));
284-
let framed = LengthDelimited::<Vec<u8>, _>::new(Cursor::new(data));
285-
253+
let framed = LengthDelimited::new(Cursor::new(data), UviBytes::<Vec<_>>::default());
286254
let recved = framed
287255
.into_future()
288256
.map(|(m, _)| m)
289257
.map_err(|(err, _)| err)
290258
.wait();
291-
match recved {
292-
Err(io_err) => assert_eq!(io_err.kind(), ErrorKind::InvalidData),
293-
_ => panic!(),
259+
260+
if let Err(io_err) = recved {
261+
assert_eq!(io_err.kind(), ErrorKind::InvalidData)
262+
} else {
263+
panic!()
294264
}
295265
}
296266

297267
#[test]
298268
fn empty_frames() {
299269
let data = vec![0, 0, 6, 9, 8, 7, 6, 5, 4, 0, 3, 9, 8, 7];
300-
let framed = LengthDelimited::<Vec<u8>, _>::new(Cursor::new(data));
301-
270+
let framed = LengthDelimited::new(Cursor::new(data), UviBytes::<Vec<_>>::default());
302271
let recved = framed.collect().wait().unwrap();
303272
assert_eq!(
304273
recved,
@@ -315,36 +284,36 @@ mod tests {
315284
#[test]
316285
fn unexpected_eof_in_len() {
317286
let data = vec![0x89];
318-
let framed = LengthDelimited::<Vec<u8>, _>::new(Cursor::new(data));
319-
287+
let framed = LengthDelimited::new(Cursor::new(data), UviBytes::<Vec<_>>::default());
320288
let recved = framed.collect().wait();
321-
match recved {
322-
Err(io_err) => assert_eq!(io_err.kind(), ErrorKind::BrokenPipe),
323-
_ => panic!(),
289+
if let Err(io_err) = recved {
290+
assert_eq!(io_err.kind(), ErrorKind::UnexpectedEof)
291+
} else {
292+
panic!()
324293
}
325294
}
326295

327296
#[test]
328297
fn unexpected_eof_in_data() {
329298
let data = vec![5];
330-
let framed = LengthDelimited::<Vec<u8>, _>::new(Cursor::new(data));
331-
299+
let framed = LengthDelimited::new(Cursor::new(data), UviBytes::<Vec<_>>::default());
332300
let recved = framed.collect().wait();
333-
match recved {
334-
Err(io_err) => assert_eq!(io_err.kind(), ErrorKind::BrokenPipe),
335-
_ => panic!(),
301+
if let Err(io_err) = recved {
302+
assert_eq!(io_err.kind(), ErrorKind::UnexpectedEof)
303+
} else {
304+
panic!()
336305
}
337306
}
338307

339308
#[test]
340309
fn unexpected_eof_in_data2() {
341310
let data = vec![5, 9, 8, 7];
342-
let framed = LengthDelimited::<Vec<u8>, _>::new(Cursor::new(data));
343-
311+
let framed = LengthDelimited::new(Cursor::new(data), UviBytes::<Vec<_>>::default());
344312
let recved = framed.collect().wait();
345-
match recved {
346-
Err(io_err) => assert_eq!(io_err.kind(), ErrorKind::BrokenPipe),
347-
_ => panic!(),
313+
if let Err(io_err) = recved {
314+
assert_eq!(io_err.kind(), ErrorKind::UnexpectedEof)
315+
} else {
316+
panic!()
348317
}
349318
}
350319
}

0 commit comments

Comments
 (0)