Add rustfmt to travis (#137)

* RFC styling-based `rustfmt.toml`

* Add rustfmt to travis

* Remove rustfmt.toml and actually fix too-long lines instead of ignoring them
This commit is contained in:
Jef
2018-03-07 16:20:55 +01:00
committed by GitHub
parent e8d29af359
commit 5217e29fab
54 changed files with 5801 additions and 5572 deletions

View File

@ -10,6 +10,7 @@ before_install:
- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then
sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6'; sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6';
fi fi
- rustup component add rustfmt-preview
cache: cargo cache: cargo
@ -19,6 +20,6 @@ matrix:
- rust: stable - rust: stable
script: script:
- cargo fmt -- --write-mode=checkstyle
- cargo check --all - cargo check --all
- cargo test --all - cargo test --all

View File

@ -221,9 +221,8 @@ impl<B: Array> CircularBuffer<B> {
/// when the slice goes out of scope), if you're using non-`Drop` types you can use /// when the slice goes out of scope), if you're using non-`Drop` types you can use
/// `pop_slice_leaky`. /// `pop_slice_leaky`.
pub fn pop_slice(&mut self) -> Option<OwnedSlice<B::Item>> { pub fn pop_slice(&mut self) -> Option<OwnedSlice<B::Item>> {
self.pop_slice_leaky().map( self.pop_slice_leaky()
|x| unsafe { OwnedSlice::new(x) }, .map(|x| unsafe { OwnedSlice::new(x) })
)
} }
/// Pop a slice containing the maximum possible contiguous number of elements. Since this buffer /// Pop a slice containing the maximum possible contiguous number of elements. Since this buffer
@ -435,9 +434,9 @@ impl<B: Array> CircularBuffer<B> {
/// Get a borrow to an element at an index unsafely (behaviour is undefined if the index is out /// Get a borrow to an element at an index unsafely (behaviour is undefined if the index is out
/// of bounds). /// of bounds).
pub unsafe fn get_unchecked(&self, index: usize) -> &B::Item { pub unsafe fn get_unchecked(&self, index: usize) -> &B::Item {
&*self.buffer.ptr().offset( &*self.buffer
((index + self.start) % B::size()) as isize, .ptr()
) .offset(((index + self.start) % B::size()) as isize)
} }
/// Get a mutable borrow to an element at an index safely (if the index is out of bounds, return /// Get a mutable borrow to an element at an index safely (if the index is out of bounds, return
@ -453,10 +452,9 @@ impl<B: Array> CircularBuffer<B> {
/// Get a mutable borrow to an element at an index unsafely (behaviour is undefined if the index /// Get a mutable borrow to an element at an index unsafely (behaviour is undefined if the index
/// is out of bounds). /// is out of bounds).
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut B::Item { pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut B::Item {
&mut *self.buffer.ptr_mut().offset( &mut *self.buffer
((index + self.start) % B::size()) as .ptr_mut()
isize, .offset(((index + self.start) % B::size()) as isize)
)
} }
/// Removes the first `by` elements of the start of the buffer. /// Removes the first `by` elements of the start of the buffer.
@ -482,8 +480,7 @@ impl<B: Array> std::ops::Index<usize> for CircularBuffer<B> {
} else { } else {
panic!( panic!(
"index out of bounds: the len is {} but the index is {}", "index out of bounds: the len is {} but the index is {}",
self.len, self.len, index
index
); );
} }
} }
@ -499,8 +496,7 @@ impl<B: Array> std::ops::IndexMut<usize> for CircularBuffer<B> {
} else { } else {
panic!( panic!(
"index out of bounds: the len is {} but the index is {}", "index out of bounds: the len is {} but the index is {}",
len, len, index
index
); );
} }
} }
@ -624,7 +620,9 @@ where
/// ```rust /// ```rust
/// use circular_buffer::CircularBuffer; /// use circular_buffer::CircularBuffer;
/// ///
/// let result = CircularBuffer::<[usize; 5]>::from_slice_prefix(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 20]); /// let result = CircularBuffer::<[usize; 5]>::from_slice_prefix(
/// &[1, 2, 3, 4, 5, 6, 7, 8, 9, 20]
/// );
/// assert_eq!(result, (CircularBuffer::from_array([1, 2, 3, 4, 5]), 5)); /// assert_eq!(result, (CircularBuffer::from_array([1, 2, 3, 4, 5]), 5));
/// ``` /// ```
pub fn from_slice_prefix(slice: &[B::Item]) -> (Self, usize) { pub fn from_slice_prefix(slice: &[B::Item]) -> (Self, usize) {

View File

@ -23,11 +23,11 @@
use Datastore; use Datastore;
use chashmap::{CHashMap, WriteGuard}; use chashmap::{CHashMap, WriteGuard};
use futures::Future; use futures::Future;
use futures::stream::{Stream, iter_ok}; use futures::stream::{iter_ok, Stream};
use query::{Query, naive_apply_query}; use query::{naive_apply_query, Query};
use serde::Serialize; use serde::Serialize;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde_json::{Map, from_value, to_value, from_reader, to_writer}; use serde_json::{from_reader, from_value, to_value, to_writer, Map};
use serde_json::value::Value; use serde_json::value::Value;
use std::borrow::Cow; use std::borrow::Cow;
use std::fs; use std::fs;
@ -41,20 +41,23 @@ use tempfile::NamedTempFile;
/// Implementation of `Datastore` that uses a single plain JSON file. /// Implementation of `Datastore` that uses a single plain JSON file.
pub struct JsonFileDatastore<T> pub struct JsonFileDatastore<T>
where T: Serialize + DeserializeOwned + Clone where
T: Serialize + DeserializeOwned + Clone,
{ {
path: PathBuf, path: PathBuf,
content: CHashMap<String, T>, content: CHashMap<String, T>,
} }
impl<T> JsonFileDatastore<T> impl<T> JsonFileDatastore<T>
where T: Serialize + DeserializeOwned + Clone where
T: Serialize + DeserializeOwned + Clone,
{ {
/// Opens or creates the datastore. If the path refers to an existing path, then this function /// Opens or creates the datastore. If the path refers to an existing path, then this function
/// will attempt to load an existing set of values from it (which can result in an error). /// will attempt to load an existing set of values from it (which can result in an error).
/// Otherwise if the path doesn't exist, a new empty datastore will be created. /// Otherwise if the path doesn't exist, a new empty datastore will be created.
pub fn new<P>(path: P) -> Result<JsonFileDatastore<T>, IoError> pub fn new<P>(path: P) -> Result<JsonFileDatastore<T>, IoError>
where P: Into<PathBuf> where
P: Into<PathBuf>,
{ {
let path = path.into(); let path = path.into();
@ -92,7 +95,10 @@ impl<T> JsonFileDatastore<T>
out out
} }
Ok(_) => { Ok(_) => {
return Err(IoError::new(IoErrorKind::InvalidData, "expected JSON object")); return Err(IoError::new(
IoErrorKind::InvalidData,
"expected JSON object",
));
} }
Err(err) => { Err(err) => {
return Err(IoError::new(IoErrorKind::InvalidData, err)); return Err(IoError::new(IoErrorKind::InvalidData, err));
@ -101,7 +107,10 @@ impl<T> JsonFileDatastore<T>
} }
}; };
Ok(JsonFileDatastore { path: path, content: content }) Ok(JsonFileDatastore {
path: path,
content: content,
})
} }
/// Flushes the content of the datastore to the disk. /// Flushes the content of the datastore to the disk.
@ -110,13 +119,12 @@ impl<T> JsonFileDatastore<T>
/// to the datastore that was performed since the last successful flush will be lost. No data /// to the datastore that was performed since the last successful flush will be lost. No data
/// will be corrupted. /// will be corrupted.
pub fn flush(&self) -> Result<(), IoError> pub fn flush(&self) -> Result<(), IoError>
where T: Clone where
T: Clone,
{ {
// Create a temporary file in the same directory as the destination, which avoids the // Create a temporary file in the same directory as the destination, which avoids the
// problem of having a file cleaner delete our file while we use it. // problem of having a file cleaner delete our file while we use it.
let self_path_parent = self.path let self_path_parent = self.path.parent().ok_or(IoError::new(
.parent()
.ok_or(IoError::new(
IoErrorKind::Other, IoErrorKind::Other,
"couldn't get parent directory of destination", "couldn't get parent directory of destination",
))?; ))?;
@ -125,7 +133,9 @@ impl<T> JsonFileDatastore<T>
let content = self.content.clone().into_iter(); let content = self.content.clone().into_iter();
to_writer( to_writer(
&mut temporary_file, &mut temporary_file,
&content.map(|(k, v)| (k, to_value(v).unwrap())).collect::<Map<_, _>>(), &content
.map(|(k, v)| (k, to_value(v).unwrap()))
.collect::<Map<_, _>>(),
)?; )?;
temporary_file.sync_data()?; temporary_file.sync_data()?;
@ -138,20 +148,24 @@ impl<T> JsonFileDatastore<T>
} }
impl<'a, T> Datastore<T> for &'a JsonFileDatastore<T> impl<'a, T> Datastore<T> for &'a JsonFileDatastore<T>
where T: Clone + Serialize + DeserializeOwned + Default + PartialOrd + 'static where
T: Clone + Serialize + DeserializeOwned + Default + PartialOrd + 'static,
{ {
type Entry = JsonFileDatastoreEntry<'a, T>; type Entry = JsonFileDatastoreEntry<'a, T>;
type QueryResult = Box<Stream<Item = (String, T), Error = IoError> + 'a>; type QueryResult = Box<Stream<Item = (String, T), Error = IoError> + 'a>;
#[inline] #[inline]
fn lock(self, key: Cow<str>) -> Option<Self::Entry> { fn lock(self, key: Cow<str>) -> Option<Self::Entry> {
self.content.get_mut(&key.into_owned()).map(JsonFileDatastoreEntry) self.content
.get_mut(&key.into_owned())
.map(JsonFileDatastoreEntry)
} }
#[inline] #[inline]
fn lock_or_create(self, key: Cow<str>) -> Self::Entry { fn lock_or_create(self, key: Cow<str>) -> Self::Entry {
loop { loop {
self.content.upsert(key.clone().into_owned(), || Default::default(), |_| {}); self.content
.upsert(key.clone().into_owned(), || Default::default(), |_| {});
// There is a slight possibility that another thread will delete our value in this // There is a slight possibility that another thread will delete our value in this
// small interval. If this happens, we just loop and reinsert the value again until // small interval. If this happens, we just loop and reinsert the value again until
@ -195,7 +209,10 @@ impl<'a, T> Datastore<T> for &'a JsonFileDatastore<T>
// `content_stream` reads from the content of the `Mutex`, so we need to clone the data // `content_stream` reads from the content of the `Mutex`, so we need to clone the data
// into a `Vec` before returning. // into a `Vec` before returning.
let collected = naive_apply_query(content_stream, query).collect().wait().expect( let collected = naive_apply_query(content_stream, query)
.collect()
.wait()
.expect(
"can only fail if either `naive_apply_query` or `content_stream` produce \ "can only fail if either `naive_apply_query` or `content_stream` produce \
an error, which cann't happen", an error, which cann't happen",
); );
@ -205,7 +222,8 @@ impl<'a, T> Datastore<T> for &'a JsonFileDatastore<T>
} }
impl<T> Drop for JsonFileDatastore<T> impl<T> Drop for JsonFileDatastore<T>
where T: Serialize + DeserializeOwned + Clone where
T: Serialize + DeserializeOwned + Clone,
{ {
#[inline] #[inline]
fn drop(&mut self) { fn drop(&mut self) {
@ -220,10 +238,13 @@ impl<T> Drop for JsonFileDatastore<T>
} }
/// Implementation of `Datastore` that uses a single plain JSON file. /// Implementation of `Datastore` that uses a single plain JSON file.
pub struct JsonFileDatastoreEntry<'a, T>(WriteGuard<'a, String, T>) where T: 'a; pub struct JsonFileDatastoreEntry<'a, T>(WriteGuard<'a, String, T>)
where
T: 'a;
impl<'a, T> Deref for JsonFileDatastoreEntry<'a, T> impl<'a, T> Deref for JsonFileDatastoreEntry<'a, T>
where T: 'a where
T: 'a,
{ {
type Target = T; type Target = T;
@ -233,7 +254,8 @@ impl<'a, T> Deref for JsonFileDatastoreEntry<'a, T>
} }
impl<'a, T> DerefMut for JsonFileDatastoreEntry<'a, T> impl<'a, T> DerefMut for JsonFileDatastoreEntry<'a, T>
where T: 'a where
T: 'a,
{ {
fn deref_mut(&mut self) -> &mut T { fn deref_mut(&mut self) -> &mut T {
&mut *self.0 &mut *self.0
@ -242,7 +264,7 @@ impl<'a, T> DerefMut for JsonFileDatastoreEntry<'a, T>
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use {Query, Order, Filter, FilterTy, FilterOp}; use {Filter, FilterOp, FilterTy, Order, Query};
use Datastore; use Datastore;
use JsonFileDatastore; use JsonFileDatastore;
use futures::{Future, Stream}; use futures::{Future, Stream};
@ -283,7 +305,8 @@ mod tests {
datastore.put("bar1".into(), vec![0, 255, 127]); datastore.put("bar1".into(), vec![0, 255, 127]);
datastore.flush().unwrap(); datastore.flush().unwrap();
let query = datastore.query(Query { let query = datastore
.query(Query {
prefix: "fo".into(), prefix: "fo".into(),
filters: vec![ filters: vec![
Filter { Filter {

View File

@ -117,7 +117,7 @@ mod query;
mod json_file; mod json_file;
pub use self::json_file::{JsonFileDatastore, JsonFileDatastoreEntry}; pub use self::json_file::{JsonFileDatastore, JsonFileDatastoreEntry};
pub use self::query::{Query, Order, Filter, FilterTy, FilterOp}; pub use self::query::{Filter, FilterOp, FilterTy, Order, Query};
/// Abstraction over any struct that can store `(key, value)` pairs. /// Abstraction over any struct that can store `(key, value)` pairs.
pub trait Datastore<T> { pub trait Datastore<T> {
@ -129,7 +129,8 @@ pub trait Datastore<T> {
/// Sets the value of a key. /// Sets the value of a key.
#[inline] #[inline]
fn put(self, key: Cow<str>, value: T) fn put(self, key: Cow<str>, value: T)
where Self: Sized where
Self: Sized,
{ {
*self.lock_or_create(key) = value; *self.lock_or_create(key) = value;
} }
@ -148,8 +149,9 @@ pub trait Datastore<T> {
/// Returns the value corresponding to this key by cloning it. /// Returns the value corresponding to this key by cloning it.
#[inline] #[inline]
fn get(self, key: &str) -> Option<T> fn get(self, key: &str) -> Option<T>
where Self: Sized, where
T: Clone Self: Sized,
T: Clone,
{ {
self.lock(key.into()).map(|v| v.clone()) self.lock(key.into()).map(|v| v.clone())
} }
@ -161,7 +163,8 @@ pub trait Datastore<T> {
/// > returns whether an entry with that key existed in the short past. /// > returns whether an entry with that key existed in the short past.
#[inline] #[inline]
fn has(self, key: &str) -> bool fn has(self, key: &str) -> bool
where Self: Sized where
Self: Sized,
{ {
self.lock(key.into()).is_some() self.lock(key.into()).is_some()
} }

View File

@ -18,8 +18,8 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
use futures::{Stream, Future, Async, Poll}; use futures::{Async, Future, Poll, Stream};
use futures::stream::{iter_ok, Take as StreamTake, Skip as StreamSkip}; use futures::stream::{iter_ok, Skip as StreamSkip, Take as StreamTake};
use std::borrow::Cow; use std::borrow::Cow;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::io::Error as IoError; use std::io::Error as IoError;
@ -89,10 +89,22 @@ pub enum Order {
} }
/// Naively applies a query on a set of results. /// Naively applies a query on a set of results.
pub fn naive_apply_query<'a, S, V>(stream: S, query: Query<'a, V>) pub fn naive_apply_query<'a, S, V>(
-> StreamTake<StreamSkip<NaiveKeysOnlyApply<NaiveApplyOrdered<NaiveFiltersApply<'a, NaivePrefixApply<'a, S>, VecIntoIter<Filter<'a, V>>>, V>>>> stream: S,
where S: Stream<Item = (String, V), Error = IoError> + 'a, query: Query<'a, V>,
V: Clone + PartialOrd + Default + 'static ) -> StreamTake<
StreamSkip<
NaiveKeysOnlyApply<
NaiveApplyOrdered<
NaiveFiltersApply<'a, NaivePrefixApply<'a, S>, VecIntoIter<Filter<'a, V>>>,
V,
>,
>,
>,
>
where
S: Stream<Item = (String, V), Error = IoError> + 'a,
V: Clone + PartialOrd + Default + 'static,
{ {
let prefixed = naive_apply_prefix(stream, query.prefix); let prefixed = naive_apply_prefix(stream, query.prefix);
let filtered = naive_apply_filters(prefixed, query.filters.into_iter()); let filtered = naive_apply_filters(prefixed, query.filters.into_iter());
@ -104,7 +116,8 @@ pub fn naive_apply_query<'a, S, V>(stream: S, query: Query<'a, V>)
/// Skips the `skip` first element of a stream and only returns `limit` elements. /// Skips the `skip` first element of a stream and only returns `limit` elements.
#[inline] #[inline]
pub fn naive_apply_skip_limit<S, T>(stream: S, skip: u64, limit: u64) -> StreamTake<StreamSkip<S>> pub fn naive_apply_skip_limit<S, T>(stream: S, skip: u64, limit: u64) -> StreamTake<StreamSkip<S>>
where S: Stream<Item = (String, T), Error = IoError> where
S: Stream<Item = (String, T), Error = IoError>,
{ {
stream.skip(skip).take(limit) stream.skip(skip).take(limit)
} }
@ -112,7 +125,8 @@ pub fn naive_apply_skip_limit<S, T>(stream: S, skip: u64, limit: u64) -> StreamT
/// Filters the result of a stream to empty values if `keys_only` is true. /// Filters the result of a stream to empty values if `keys_only` is true.
#[inline] #[inline]
pub fn naive_apply_keys_only<S, T>(stream: S, keys_only: bool) -> NaiveKeysOnlyApply<S> pub fn naive_apply_keys_only<S, T>(stream: S, keys_only: bool) -> NaiveKeysOnlyApply<S>
where S: Stream<Item = (String, T), Error = IoError> where
S: Stream<Item = (String, T), Error = IoError>,
{ {
NaiveKeysOnlyApply { NaiveKeysOnlyApply {
keys_only: keys_only, keys_only: keys_only,
@ -128,8 +142,9 @@ pub struct NaiveKeysOnlyApply<S> {
} }
impl<S, T> Stream for NaiveKeysOnlyApply<S> impl<S, T> Stream for NaiveKeysOnlyApply<S>
where S: Stream<Item = (String, T), Error = IoError>, where
T: Default S: Stream<Item = (String, T), Error = IoError>,
T: Default,
{ {
type Item = (String, T); type Item = (String, T);
type Error = IoError; type Error = IoError;
@ -150,9 +165,13 @@ impl<S, T> Stream for NaiveKeysOnlyApply<S>
/// Filters the result of a stream to only keep the results with a prefix. /// Filters the result of a stream to only keep the results with a prefix.
#[inline] #[inline]
pub fn naive_apply_prefix<'a, S, T>(stream: S, prefix: Cow<'a, str>) -> NaivePrefixApply<'a, S> pub fn naive_apply_prefix<'a, S, T>(stream: S, prefix: Cow<'a, str>) -> NaivePrefixApply<'a, S>
where S: Stream<Item = (String, T), Error = IoError> where
S: Stream<Item = (String, T), Error = IoError>,
{ {
NaivePrefixApply { prefix: prefix, stream: stream } NaivePrefixApply {
prefix: prefix,
stream: stream,
}
} }
/// Returned by `naive_apply_prefix`. /// Returned by `naive_apply_prefix`.
@ -163,7 +182,8 @@ pub struct NaivePrefixApply<'a, S> {
} }
impl<'a, S, T> Stream for NaivePrefixApply<'a, S> impl<'a, S, T> Stream for NaivePrefixApply<'a, S>
where S: Stream<Item = (String, T), Error = IoError> where
S: Stream<Item = (String, T), Error = IoError>,
{ {
type Item = (String, T); type Item = (String, T);
type Error = IoError; type Error = IoError;
@ -187,17 +207,21 @@ impl<'a, S, T> Stream for NaivePrefixApply<'a, S>
/// Applies orderings on the stream data. Will simply pass data through if the list of orderings /// Applies orderings on the stream data. Will simply pass data through if the list of orderings
/// is empty. Otherwise will need to collect. /// is empty. Otherwise will need to collect.
pub fn naive_apply_ordered<'a, S, I, V>(stream: S, orders_iter: I) -> NaiveApplyOrdered<'a, S, V> pub fn naive_apply_ordered<'a, S, I, V>(stream: S, orders_iter: I) -> NaiveApplyOrdered<'a, S, V>
where S: Stream<Item = (String, V), Error = IoError> + 'a, where
S: Stream<Item = (String, V), Error = IoError> + 'a,
I: IntoIterator<Item = Order>, I: IntoIterator<Item = Order>,
I::IntoIter: 'a, I::IntoIter: 'a,
V: PartialOrd + 'static V: PartialOrd + 'static,
{ {
let orders_iter = orders_iter.into_iter(); let orders_iter = orders_iter.into_iter();
if orders_iter.size_hint().1 == Some(0) { if orders_iter.size_hint().1 == Some(0) {
return NaiveApplyOrdered { inner: NaiveApplyOrderedInner::PassThrough(stream) }; return NaiveApplyOrdered {
inner: NaiveApplyOrderedInner::PassThrough(stream),
};
} }
let collected = stream.collect() let collected = stream
.collect()
.and_then(move |mut collected| { .and_then(move |mut collected| {
for order in orders_iter { for order in orders_iter {
match order { match order {
@ -219,7 +243,9 @@ pub fn naive_apply_ordered<'a, S, I, V>(stream: S, orders_iter: I) -> NaiveApply
}) })
.flatten_stream(); .flatten_stream();
NaiveApplyOrdered { inner: NaiveApplyOrderedInner::Collected(Box::new(collected)) } NaiveApplyOrdered {
inner: NaiveApplyOrderedInner::Collected(Box::new(collected)),
}
} }
/// Returned by `naive_apply_ordered`. /// Returned by `naive_apply_ordered`.
@ -233,7 +259,8 @@ enum NaiveApplyOrderedInner<'a, S, T> {
} }
impl<'a, S, V> Stream for NaiveApplyOrdered<'a, S, V> impl<'a, S, V> Stream for NaiveApplyOrdered<'a, S, V>
where S: Stream<Item = (String, V), Error = IoError> where
S: Stream<Item = (String, V), Error = IoError>,
{ {
type Item = (String, V); type Item = (String, V);
type Error = IoError; type Error = IoError;
@ -250,9 +277,10 @@ impl<'a, S, V> Stream for NaiveApplyOrdered<'a, S, V>
/// Filters the result of a stream to apply a set of filters. /// Filters the result of a stream to apply a set of filters.
#[inline] #[inline]
pub fn naive_apply_filters<'a, S, I, V>(stream: S, filters: I) -> NaiveFiltersApply<'a, S, I> pub fn naive_apply_filters<'a, S, I, V>(stream: S, filters: I) -> NaiveFiltersApply<'a, S, I>
where S: Stream<Item = (String, V), Error = IoError>, where
S: Stream<Item = (String, V), Error = IoError>,
I: Iterator<Item = Filter<'a, V>> + Clone, I: Iterator<Item = Filter<'a, V>> + Clone,
V: 'a V: 'a,
{ {
NaiveFiltersApply { NaiveFiltersApply {
filters: filters, filters: filters,
@ -270,9 +298,10 @@ pub struct NaiveFiltersApply<'a, S, I> {
} }
impl<'a, S, I, T> Stream for NaiveFiltersApply<'a, S, I> impl<'a, S, I, T> Stream for NaiveFiltersApply<'a, S, I>
where S: Stream<Item = (String, T), Error = IoError>, where
S: Stream<Item = (String, T), Error = IoError>,
I: Iterator<Item = Filter<'a, T>> + Clone, I: Iterator<Item = Filter<'a, T>> + Clone,
T: PartialOrd + 'a T: PartialOrd + 'a,
{ {
type Item = (String, T); type Item = (String, T);
type Error = IoError; type Error = IoError;
@ -298,7 +327,8 @@ impl<'a, S, I, T> Stream for NaiveFiltersApply<'a, S, I>
#[inline] #[inline]
fn naive_filter_test<T>(entry: &(String, T), filter: &Filter<T>) -> bool fn naive_filter_test<T>(entry: &(String, T), filter: &Filter<T>) -> bool
where T: PartialOrd where
T: PartialOrd,
{ {
let (expected_ordering, revert_expected) = match filter.operation { let (expected_ordering, revert_expected) = match filter.operation {
FilterOp::Equal => (Ordering::Equal, false), FilterOp::Equal => (Ordering::Equal, false),

View File

@ -31,7 +31,7 @@ extern crate tokio_io;
use futures::{Future, Sink, Stream}; use futures::{Future, Sink, Stream};
use futures::sync::oneshot; use futures::sync::oneshot;
use std::env; use std::env;
use swarm::{UpgradeExt, SimpleProtocol, Transport, DeniedConnectionUpgrade}; use swarm::{DeniedConnectionUpgrade, SimpleProtocol, Transport, UpgradeExt};
use tcp::TcpConfig; use tcp::TcpConfig;
use tokio_core::reactor::Core; use tokio_core::reactor::Core;
use tokio_io::AsyncRead; use tokio_io::AsyncRead;
@ -40,7 +40,9 @@ use websocket::WsConfig;
fn main() { fn main() {
// Determine which address to dial. // Determine which address to dial.
let target_addr = env::args().nth(1).unwrap_or("/ip4/127.0.0.1/tcp/10333".to_owned()); let target_addr = env::args()
.nth(1)
.unwrap_or("/ip4/127.0.0.1/tcp/10333".to_owned());
// We start by building the tokio engine that will run all the sockets. // We start by building the tokio engine that will run all the sockets.
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
@ -82,10 +84,13 @@ fn main() {
// connections for us. The second parameter we pass is the connection upgrade that is accepted // connections for us. The second parameter we pass is the connection upgrade that is accepted
// by the listening part. We don't want to accept anything, so we pass a dummy object that // by the listening part. We don't want to accept anything, so we pass a dummy object that
// represents a connection that is always denied. // represents a connection that is always denied.
let (swarm_controller, swarm_future) = swarm::swarm(transport, DeniedConnectionUpgrade, let (swarm_controller, swarm_future) = swarm::swarm(
transport,
DeniedConnectionUpgrade,
|_socket, _client_addr| -> Result<(), _> { |_socket, _client_addr| -> Result<(), _> {
unreachable!("All incoming connections should have been denied") unreachable!("All incoming connections should have been denied")
}); },
);
// Building a struct that represents the protocol that we are going to use for dialing. // Building a struct that represents the protocol that we are going to use for dialing.
let proto = SimpleProtocol::new("/echo/1.0.0", |socket| { let proto = SimpleProtocol::new("/echo/1.0.0", |socket| {

View File

@ -28,10 +28,10 @@ extern crate multiplex;
extern crate tokio_core; extern crate tokio_core;
extern crate tokio_io; extern crate tokio_io;
use futures::future::{Future, IntoFuture, loop_fn, Loop}; use futures::future::{loop_fn, Future, IntoFuture, Loop};
use futures::{Stream, Sink}; use futures::{Sink, Stream};
use std::env; use std::env;
use swarm::{Transport, UpgradeExt, SimpleProtocol}; use swarm::{SimpleProtocol, Transport, UpgradeExt};
use tcp::TcpConfig; use tcp::TcpConfig;
use tokio_core::reactor::Core; use tokio_core::reactor::Core;
use tokio_io::AsyncRead; use tokio_io::AsyncRead;
@ -40,7 +40,9 @@ use websocket::WsConfig;
fn main() { fn main() {
// Determine which address to listen to. // Determine which address to listen to.
let listen_addr = env::args().nth(1).unwrap_or("/ip4/0.0.0.0/tcp/10333".to_owned()); let listen_addr = env::args()
.nth(1)
.unwrap_or("/ip4/0.0.0.0/tcp/10333".to_owned());
// We start by building the tokio engine that will run all the sockets. // We start by building the tokio engine that will run all the sockets.
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
@ -107,14 +109,16 @@ fn main() {
.and_then(move |(msg, rest)| { .and_then(move |(msg, rest)| {
if let Some(msg) = msg { if let Some(msg) = msg {
// One message has been received. We send it back to the client. // One message has been received. We send it back to the client.
println!("Received a message from {}: {:?}\n => Sending back \ println!(
identical message to remote", client_addr, msg); "Received a message from {}: {:?}\n => Sending back \
identical message to remote",
client_addr, msg
);
Box::new(rest.send(msg.freeze()).map(|m| Loop::Continue(m))) Box::new(rest.send(msg.freeze()).map(|m| Loop::Continue(m)))
as Box<Future<Item = _, Error = _>> as Box<Future<Item = _, Error = _>>
} else { } else {
// End of stream. Connection closed. Breaking the loop. // End of stream. Connection closed. Breaking the loop.
println!("Received EOF from {}\n => Dropping connection", println!("Received EOF from {}\n => Dropping connection", client_addr);
client_addr);
Box::new(Ok(Loop::Break(())).into_future()) Box::new(Ok(Loop::Break(())).into_future())
as Box<Future<Item = _, Error = _>> as Box<Future<Item = _, Error = _>>
} }

View File

@ -31,13 +31,15 @@ extern crate tokio_io;
use futures::Future; use futures::Future;
use futures::sync::oneshot; use futures::sync::oneshot;
use std::env; use std::env;
use swarm::{UpgradeExt, Transport, DeniedConnectionUpgrade}; use swarm::{DeniedConnectionUpgrade, Transport, UpgradeExt};
use tcp::TcpConfig; use tcp::TcpConfig;
use tokio_core::reactor::Core; use tokio_core::reactor::Core;
fn main() { fn main() {
// Determine which address to dial. // Determine which address to dial.
let target_addr = env::args().nth(1).unwrap_or("/ip4/127.0.0.1/tcp/4001".to_owned()); let target_addr = env::args()
.nth(1)
.unwrap_or("/ip4/127.0.0.1/tcp/4001".to_owned());
// We start by building the tokio engine that will run all the sockets. // We start by building the tokio engine that will run all the sockets.
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
@ -74,10 +76,13 @@ fn main() {
// connections for us. The second parameter we pass is the connection upgrade that is accepted // connections for us. The second parameter we pass is the connection upgrade that is accepted
// by the listening part. We don't want to accept anything, so we pass a dummy object that // by the listening part. We don't want to accept anything, so we pass a dummy object that
// represents a connection that is always denied. // represents a connection that is always denied.
let (swarm_controller, swarm_future) = swarm::swarm(transport, DeniedConnectionUpgrade, let (swarm_controller, swarm_future) = swarm::swarm(
transport,
DeniedConnectionUpgrade,
|_socket, _client_addr| -> Result<(), _> { |_socket, _client_addr| -> Result<(), _> {
unreachable!("All incoming connections should have been denied") unreachable!("All incoming connections should have been denied")
}); },
);
// We now use the controller to dial to the address. // We now use the controller to dial to the address.
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
@ -101,5 +106,9 @@ fn main() {
// `swarm_future` is a future that contains all the behaviour that we want, but nothing has // `swarm_future` is a future that contains all the behaviour that we want, but nothing has
// actually started yet. Because we created the `TcpConfig` with tokio, we need to run the // actually started yet. Because we created the `TcpConfig` with tokio, we need to run the
// future through the tokio core. // future through the tokio core.
core.run(rx.select(swarm_future.map_err(|_| unreachable!())).map_err(|(e, _)| e).map(|_| ())).unwrap(); core.run(
rx.select(swarm_future.map_err(|_| unreachable!()))
.map_err(|(e, _)| e)
.map(|_| ()),
).unwrap();
} }

View File

@ -22,7 +22,7 @@ extern crate libp2p_peerstore;
extern crate libp2p_swarm; extern crate libp2p_swarm;
extern crate multiaddr; extern crate multiaddr;
use libp2p_peerstore::{PeerId, PeerAccess, Peerstore}; use libp2p_peerstore::{PeerAccess, PeerId, Peerstore};
use multiaddr::Multiaddr; use multiaddr::Multiaddr;
use std::time::Duration; use std::time::Duration;

View File

@ -167,7 +167,6 @@ where
info, info,
observed_addr, observed_addr,
}) })
} else { } else {
debug!(target: "libp2p-identify", "Identify protocol stream closed \ debug!(target: "libp2p-identify", "Identify protocol stream closed \
before receiving info"); before receiving info");
@ -236,7 +235,7 @@ mod tests {
use self::libp2p_tcp_transport::TcpConfig; use self::libp2p_tcp_transport::TcpConfig;
use self::tokio_core::reactor::Core; use self::tokio_core::reactor::Core;
use {IdentifyProtocolConfig, IdentifyOutput, IdentifyInfo}; use {IdentifyInfo, IdentifyOutput, IdentifyProtocolConfig};
use futures::{Future, Stream}; use futures::{Future, Stream};
use libp2p_swarm::Transport; use libp2p_swarm::Transport;
use std::sync::mpsc; use std::sync::mpsc;
@ -251,61 +250,69 @@ mod tests {
let bg_thread = thread::spawn(move || { let bg_thread = thread::spawn(move || {
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
let transport = TcpConfig::new(core.handle()) let transport = TcpConfig::new(core.handle()).with_upgrade(IdentifyProtocolConfig);
.with_upgrade(IdentifyProtocolConfig);
let (listener, addr) = transport let (listener, addr) = transport
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap(); .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
.unwrap();
tx.send(addr).unwrap(); tx.send(addr).unwrap();
let future = listener let future = listener
.into_future() .into_future()
.map_err(|(err, _)| err) .map_err(|(err, _)| err)
.and_then(|(client, _)| client.unwrap().map(|v| v.0)) .and_then(|(client, _)| client.unwrap().map(|v| v.0))
.and_then(|identify| { .and_then(|identify| match identify {
match identify { IdentifyOutput::Sender { sender, .. } => sender.send(
IdentifyOutput::Sender { sender, .. } => { IdentifyInfo {
sender.send(IdentifyInfo {
public_key: vec![1, 2, 3, 4, 5, 7], public_key: vec![1, 2, 3, 4, 5, 7],
protocol_version: "proto_version".to_owned(), protocol_version: "proto_version".to_owned(),
agent_version: "agent_version".to_owned(), agent_version: "agent_version".to_owned(),
listen_addrs: vec![ listen_addrs: vec![
"/ip4/80.81.82.83/tcp/500".parse().unwrap(), "/ip4/80.81.82.83/tcp/500".parse().unwrap(),
"/ip6/::1/udp/1000".parse().unwrap() "/ip6/::1/udp/1000".parse().unwrap(),
], ],
protocols: vec!["proto1".to_string(), "proto2".to_string()], protocols: vec!["proto1".to_string(), "proto2".to_string()],
}, &"/ip4/100.101.102.103/tcp/5000".parse().unwrap())
}, },
_ => panic!() &"/ip4/100.101.102.103/tcp/5000".parse().unwrap(),
} ),
_ => panic!(),
}); });
let _ = core.run(future).unwrap(); let _ = core.run(future).unwrap();
}); });
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
let transport = TcpConfig::new(core.handle()) let transport = TcpConfig::new(core.handle()).with_upgrade(IdentifyProtocolConfig);
.with_upgrade(IdentifyProtocolConfig);
let future = transport let future = transport
.dial(rx.recv().unwrap()) .dial(rx.recv().unwrap())
.unwrap_or_else(|_| panic!()) .unwrap_or_else(|_| panic!())
.and_then(|(identify, _)| { .and_then(|(identify, _)| match identify {
match identify { IdentifyOutput::RemoteInfo {
IdentifyOutput::RemoteInfo { info, observed_addr } => { info,
assert_eq!(observed_addr, "/ip4/100.101.102.103/tcp/5000".parse().unwrap()); observed_addr,
} => {
assert_eq!(
observed_addr,
"/ip4/100.101.102.103/tcp/5000".parse().unwrap()
);
assert_eq!(info.public_key, &[1, 2, 3, 4, 5, 7]); assert_eq!(info.public_key, &[1, 2, 3, 4, 5, 7]);
assert_eq!(info.protocol_version, "proto_version"); assert_eq!(info.protocol_version, "proto_version");
assert_eq!(info.agent_version, "agent_version"); assert_eq!(info.agent_version, "agent_version");
assert_eq!(info.listen_addrs, &[ assert_eq!(
info.listen_addrs,
&[
"/ip4/80.81.82.83/tcp/500".parse().unwrap(), "/ip4/80.81.82.83/tcp/500".parse().unwrap(),
"/ip6/::1/udp/1000".parse().unwrap() "/ip6/::1/udp/1000".parse().unwrap()
]); ]
assert_eq!(info.protocols, &["proto1".to_string(), "proto2".to_string()]); );
assert_eq!(
info.protocols,
&["proto1".to_string(), "proto2".to_string()]
);
Ok(()) Ok(())
},
_ => panic!()
} }
_ => panic!(),
}); });
let _ = core.run(future).unwrap(); let _ = core.run(future).unwrap();

View File

@ -232,9 +232,7 @@ where
let peerstore = self.peerstore; let peerstore = self.peerstore;
let addr_ttl = self.addr_ttl; let addr_ttl = self.addr_ttl;
let future = self.transport let future = self.transport.next_incoming().map(move |incoming| {
.next_incoming()
.map(move |incoming| {
let future = incoming let future = incoming
.and_then(move |(connec, client_addr)| { .and_then(move |(connec, client_addr)| {
// On an incoming connection, dial back the node and upgrade to the identify // On an incoming connection, dial back the node and upgrade to the identify
@ -280,8 +278,7 @@ fn multiaddr_to_peerid(addr: Multiaddr) -> Result<PeerId, Multiaddr> {
} }
match components.last() { match components.last() {
Some(&AddrComponent::P2P(ref peer_id)) | Some(&AddrComponent::P2P(ref peer_id)) | Some(&AddrComponent::IPFS(ref peer_id)) => {
Some(&AddrComponent::IPFS(ref peer_id)) => {
// TODO: `peer_id` is sometimes in fact a CID here // TODO: `peer_id` is sometimes in fact a CID here
match PeerId::from_bytes(peer_id.clone()) { match PeerId::from_bytes(peer_id.clone()) {
Ok(peer_id) => Ok(peer_id), Ok(peer_id) => Ok(peer_id),

View File

@ -23,11 +23,11 @@
use super::TTL; use super::TTL;
use PeerId; use PeerId;
use base58::{FromBase58, ToBase58}; use base58::{FromBase58, ToBase58};
use datastore::{Datastore, Query, JsonFileDatastore, JsonFileDatastoreEntry}; use datastore::{Datastore, JsonFileDatastore, JsonFileDatastoreEntry, Query};
use futures::{Future, Stream}; use futures::{Future, Stream};
use multiaddr::Multiaddr; use multiaddr::Multiaddr;
use peer_info::{PeerInfo, AddAddrBehaviour}; use peer_info::{AddAddrBehaviour, PeerInfo};
use peerstore::{Peerstore, PeerAccess}; use peerstore::{PeerAccess, Peerstore};
use std::io::Error as IoError; use std::io::Error as IoError;
use std::iter; use std::iter;
use std::path::PathBuf; use std::path::PathBuf;
@ -45,9 +45,12 @@ impl JsonPeerstore {
/// destroying it will write to the file. /// destroying it will write to the file.
#[inline] #[inline]
pub fn new<P>(path: P) -> Result<JsonPeerstore, IoError> pub fn new<P>(path: P) -> Result<JsonPeerstore, IoError>
where P: Into<PathBuf> where
P: Into<PathBuf>,
{ {
Ok(JsonPeerstore { store: JsonFileDatastore::new(path)? }) Ok(JsonPeerstore {
store: JsonFileDatastore::new(path)?,
})
} }
/// Flushes the content of the peer store to the disk. /// Flushes the content of the peer store to the disk.
@ -87,7 +90,8 @@ impl<'a> Peerstore for &'a JsonPeerstore {
keys_only: true, keys_only: true,
}); });
let list = query.filter_map(|(key, _)| { let list = query
.filter_map(|(key, _)| {
// We filter out invalid elements. This can happen if the JSON storage file was // We filter out invalid elements. This can happen if the JSON storage file was
// corrupted or manually modified by the user. // corrupted or manually modified by the user.
PeerId::from_bytes(key.from_base58().ok()?).ok() PeerId::from_bytes(key.from_base58().ok()?).ok()
@ -116,7 +120,8 @@ impl<'a> PeerAccess for JsonPeerstoreAccess<'a> {
#[inline] #[inline]
fn add_addr(&mut self, addr: Multiaddr, ttl: TTL) { fn add_addr(&mut self, addr: Multiaddr, ttl: TTL) {
self.0.add_addr(addr, ttl, AddAddrBehaviour::IgnoreTtlIfInferior); self.0
.add_addr(addr, ttl, AddAddrBehaviour::IgnoreTtlIfInferior);
} }
#[inline] #[inline]

View File

@ -80,7 +80,7 @@ extern crate serde_derive;
use std::fmt; use std::fmt;
use base58::ToBase58; use base58::ToBase58;
pub use self::peerstore::{Peerstore, PeerAccess}; pub use self::peerstore::{PeerAccess, Peerstore};
#[macro_use] #[macro_use]
mod peerstore_tests; mod peerstore_tests;
@ -141,17 +141,16 @@ impl PeerId {
/// Returns the raw bytes of the hash of this `PeerId`. /// Returns the raw bytes of the hash of this `PeerId`.
#[inline] #[inline]
pub fn hash(&self) -> &[u8] { pub fn hash(&self) -> &[u8] {
let multihash::Multihash { digest, .. } = multihash::decode(&self.multihash) let multihash::Multihash { digest, .. } =
.expect("our inner value should always be valid"); multihash::decode(&self.multihash).expect("our inner value should always be valid");
digest digest
} }
/// Checks whether the public key passed as parameter matches the public key of this `PeerId`. /// Checks whether the public key passed as parameter matches the public key of this `PeerId`.
pub fn is_public_key(&self, public_key: &[u8]) -> bool { pub fn is_public_key(&self, public_key: &[u8]) -> bool {
let multihash::Multihash { alg, .. } = multihash::decode(&self.multihash) let multihash::Multihash { alg, .. } =
.expect("our inner value should always be valid"); multihash::decode(&self.multihash).expect("our inner value should always be valid");
let compare = multihash::encode(alg, public_key) let compare = multihash::encode(alg, public_key).expect("unsupported multihash algorithm"); // TODO: what to do here?
.expect("unsupported multihash algorithm"); // TODO: what to do here?
compare == self.multihash compare == self.multihash
} }
} }

View File

@ -24,8 +24,8 @@ use super::TTL;
use PeerId; use PeerId;
use multiaddr::Multiaddr; use multiaddr::Multiaddr;
use owning_ref::OwningRefMut; use owning_ref::OwningRefMut;
use peer_info::{PeerInfo, AddAddrBehaviour}; use peer_info::{AddAddrBehaviour, PeerInfo};
use peerstore::{Peerstore, PeerAccess}; use peerstore::{PeerAccess, Peerstore};
use std::collections::HashMap; use std::collections::HashMap;
use std::iter; use std::iter;
use std::sync::{Mutex, MutexGuard}; use std::sync::{Mutex, MutexGuard};
@ -41,7 +41,9 @@ impl MemoryPeerstore {
/// Initializes a new `MemoryPeerstore`. The database is initially empty. /// Initializes a new `MemoryPeerstore`. The database is initially empty.
#[inline] #[inline]
pub fn empty() -> MemoryPeerstore { pub fn empty() -> MemoryPeerstore {
MemoryPeerstore { store: Mutex::new(HashMap::new()) } MemoryPeerstore {
store: Mutex::new(HashMap::new()),
}
} }
} }
@ -79,7 +81,9 @@ impl<'a> Peerstore for &'a MemoryPeerstore {
// Note: Rust doesn't provide a `MutexGuard::map` method, otherwise we could directly store a // Note: Rust doesn't provide a `MutexGuard::map` method, otherwise we could directly store a
// `MutexGuard<'a, (&'a PeerId, &'a PeerInfo)>`. // `MutexGuard<'a, (&'a PeerId, &'a PeerInfo)>`.
pub struct MemoryPeerstoreAccess<'a>(OwningRefMut<MutexGuard<'a, HashMap<PeerId, PeerInfo>>, PeerInfo>); pub struct MemoryPeerstoreAccess<'a>(
OwningRefMut<MutexGuard<'a, HashMap<PeerId, PeerInfo>>, PeerInfo>,
);
impl<'a> PeerAccess for MemoryPeerstoreAccess<'a> { impl<'a> PeerAccess for MemoryPeerstoreAccess<'a> {
type AddrsIter = VecIntoIter<Multiaddr>; type AddrsIter = VecIntoIter<Multiaddr>;
@ -91,7 +95,8 @@ impl<'a> PeerAccess for MemoryPeerstoreAccess<'a> {
#[inline] #[inline]
fn add_addr(&mut self, addr: Multiaddr, ttl: TTL) { fn add_addr(&mut self, addr: Multiaddr, ttl: TTL) {
self.0.add_addr(addr, ttl, AddAddrBehaviour::IgnoreTtlIfInferior); self.0
.add_addr(addr, ttl, AddAddrBehaviour::IgnoreTtlIfInferior);
} }
#[inline] #[inline]
@ -107,7 +112,5 @@ impl<'a> PeerAccess for MemoryPeerstoreAccess<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
peerstore_tests!({ peerstore_tests!({ ::memory_peerstore::MemoryPeerstore::empty() });
::memory_peerstore::MemoryPeerstore::empty()
});
} }

View File

@ -28,7 +28,7 @@
use TTL; use TTL;
use multiaddr::Multiaddr; use multiaddr::Multiaddr;
use serde::{Serialize, Deserialize, Serializer, Deserializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::Error as DeserializerError; use serde::de::Error as DeserializerError;
use serde::ser::SerializeStruct; use serde::ser::SerializeStruct;
use std::cmp::Ordering; use std::cmp::Ordering;
@ -56,11 +56,9 @@ impl PeerInfo {
#[inline] #[inline]
pub fn addrs<'a>(&'a self) -> Box<Iterator<Item = &'a Multiaddr> + 'a> { pub fn addrs<'a>(&'a self) -> Box<Iterator<Item = &'a Multiaddr> + 'a> {
let now = SystemTime::now(); let now = SystemTime::now();
Box::new(self.addrs.iter().filter_map(move |&(ref addr, ref expires)| if *expires >= now { Box::new(self.addrs.iter().filter_map(
Some(addr) move |&(ref addr, ref expires)| if *expires >= now { Some(addr) } else { None },
} else { ))
None
}))
} }
/// Sets the list of addresses and their time-to-live. /// Sets the list of addresses and their time-to-live.
@ -68,10 +66,14 @@ impl PeerInfo {
/// This removes all previously-stored addresses and replaces them with new ones. /// This removes all previously-stored addresses and replaces them with new ones.
#[inline] #[inline]
pub fn set_addrs<I>(&mut self, addrs: I) pub fn set_addrs<I>(&mut self, addrs: I)
where I: IntoIterator<Item = (Multiaddr, TTL)> where
I: IntoIterator<Item = (Multiaddr, TTL)>,
{ {
let now = SystemTime::now(); let now = SystemTime::now();
self.addrs = addrs.into_iter().map(move |(addr, ttl)| (addr, now + ttl)).collect(); self.addrs = addrs
.into_iter()
.map(move |(addr, ttl)| (addr, now + ttl))
.collect();
} }
/// Adds a single address and its time-to-live. /// Adds a single address and its time-to-live.
@ -105,7 +107,8 @@ pub enum AddAddrBehaviour {
impl Serialize for PeerInfo { impl Serialize for PeerInfo {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer where
S: Serializer,
{ {
let mut s = serializer.serialize_struct("PeerInfo", 2)?; let mut s = serializer.serialize_struct("PeerInfo", 2)?;
s.serialize_field( s.serialize_field(
@ -120,7 +123,8 @@ impl Serialize for PeerInfo {
// improbable corner case and is not attackable in any way, so we don't really // improbable corner case and is not attackable in any way, so we don't really
// care. // care.
.unwrap_or(Duration::new(0, 0)); .unwrap_or(Duration::new(0, 0));
let secs = from_epoch.as_secs() let secs = from_epoch
.as_secs()
.saturating_mul(1_000) .saturating_mul(1_000)
.saturating_add(from_epoch.subsec_nanos() as u64 / 1_000_000); .saturating_add(from_epoch.subsec_nanos() as u64 / 1_000_000);
(addr, secs) (addr, secs)
@ -133,7 +137,8 @@ impl Serialize for PeerInfo {
impl<'de> Deserialize<'de> for PeerInfo { impl<'de> Deserialize<'de> for PeerInfo {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> where
D: Deserializer<'de>,
{ {
// We deserialize to an intermdiate struct first, then turn that struct into a `PeerInfo`. // We deserialize to an intermdiate struct first, then turn that struct into a `PeerInfo`.
let interm = { let interm = {
@ -157,9 +162,7 @@ impl<'de> Deserialize<'de> for PeerInfo {
out out
}; };
Ok(PeerInfo { Ok(PeerInfo { addrs: addrs })
addrs: addrs,
})
} }
} }

View File

@ -71,7 +71,8 @@ pub trait PeerAccess {
// Similar to calling `add_addr` multiple times in a row. // Similar to calling `add_addr` multiple times in a row.
#[inline] #[inline]
fn add_addrs<I>(&mut self, addrs: I, ttl: TTL) fn add_addrs<I>(&mut self, addrs: I, ttl: TTL)
where I: IntoIterator<Item = Multiaddr> where
I: IntoIterator<Item = Multiaddr>,
{ {
for addr in addrs.into_iter() { for addr in addrs.into_iter() {
self.add_addr(addr, ttl); self.add_addr(addr, ttl);
@ -86,7 +87,8 @@ pub trait PeerAccess {
// Similar to calling `set_addr_ttl` multiple times in a row. // Similar to calling `set_addr_ttl` multiple times in a row.
fn set_addrs_ttl<I>(&mut self, addrs: I, ttl: TTL) fn set_addrs_ttl<I>(&mut self, addrs: I, ttl: TTL)
where I: IntoIterator<Item = Multiaddr> where
I: IntoIterator<Item = Multiaddr>,
{ {
for addr in addrs.into_iter() { for addr in addrs.into_iter() {
self.add_addr(addr, ttl); self.add_addr(addr, ttl);

View File

@ -79,7 +79,8 @@ macro_rules! peerstore_tests {
let peer_id = PeerId::from_public_key(&[1, 2, 3]); let peer_id = PeerId::from_public_key(&[1, 2, 3]);
let addr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap(); let addr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap();
peer_store.peer_or_create(&peer_id).add_addr(addr.clone(), Duration::from_millis(5000)); peer_store.peer_or_create(&peer_id)
.add_addr(addr.clone(), Duration::from_millis(5000));
peer_store.peer(&peer_id).unwrap().clear_addrs(); peer_store.peer(&peer_id).unwrap().clear_addrs();
let addrs = peer_store.peer(&peer_id).unwrap().addrs(); let addrs = peer_store.peer(&peer_id).unwrap().addrs();
@ -95,8 +96,10 @@ macro_rules! peerstore_tests {
let addr1 = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap(); let addr1 = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap();
let addr2 = "/ip4/0.0.0.1/tcp/0".parse::<Multiaddr>().unwrap(); let addr2 = "/ip4/0.0.0.1/tcp/0".parse::<Multiaddr>().unwrap();
peer_store.peer_or_create(&peer_id).add_addr(addr1.clone(), Duration::from_millis(5000)); peer_store.peer_or_create(&peer_id)
peer_store.peer_or_create(&peer_id).add_addr(addr2.clone(), Duration::from_millis(5000)); .add_addr(addr1.clone(), Duration::from_millis(5000));
peer_store.peer_or_create(&peer_id)
.add_addr(addr2.clone(), Duration::from_millis(5000));
assert_eq!(peer_store.peer(&peer_id).unwrap().addrs().count(), 2); assert_eq!(peer_store.peer(&peer_id).unwrap().addrs().count(), 2);
// `add_addr` must not overwrite the TTL because it's already higher // `add_addr` must not overwrite the TTL because it's already higher
@ -114,11 +117,14 @@ macro_rules! peerstore_tests {
let addr1 = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap(); let addr1 = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap();
let addr2 = "/ip4/0.0.0.1/tcp/0".parse::<Multiaddr>().unwrap(); let addr2 = "/ip4/0.0.0.1/tcp/0".parse::<Multiaddr>().unwrap();
peer_store.peer_or_create(&peer_id).add_addr(addr1.clone(), Duration::from_millis(5000)); peer_store.peer_or_create(&peer_id)
peer_store.peer_or_create(&peer_id).add_addr(addr2.clone(), Duration::from_millis(5000)); .add_addr(addr1.clone(), Duration::from_millis(5000));
peer_store.peer_or_create(&peer_id)
.add_addr(addr2.clone(), Duration::from_millis(5000));
assert_eq!(peer_store.peer(&peer_id).unwrap().addrs().count(), 2); assert_eq!(peer_store.peer(&peer_id).unwrap().addrs().count(), 2);
peer_store.peer_or_create(&peer_id).set_addr_ttl(addr1.clone(), Duration::from_millis(0)); peer_store.peer_or_create(&peer_id)
.set_addr_ttl(addr1.clone(), Duration::from_millis(0));
thread::sleep(Duration::from_millis(2)); thread::sleep(Duration::from_millis(2));
assert_eq!(peer_store.peer(&peer_id).unwrap().addrs().count(), 1); assert_eq!(peer_store.peer(&peer_id).unwrap().addrs().count(), 1);
} }

View File

@ -88,9 +88,9 @@ extern crate parking_lot;
extern crate rand; extern crate rand;
extern crate tokio_io; extern crate tokio_io;
use bytes::{Bytes, BytesMut, BufMut}; use bytes::{BufMut, Bytes, BytesMut};
use futures::{Future, Sink, Stream}; use futures::{Future, Sink, Stream};
use futures::future::{FutureResult, IntoFuture, loop_fn, Loop}; use futures::future::{loop_fn, FutureResult, IntoFuture, Loop};
use futures::sync::{mpsc, oneshot}; use futures::sync::{mpsc, oneshot};
use libp2p_swarm::Multiaddr; use libp2p_swarm::Multiaddr;
use libp2p_swarm::transport::{ConnectionUpgrade, Endpoint}; use libp2p_swarm::transport::{ConnectionUpgrade, Endpoint};
@ -104,7 +104,7 @@ use std::io::Error as IoError;
use std::iter; use std::iter;
use std::sync::Arc; use std::sync::Arc;
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Encoder, Decoder}; use tokio_io::codec::{Decoder, Encoder};
/// Represents a prototype for an upgrade to handle the ping protocol. /// Represents a prototype for an upgrade to handle the ping protocol.
/// ///
@ -114,7 +114,8 @@ use tokio_io::codec::{Encoder, Decoder};
pub struct Ping; pub struct Ping;
impl<C> ConnectionUpgrade<C> for Ping impl<C> ConnectionUpgrade<C> for Ping
where C: AsyncRead + AsyncWrite + 'static where
C: AsyncRead + AsyncWrite + 'static,
{ {
type NamesIter = iter::Once<(Bytes, Self::UpgradeIdentifier)>; type NamesIter = iter::Once<(Bytes, Self::UpgradeIdentifier)>;
type UpgradeIdentifier = (); type UpgradeIdentifier = ();
@ -128,9 +129,13 @@ impl<C> ConnectionUpgrade<C> for Ping
type Future = FutureResult<Self::Output, IoError>; type Future = FutureResult<Self::Output, IoError>;
#[inline] #[inline]
fn upgrade(self, socket: C, _: Self::UpgradeIdentifier, _: Endpoint, remote_addr: &Multiaddr) fn upgrade(
-> Self::Future self,
{ socket: C,
_: Self::UpgradeIdentifier,
_: Endpoint,
remote_addr: &Multiaddr,
) -> Self::Future {
// # How does it work? // # How does it work?
// //
// All the actual processing is performed by the *ponger*. // All the actual processing is performed by the *ponger*.
@ -156,7 +161,9 @@ impl<C> ConnectionUpgrade<C> for Ping
// TODO: can't figure out how to make it work without using an Arc/Mutex // TODO: can't figure out how to make it work without using an Arc/Mutex
let expected_pongs = Arc::new(Mutex::new(HashMap::with_capacity(4))); let expected_pongs = Arc::new(Mutex::new(HashMap::with_capacity(4)));
let sink_stream = socket.framed(Codec).map(|msg| Message::Received(msg.freeze())); let sink_stream = socket
.framed(Codec)
.map(|msg| Message::Received(msg.freeze()));
let (sink, stream) = sink_stream.split(); let (sink, stream) = sink_stream.split();
let remote_addr = if log_enabled!(target: "libp2p-ping", Level::Debug) { let remote_addr = if log_enabled!(target: "libp2p-ping", Level::Debug) {
@ -169,7 +176,10 @@ impl<C> ConnectionUpgrade<C> for Ping
let expected_pongs = expected_pongs.clone(); let expected_pongs = expected_pongs.clone();
let remote_addr = remote_addr.clone(); let remote_addr = remote_addr.clone();
stream.into_future().map_err(|(err, _)| err).and_then(move |(message, stream)| { stream
.into_future()
.map_err(|(err, _)| err)
.and_then(move |(message, stream)| {
let mut expected_pongs = expected_pongs.lock(); let mut expected_pongs = expected_pongs.lock();
if let Some(message) = message { if let Some(message) = message {
@ -180,8 +190,10 @@ impl<C> ConnectionUpgrade<C> for Ping
remote_addr.expect("debug log level is enabled"), payload); remote_addr.expect("debug log level is enabled"), payload);
expected_pongs.insert(payload.clone(), finished); expected_pongs.insert(payload.clone(), finished);
Box::new( Box::new(
sink.send(payload).map(|sink| Loop::Continue((sink, stream))), sink.send(payload)
) as Box<Future<Item = _, Error = _>> .map(|sink| Loop::Continue((sink, stream))),
)
as Box<Future<Item = _, Error = _>>
} }
Message::Received(payload) => { Message::Received(payload) => {
// Received a payload from the remote. // Received a payload from the remote.
@ -193,22 +205,24 @@ impl<C> ConnectionUpgrade<C> for Ping
(payload={:?}) ; ping fufilled", (payload={:?}) ; ping fufilled",
remote_addr.expect("debug log level is enabled"), payload); remote_addr.expect("debug log level is enabled"), payload);
let _ = fut.send(()); let _ = fut.send(());
Box::new(Ok(Loop::Continue((sink, stream))).into_future()) as Box::new(Ok(Loop::Continue((sink, stream))).into_future())
Box<Future<Item = _, Error = _>> as Box<Future<Item = _, Error = _>>
} else { } else {
// Payload was not ours. Sending it back. // Payload was not ours. Sending it back.
debug!(target: "libp2p-ping", "Received ping from {:?} \ debug!(target: "libp2p-ping", "Received ping from {:?} \
(payload={:?}) ; sending back", (payload={:?}) ; sending back",
remote_addr.expect("debug log level is enabled"), payload); remote_addr.expect("debug log level is enabled"), payload);
Box::new( Box::new(
sink.send(payload).map(|sink| Loop::Continue((sink, stream))), sink.send(payload)
) as Box<Future<Item = _, Error = _>> .map(|sink| Loop::Continue((sink, stream))),
)
as Box<Future<Item = _, Error = _>>
} }
} }
} }
} else { } else {
Box::new(Ok(Loop::Break(())).into_future()) as Box<Future<Item = _, Error = _>> Box::new(Ok(Loop::Break(())).into_future())
as Box<Future<Item = _, Error = _>>
} }
}) })
}); });
@ -234,7 +248,9 @@ impl Pinger {
debug!(target: "libp2p-ping", "Preparing for ping with payload {:?}", payload); debug!(target: "libp2p-ping", "Preparing for ping with payload {:?}", payload);
// Ignore errors if the ponger has been already destroyed. The returned future will never // Ignore errors if the ponger has been already destroyed. The returned future will never
// be signalled. // be signalled.
let fut = self.send.clone().send(Message::Ping(Bytes::from(payload.to_vec()), tx)) let fut = self.send
.clone()
.send(Message::Ping(Bytes::from(payload.to_vec()), tx))
.from_err() .from_err()
.and_then(|_| rx.from_err()); .and_then(|_| rx.from_err());
Box::new(fut) as Box<_> Box::new(fut) as Box<_>
@ -256,7 +272,11 @@ impl Decoder for Codec {
#[inline] #[inline]
fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<BytesMut>, IoError> { fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<BytesMut>, IoError> {
if buf.len() >= 32 { Ok(Some(buf.split_to(32))) } else { Ok(None) } if buf.len() >= 32 {
Ok(Some(buf.split_to(32)))
} else {
Ok(None)
}
} }
} }
@ -294,24 +314,42 @@ mod tests {
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap(); let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
let listener_addr = listener.local_addr().unwrap(); let listener_addr = listener.local_addr().unwrap();
let server = listener.incoming() let server = listener
.incoming()
.into_future() .into_future()
.map_err(|(e, _)| e.into()) .map_err(|(e, _)| e.into())
.and_then(|(c, _)| { .and_then(|(c, _)| {
Ping.upgrade(c.unwrap().0, (), Endpoint::Listener, Ping.upgrade(
&"/ip4/127.0.0.1/tcp/10000".parse().unwrap()) c.unwrap().0,
(),
Endpoint::Listener,
&"/ip4/127.0.0.1/tcp/10000".parse().unwrap(),
)
}) })
.and_then(|(mut pinger, service)| { .and_then(|(mut pinger, service)| {
pinger.ping().map_err(|_| panic!()).select(service).map_err(|_| panic!()) pinger
.ping()
.map_err(|_| panic!())
.select(service)
.map_err(|_| panic!())
}); });
let client = TcpStream::connect(&listener_addr, &core.handle()) let client = TcpStream::connect(&listener_addr, &core.handle())
.map_err(|e| e.into()) .map_err(|e| e.into())
.and_then(|c| { .and_then(|c| {
Ping.upgrade(c, (), Endpoint::Dialer, &"/ip4/127.0.0.1/tcp/10000".parse().unwrap()) Ping.upgrade(
c,
(),
Endpoint::Dialer,
&"/ip4/127.0.0.1/tcp/10000".parse().unwrap(),
)
}) })
.and_then(|(mut pinger, service)| { .and_then(|(mut pinger, service)| {
pinger.ping().map_err(|_| panic!()).select(service).map_err(|_| panic!()) pinger
.ping()
.map_err(|_| panic!())
.select(service)
.map_err(|_| panic!())
}); });
core.run(server.join(client)).unwrap(); core.run(server.join(client)).unwrap();
@ -325,26 +363,39 @@ mod tests {
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap(); let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
let listener_addr = listener.local_addr().unwrap(); let listener_addr = listener.local_addr().unwrap();
let server = listener.incoming() let server = listener
.incoming()
.into_future() .into_future()
.map_err(|(e, _)| e.into()) .map_err(|(e, _)| e.into())
.and_then(|(c, _)| { .and_then(|(c, _)| {
Ping.upgrade(c.unwrap().0, (), Endpoint::Listener, Ping.upgrade(
&"/ip4/127.0.0.1/tcp/10000".parse().unwrap()) c.unwrap().0,
(),
Endpoint::Listener,
&"/ip4/127.0.0.1/tcp/10000".parse().unwrap(),
)
}) })
.and_then(|(_, service)| service.map_err(|_| panic!())); .and_then(|(_, service)| service.map_err(|_| panic!()));
let client = TcpStream::connect(&listener_addr, &core.handle()) let client = TcpStream::connect(&listener_addr, &core.handle())
.map_err(|e| e.into()) .map_err(|e| e.into())
.and_then(|c| Ping.upgrade(c, (), Endpoint::Dialer, .and_then(|c| {
&"/ip4/127.0.0.1/tcp/1000".parse().unwrap())) Ping.upgrade(
c,
(),
Endpoint::Dialer,
&"/ip4/127.0.0.1/tcp/1000".parse().unwrap(),
)
})
.and_then(|(mut pinger, service)| { .and_then(|(mut pinger, service)| {
let pings = (0 .. 20).map(move |_| { let pings = (0..20).map(move |_| pinger.ping().map_err(|_| ()));
pinger.ping().map_err(|_| ())
});
join_all(pings).map(|_| ()).map_err(|_| panic!()) join_all(pings)
.select(service).map(|_| ()).map_err(|_| panic!()) .map(|_| ())
.map_err(|_| panic!())
.select(service)
.map(|_| ())
.map_err(|_| panic!())
}); });
core.run(server.select(client)).unwrap_or_else(|_| panic!()); core.run(server.select(client)).unwrap_or_else(|_| panic!());

View File

@ -61,8 +61,9 @@ impl<S> DecoderMiddleware<S> {
} }
impl<S> Stream for DecoderMiddleware<S> impl<S> Stream for DecoderMiddleware<S>
where S: Stream<Item = BytesMut>, where
S::Error: Into<SecioError> S: Stream<Item = BytesMut>,
S::Error: Into<SecioError>,
{ {
type Item = Vec<u8>; type Item = Vec<u8>;
type Error = SecioError; type Error = SecioError;
@ -93,14 +94,16 @@ impl<S> Stream for DecoderMiddleware<S>
// Note that there is no way to decipher in place with rust-crypto right now. // Note that there is no way to decipher in place with rust-crypto right now.
let mut decrypted_data = crypted_data.to_vec(); let mut decrypted_data = crypted_data.to_vec();
self.cipher_state.process(&crypted_data, &mut decrypted_data); self.cipher_state
.process(&crypted_data, &mut decrypted_data);
Ok(Async::Ready(Some(decrypted_data))) Ok(Async::Ready(Some(decrypted_data)))
} }
} }
impl<S> Sink for DecoderMiddleware<S> impl<S> Sink for DecoderMiddleware<S>
where S: Sink where
S: Sink,
{ {
type SinkItem = S::SinkItem; type SinkItem = S::SinkItem;
type SinkError = S::SinkError; type SinkError = S::SinkError;

View File

@ -56,7 +56,8 @@ impl<S> EncoderMiddleware<S> {
} }
impl<S> Sink for EncoderMiddleware<S> impl<S> Sink for EncoderMiddleware<S>
where S: Sink<SinkItem = BytesMut> where
S: Sink<SinkItem = BytesMut>,
{ {
type SinkItem = BytesMut; type SinkItem = BytesMut;
type SinkError = S::SinkError; type SinkError = S::SinkError;
@ -86,7 +87,8 @@ impl<S> Sink for EncoderMiddleware<S>
} }
impl<S> Stream for EncoderMiddleware<S> impl<S> Stream for EncoderMiddleware<S>
where S: Stream where
S: Stream,
{ {
type Item = S::Item; type Item = S::Item;
type Error = S::Error; type Error = S::Error;

View File

@ -47,7 +47,8 @@ pub fn full_codec<S>(
cipher_decoder: Box<SynchronousStreamCipher>, cipher_decoder: Box<SynchronousStreamCipher>,
decoding_hmac: hmac::VerificationKey, decoding_hmac: hmac::VerificationKey,
) -> FullCodec<S> ) -> FullCodec<S>
where S: AsyncRead + AsyncWrite where
S: AsyncRead + AsyncWrite,
{ {
let encoder = EncoderMiddleware::new(socket, cipher_encoding, encoding_hmac); let encoder = EncoderMiddleware::new(socket, cipher_encoding, encoding_hmac);
let codec = DecoderMiddleware::new(encoder, cipher_decoder, decoding_hmac); let codec = DecoderMiddleware::new(encoder, cipher_decoder, decoding_hmac);
@ -86,16 +87,20 @@ mod tests {
let cipher_key: [u8; 32] = rand::random(); let cipher_key: [u8; 32] = rand::random();
let hmac_key: [u8; 32] = rand::random(); let hmac_key: [u8; 32] = rand::random();
let encoder = let encoder = EncoderMiddleware::new(
EncoderMiddleware::new(
data_tx, data_tx,
Box::new(CtrMode::new(AesSafe256Encryptor::new(&cipher_key), vec![0; 16])), Box::new(CtrMode::new(
AesSafe256Encryptor::new(&cipher_key),
vec![0; 16],
)),
SigningKey::new(&SHA256, &hmac_key), SigningKey::new(&SHA256, &hmac_key),
); );
let decoder = let decoder = DecoderMiddleware::new(
DecoderMiddleware::new(
data_rx, data_rx,
Box::new(CtrMode::new(AesSafe256Encryptor::new(&cipher_key), vec![0; 16])), Box::new(CtrMode::new(
AesSafe256Encryptor::new(&cipher_key),
vec![0; 16],
)),
VerificationKey::new(&SHA256, &hmac_key), VerificationKey::new(&SHA256, &hmac_key),
); );
@ -105,7 +110,9 @@ mod tests {
let data_received = decoder.into_future().map(|(n, _)| n).map_err(|(e, _)| e); let data_received = decoder.into_future().map(|(n, _)| n).map_err(|(e, _)| e);
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
let (_, decoded) = core.run(data_sent.join(data_received)).map_err(|_| ()).unwrap(); let (_, decoded) = core.run(data_sent.join(data_received))
.map_err(|_| ())
.unwrap();
assert_eq!(decoded.unwrap(), data); assert_eq!(decoded.unwrap(), data);
} }
@ -123,18 +130,25 @@ mod tests {
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap(); let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
let listener_addr = listener.local_addr().unwrap(); let listener_addr = listener.local_addr().unwrap();
let server = let server = listener.incoming().into_future().map_err(|(e, _)| e).map(
listener.incoming().into_future().map_err(|(e, _)| e).map(move |(connec, _)| { move |(connec, _)| {
let connec = Framed::new(connec.unwrap().0); let connec = Framed::new(connec.unwrap().0);
full_codec( full_codec(
connec, connec,
Box::new(CtrMode::new(AesSafe256Encryptor::new(&cipher_key), vec![0; 16])), Box::new(CtrMode::new(
AesSafe256Encryptor::new(&cipher_key),
vec![0; 16],
)),
SigningKey::new(&SHA256, &hmac_key), SigningKey::new(&SHA256, &hmac_key),
Box::new(CtrMode::new(AesSafe256Encryptor::new(&cipher_key), vec![0; 16])), Box::new(CtrMode::new(
AesSafe256Encryptor::new(&cipher_key),
vec![0; 16],
)),
VerificationKey::new(&SHA256, &hmac_key), VerificationKey::new(&SHA256, &hmac_key),
) )
}); },
);
let client = TcpStream::connect(&listener_addr, &core.handle()) let client = TcpStream::connect(&listener_addr, &core.handle())
.map_err(|e| e.into()) .map_err(|e| e.into())
@ -143,17 +157,27 @@ mod tests {
full_codec( full_codec(
stream, stream,
Box::new(CtrMode::new(AesSafe256Encryptor::new(&cipher_key_clone), vec![0; 16])), Box::new(CtrMode::new(
AesSafe256Encryptor::new(&cipher_key_clone),
vec![0; 16],
)),
SigningKey::new(&SHA256, &hmac_key_clone), SigningKey::new(&SHA256, &hmac_key_clone),
Box::new(CtrMode::new(AesSafe256Encryptor::new(&cipher_key_clone), vec![0; 16])), Box::new(CtrMode::new(
AesSafe256Encryptor::new(&cipher_key_clone),
vec![0; 16],
)),
VerificationKey::new(&SHA256, &hmac_key_clone), VerificationKey::new(&SHA256, &hmac_key_clone),
) )
}); });
let fin = server.join(client) let fin = server
.join(client)
.from_err::<SecioError>() .from_err::<SecioError>()
.and_then(|(server, client)| { .and_then(|(server, client)| {
client.send(BytesMut::from(&data_clone[..])).map(move |_| server).from_err() client
.send(BytesMut::from(&data_clone[..]))
.map(move |_| server)
.from_err()
}) })
.and_then(|server| server.into_future().map_err(|(e, _)| e.into())) .and_then(|server| server.into_future().map_err(|(e, _)| e.into()))
.map(|recved| recved.0.unwrap().to_vec()); .map(|recved| recved.0.unwrap().to_vec());

View File

@ -69,50 +69,32 @@ impl error::Error for SecioError {
#[inline] #[inline]
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
SecioError::IoError(_) => { SecioError::IoError(_) => "I/O error",
"I/O error"
}
SecioError::HandshakeParsingFailure => { SecioError::HandshakeParsingFailure => {
"Failed to parse one of the handshake protobuf messages" "Failed to parse one of the handshake protobuf messages"
} }
SecioError::NoSupportIntersection(_, _) => { SecioError::NoSupportIntersection(_, _) => {
"There is no protocol supported by both the local and remote hosts" "There is no protocol supported by both the local and remote hosts"
} }
SecioError::NonceGenerationFailed => { SecioError::NonceGenerationFailed => "Failed to generate nonce",
"Failed to generate nonce" SecioError::EphemeralKeyGenerationFailed => "Failed to generate ephemeral key",
} SecioError::SigningFailure => "Failed to sign a message with our local private key",
SecioError::EphemeralKeyGenerationFailed => {
"Failed to generate ephemeral key"
}
SecioError::SigningFailure => {
"Failed to sign a message with our local private key"
}
SecioError::SignatureVerificationFailed => { SecioError::SignatureVerificationFailed => {
"The signature of the exchange packet doesn't verify the remote public key" "The signature of the exchange packet doesn't verify the remote public key"
} }
SecioError::SecretGenerationFailed => { SecioError::SecretGenerationFailed => {
"Failed to generate the secret shared key from the ephemeral key" "Failed to generate the secret shared key from the ephemeral key"
} }
SecioError::NonceVerificationFailed => { SecioError::NonceVerificationFailed => "The final check of the handshake failed",
"The final check of the handshake failed" SecioError::CipherError(_) => "Error while decoding/encoding data",
} SecioError::FrameTooShort => "The received frame was of invalid length",
SecioError::CipherError(_) => { SecioError::HmacNotMatching => "The hashes of the message didn't match",
"Error while decoding/encoding data"
}
SecioError::FrameTooShort => {
"The received frame was of invalid length"
}
SecioError::HmacNotMatching => {
"The hashes of the message didn't match"
}
} }
} }
fn cause(&self) -> Option<&error::Error> { fn cause(&self) -> Option<&error::Error> {
match *self { match *self {
SecioError::IoError(ref err) => { SecioError::IoError(ref err) => Some(err),
Some(err)
}
// TODO: The type doesn't implement `Error` // TODO: The type doesn't implement `Error`
/*SecioError::CipherError(ref err) => { /*SecioError::CipherError(ref err) => {
Some(err) Some(err)

View File

@ -27,20 +27,20 @@ use futures::Future;
use futures::future; use futures::future;
use futures::sink::Sink; use futures::sink::Sink;
use futures::stream::Stream; use futures::stream::Stream;
use keys_proto::{PublicKey as PublicKeyProtobuf, KeyType as KeyTypeProtobuf}; use keys_proto::{KeyType as KeyTypeProtobuf, PublicKey as PublicKeyProtobuf};
use protobuf::Message as ProtobufMessage; use protobuf::Message as ProtobufMessage;
use protobuf::core::parse_from_bytes as protobuf_parse_from_bytes; use protobuf::core::parse_from_bytes as protobuf_parse_from_bytes;
use ring::{agreement, digest, rand}; use ring::{agreement, digest, rand};
use ring::agreement::EphemeralPrivateKey; use ring::agreement::EphemeralPrivateKey;
use ring::hmac::{SigningKey, SigningContext, VerificationKey}; use ring::hmac::{SigningContext, SigningKey, VerificationKey};
use ring::rand::SecureRandom; use ring::rand::SecureRandom;
use ring::signature::{RSAKeyPair, RSASigningState, RSA_PKCS1_SHA256, RSA_PKCS1_2048_8192_SHA256}; use ring::signature::{RSAKeyPair, RSASigningState, RSA_PKCS1_2048_8192_SHA256, RSA_PKCS1_SHA256};
use ring::signature::verify as signature_verify; use ring::signature::verify as signature_verify;
use std::cmp::{self, Ordering}; use std::cmp::{self, Ordering};
use std::io::{Error as IoError, ErrorKind as IoErrorKind}; use std::io::{Error as IoError, ErrorKind as IoErrorKind};
use std::mem; use std::mem;
use std::sync::Arc; use std::sync::Arc;
use structs_proto::{Propose, Exchange}; use structs_proto::{Exchange, Propose};
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::length_delimited; use tokio_io::codec::length_delimited;
use untrusted::Input as UntrustedInput; use untrusted::Input as UntrustedInput;
@ -58,7 +58,8 @@ pub fn handshake<'a, S: 'a>(
local_public_key: Vec<u8>, local_public_key: Vec<u8>,
local_private_key: Arc<RSAKeyPair>, local_private_key: Arc<RSAKeyPair>,
) -> Box<Future<Item = (FullCodec<S>, Vec<u8>), Error = SecioError> + 'a> ) -> Box<Future<Item = (FullCodec<S>, Vec<u8>), Error = SecioError> + 'a>
where S: AsyncRead + AsyncWrite where
S: AsyncRead + AsyncWrite,
{ {
// TODO: could be rewritten as a coroutine once coroutines land in stable Rust // TODO: could be rewritten as a coroutine once coroutines land in stable Rust
@ -128,8 +129,10 @@ pub fn handshake<'a, S: 'a>(
}; };
// The handshake messages all start with a 4-bytes message length prefix. // The handshake messages all start with a 4-bytes message length prefix.
let socket = let socket = length_delimited::Builder::new()
length_delimited::Builder::new().big_endian().length_field_length(4).new_framed(socket); .big_endian()
.length_field_length(4)
.new_framed(socket);
let future = future::ok::<_, SecioError>(context) let future = future::ok::<_, SecioError>(context)
// Generate our nonce. // Generate our nonce.
@ -180,7 +183,9 @@ pub fn handshake<'a, S: 'a>(
}, },
}; };
let mut prop = match protobuf_parse_from_bytes::<Propose>(&context.remote_proposition_bytes) { let mut prop = match protobuf_parse_from_bytes::<Propose>(
&context.remote_proposition_bytes
) {
Ok(prop) => prop, Ok(prop) => prop,
Err(_) => { Err(_) => {
debug!(target: "libp2p-secio", "failed to parse remote's proposition \ debug!(target: "libp2p-secio", "failed to parse remote's proposition \
@ -553,12 +558,11 @@ mod tests {
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap(); let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
let listener_addr = listener.local_addr().unwrap(); let listener_addr = listener.local_addr().unwrap();
let server = listener.incoming() let server = listener
.incoming()
.into_future() .into_future()
.map_err(|(e, _)| e.into()) .map_err(|(e, _)| e.into())
.and_then(move |(connec, _)| { .and_then(move |(connec, _)| handshake(connec.unwrap().0, public_key1, private_key1));
handshake(connec.unwrap().0, public_key1, private_key1)
});
let client = TcpStream::connect(&listener_addr, &core.handle()) let client = TcpStream::connect(&listener_addr, &core.handle())
.map_err(|e| e.into()) .map_err(|e| e.into())
@ -576,254 +580,44 @@ mod tests {
assert_eq!( assert_eq!(
&output, &output,
&[ &[
103, 103, 144, 60, 199, 85, 145, 239, 71, 79, 198, 85, 164, 32, 53, 143, 205, 50, 48,
144, 153, 10, 37, 32, 85, 1, 226, 61, 193, 1, 154, 120, 207, 80,
60,
199,
85,
145,
239,
71,
79,
198,
85,
164,
32,
53,
143,
205,
50,
48,
153,
10,
37,
32,
85,
1,
226,
61,
193,
1,
154,
120,
207,
80,
] ]
); );
let key2 = SigningKey::new( let key2 = SigningKey::new(
&SHA256, &SHA256,
&[ &[
157, 157, 166, 80, 144, 77, 193, 198, 6, 23, 220, 87, 220, 191, 72, 168, 197, 54, 33,
166, 219, 225, 84, 156, 165, 37, 149, 224, 244, 32, 170, 79, 125, 35, 171, 26, 178, 176,
80, 92, 168, 22, 27, 205, 44, 229, 61, 152, 21, 222, 81, 241, 81, 116, 236, 74, 166,
144, 89, 145, 5, 162, 108, 230, 55, 54, 9, 17,
77,
193,
198,
6,
23,
220,
87,
220,
191,
72,
168,
197,
54,
33,
219,
225,
84,
156,
165,
37,
149,
224,
244,
32,
170,
79,
125,
35,
171,
26,
178,
176,
92,
168,
22,
27,
205,
44,
229,
61,
152,
21,
222,
81,
241,
81,
116,
236,
74,
166,
89,
145,
5,
162,
108,
230,
55,
54,
9,
17,
], ],
); );
stretch_key(&key2, &mut output); stretch_key(&key2, &mut output);
assert_eq!( assert_eq!(
&output, &output,
&[ &[
39, 39, 151, 182, 63, 180, 175, 224, 139, 42, 131, 130, 116, 55, 146, 62, 31, 157, 95,
151, 217, 15, 73, 81, 10, 83, 243, 141, 64, 227, 103, 144, 99, 121,
182,
63,
180,
175,
224,
139,
42,
131,
130,
116,
55,
146,
62,
31,
157,
95,
217,
15,
73,
81,
10,
83,
243,
141,
64,
227,
103,
144,
99,
121,
] ]
); );
let key3 = SigningKey::new( let key3 = SigningKey::new(
&SHA256, &SHA256,
&[ &[
98, 98, 219, 94, 104, 97, 70, 139, 13, 185, 110, 56, 36, 66, 3, 80, 224, 32, 205, 102,
219, 170, 59, 32, 140, 245, 86, 102, 231, 68, 85, 249, 227, 243, 57, 53, 171, 36, 62,
94, 225, 178, 74, 89, 142, 151, 94, 183, 231, 208, 166, 244, 130, 130, 209, 248, 65,
104, 19, 48, 127, 127, 55, 82, 117, 154, 124, 108,
97,
70,
139,
13,
185,
110,
56,
36,
66,
3,
80,
224,
32,
205,
102,
170,
59,
32,
140,
245,
86,
102,
231,
68,
85,
249,
227,
243,
57,
53,
171,
36,
62,
225,
178,
74,
89,
142,
151,
94,
183,
231,
208,
166,
244,
130,
130,
209,
248,
65,
19,
48,
127,
127,
55,
82,
117,
154,
124,
108,
], ],
); );
stretch_key(&key3, &mut output); stretch_key(&key3, &mut output);
assert_eq!( assert_eq!(
&output, &output,
&[ &[
28, 28, 39, 158, 206, 164, 16, 211, 194, 99, 43, 208, 36, 24, 141, 90, 93, 157, 236,
39, 238, 111, 170, 0, 60, 11, 49, 174, 177, 121, 30, 12, 182, 25,
158,
206,
164,
16,
211,
194,
99,
43,
208,
36,
24,
141,
90,
93,
157,
236,
238,
111,
170,
0,
60,
11,
49,
174,
177,
121,
30,
12,
182,
25,
] ]
); );
} }

View File

@ -95,7 +95,7 @@ extern crate untrusted;
pub use self::error::SecioError; pub use self::error::SecioError;
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use futures::{Future, Poll, StartSend, Sink, Stream}; use futures::{Future, Poll, Sink, StartSend, Stream};
use futures::stream::MapErr as StreamMapErr; use futures::stream::MapErr as StreamMapErr;
use libp2p_swarm::Multiaddr; use libp2p_swarm::Multiaddr;
use ring::signature::RSAKeyPair; use ring::signature::RSAKeyPair;
@ -150,18 +150,21 @@ pub struct SecioKeyPair {
} }
impl SecioKeyPair { impl SecioKeyPair {
pub fn rsa_from_pkcs8<P>(private: &[u8], public: P) pub fn rsa_from_pkcs8<P>(
-> Result<SecioKeyPair, Box<Error + Send + Sync>> private: &[u8],
where P: Into<Vec<u8>> public: P,
) -> Result<SecioKeyPair, Box<Error + Send + Sync>>
where
P: Into<Vec<u8>>,
{ {
let private = RSAKeyPair::from_pkcs8(Input::from(&private[..])) let private =
.map_err(|err| Box::new(err))?; RSAKeyPair::from_pkcs8(Input::from(&private[..])).map_err(|err| Box::new(err))?;
Ok(SecioKeyPair { Ok(SecioKeyPair {
inner: SecioKeyPairInner::Rsa { inner: SecioKeyPairInner::Rsa {
public: public.into(), public: public.into(),
private: Arc::new(private), private: Arc::new(private),
} },
}) })
} }
} }
@ -172,7 +175,7 @@ enum SecioKeyPairInner {
Rsa { Rsa {
public: Vec<u8>, public: Vec<u8>,
private: Arc<RSAKeyPair>, private: Arc<RSAKeyPair>,
} },
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -182,14 +185,10 @@ pub enum SecioPublicKey<'a> {
} }
impl<S> libp2p_swarm::ConnectionUpgrade<S> for SecioConfig impl<S> libp2p_swarm::ConnectionUpgrade<S> for SecioConfig
where S: AsyncRead + AsyncWrite + 'static where
S: AsyncRead + AsyncWrite + 'static,
{ {
type Output = RwStreamSink< type Output = RwStreamSink<StreamMapErr<SecioMiddleware<S>, fn(SecioError) -> IoError>>;
StreamMapErr<
SecioMiddleware<S>,
fn(SecioError) -> IoError,
>,
>;
type Future = Box<Future<Item = Self::Output, Error = IoError>>; type Future = Box<Future<Item = Self::Output, Error = IoError>>;
type NamesIter = iter::Once<(Bytes, ())>; type NamesIter = iter::Once<(Bytes, ())>;
type UpgradeIdentifier = (); type UpgradeIdentifier = ();
@ -200,15 +199,16 @@ impl<S> libp2p_swarm::ConnectionUpgrade<S> for SecioConfig
} }
#[inline] #[inline]
fn upgrade(self, incoming: S, _: (), _: libp2p_swarm::Endpoint, remote_addr: &Multiaddr) fn upgrade(
-> Self::Future self,
{ incoming: S,
_: (),
_: libp2p_swarm::Endpoint,
remote_addr: &Multiaddr,
) -> Self::Future {
info!(target: "libp2p-secio", "starting secio upgrade with {:?}", remote_addr); info!(target: "libp2p-secio", "starting secio upgrade with {:?}", remote_addr);
let fut = SecioMiddleware::handshake( let fut = SecioMiddleware::handshake(incoming, self.key);
incoming,
self.key,
);
let wrapped = fut.map(|stream_sink| { let wrapped = fut.map(|stream_sink| {
let mapped = stream_sink.map_err(map_err as fn(_) -> _); let mapped = stream_sink.map_err(map_err as fn(_) -> _);
RwStreamSink::new(mapped) RwStreamSink::new(mapped)
@ -233,7 +233,8 @@ pub struct SecioMiddleware<S> {
} }
impl<S> SecioMiddleware<S> impl<S> SecioMiddleware<S>
where S: AsyncRead + AsyncWrite where
S: AsyncRead + AsyncWrite,
{ {
/// Attempts to perform a handshake on the given socket. /// Attempts to perform a handshake on the given socket.
/// ///
@ -243,16 +244,15 @@ impl<S> SecioMiddleware<S>
socket: S, socket: S,
key_pair: SecioKeyPair, key_pair: SecioKeyPair,
) -> Box<Future<Item = SecioMiddleware<S>, Error = SecioError> + 'a> ) -> Box<Future<Item = SecioMiddleware<S>, Error = SecioError> + 'a>
where S: 'a where
S: 'a,
{ {
let SecioKeyPairInner::Rsa { private, public } = key_pair.inner; let SecioKeyPairInner::Rsa { private, public } = key_pair.inner;
let fut = handshake::handshake(socket, public, private) let fut =
.map(|(inner, pubkey)| { handshake::handshake(socket, public, private).map(|(inner, pubkey)| SecioMiddleware {
SecioMiddleware {
inner: inner, inner: inner,
remote_pubkey_der: pubkey, remote_pubkey_der: pubkey,
}
}); });
Box::new(fut) Box::new(fut)
} }
@ -265,7 +265,8 @@ impl<S> SecioMiddleware<S>
} }
impl<S> Sink for SecioMiddleware<S> impl<S> Sink for SecioMiddleware<S>
where S: AsyncRead + AsyncWrite where
S: AsyncRead + AsyncWrite,
{ {
type SinkItem = BytesMut; type SinkItem = BytesMut;
type SinkError = IoError; type SinkError = IoError;
@ -282,7 +283,8 @@ impl<S> Sink for SecioMiddleware<S>
} }
impl<S> Stream for SecioMiddleware<S> impl<S> Stream for SecioMiddleware<S>
where S: AsyncRead + AsyncWrite where
S: AsyncRead + AsyncWrite,
{ {
type Item = Vec<u8>; type Item = Vec<u8>;
type Error = SecioError; type Error = SecioError;

View File

@ -40,7 +40,7 @@
//! `MuxedTransport` trait. //! `MuxedTransport` trait.
use fnv::FnvHashMap; use fnv::FnvHashMap;
use futures::future::{self, IntoFuture, FutureResult}; use futures::future::{self, FutureResult, IntoFuture};
use futures::{Async, Future, Poll, Stream}; use futures::{Async, Future, Poll, Stream};
use futures::stream::Fuse as StreamFuse; use futures::stream::Fuse as StreamFuse;
use futures::sync::mpsc; use futures::sync::mpsc;
@ -70,7 +70,10 @@ where
shared: Arc<Mutex<Shared<C::Output>>>, shared: Arc<Mutex<Shared<C::Output>>>,
} }
struct Shared<M> where M: StreamMuxer { struct Shared<M>
where
M: StreamMuxer,
{
// List of active muxers. // List of active muxers.
active_connections: FnvHashMap<Multiaddr, M>, active_connections: FnvHashMap<Multiaddr, M>,
@ -125,7 +128,13 @@ where
let (listener, new_addr) = match self.inner.listen_on(addr.clone()) { let (listener, new_addr) = match self.inner.listen_on(addr.clone()) {
Ok((l, a)) => (l, a), Ok((l, a)) => (l, a),
Err((inner, addr)) => { Err((inner, addr)) => {
return Err((ConnectionReuse { inner: inner, shared: self.shared }, addr)); return Err((
ConnectionReuse {
inner: inner,
shared: self.shared,
},
addr,
));
} }
}; };
@ -141,7 +150,12 @@ where
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, (Self, Multiaddr)> { fn dial(self, addr: Multiaddr) -> Result<Self::Dial, (Self, Multiaddr)> {
// If we already have an active connection, use it! // If we already have an active connection, use it!
if let Some(connec) = self.shared.lock().active_connections.get(&addr).map(|c| c.clone()) { if let Some(connec) = self.shared
.lock()
.active_connections
.get(&addr)
.map(|c| c.clone())
{
let future = connec.outbound().map(|s| (s, addr)); let future = connec.outbound().map(|s| (s, addr));
return Ok(Box::new(future) as Box<_>); return Ok(Box::new(future) as Box<_>);
} }
@ -152,20 +166,27 @@ where
let dial = match self.inner.dial(addr) { let dial = match self.inner.dial(addr) {
Ok(l) => l, Ok(l) => l,
Err((inner, addr)) => { Err((inner, addr)) => {
return Err((ConnectionReuse { inner: inner, shared: self.shared }, addr)); return Err((
ConnectionReuse {
inner: inner,
shared: self.shared,
},
addr,
));
} }
}; };
let shared = self.shared.clone(); let shared = self.shared.clone();
let dial = dial let dial = dial.into_future().and_then(move |(connec, addr)| {
.into_future()
.and_then(move |(connec, addr)| {
// Always replace the active connection because we are the most recent. // Always replace the active connection because we are the most recent.
let mut lock = shared.lock(); let mut lock = shared.lock();
lock.active_connections.insert(addr.clone(), connec.clone()); lock.active_connections.insert(addr.clone(), connec.clone());
// TODO: doesn't need locking ; the sender could be extracted // TODO: doesn't need locking ; the sender could be extracted
let _ = lock.add_to_next_tx let _ = lock.add_to_next_tx.unbounded_send((
.unbounded_send((connec.clone(), connec.clone().inbound(), addr.clone())); connec.clone(),
connec.clone().inbound(),
addr.clone(),
));
connec.outbound().map(|s| (s, addr)) connec.outbound().map(|s| (s, addr))
}); });
@ -187,11 +208,14 @@ where
C::NamesIter: Clone, // TODO: not elegant C::NamesIter: Clone, // TODO: not elegant
{ {
type Incoming = ConnectionReuseIncoming<C::Output>; type Incoming = ConnectionReuseIncoming<C::Output>;
type IncomingUpgrade = future::FutureResult<(<C::Output as StreamMuxer>::Substream, Multiaddr), IoError>; type IncomingUpgrade =
future::FutureResult<(<C::Output as StreamMuxer>::Substream, Multiaddr), IoError>;
#[inline] #[inline]
fn next_incoming(self) -> Self::Incoming { fn next_incoming(self) -> Self::Incoming {
ConnectionReuseIncoming { shared: self.shared.clone() } ConnectionReuseIncoming {
shared: self.shared.clone(),
}
} }
} }
@ -212,9 +236,10 @@ where
} }
impl<S, F, M> Stream for ConnectionReuseListener<S, F, M> impl<S, F, M> Stream for ConnectionReuseListener<S, F, M>
where S: Stream<Item = F, Error = IoError>, where
S: Stream<Item = F, Error = IoError>,
F: Future<Item = (M, Multiaddr), Error = IoError>, F: Future<Item = (M, Multiaddr), Error = IoError>,
M: StreamMuxer + Clone + 'static // TODO: 'static :( M: StreamMuxer + Clone + 'static, // TODO: 'static :(
{ {
type Item = FutureResult<(M::Substream, Multiaddr), IoError>; type Item = FutureResult<(M::Substream, Multiaddr), IoError>;
type Error = IoError; type Error = IoError;
@ -227,7 +252,7 @@ where S: Stream<Item = F, Error = IoError>,
Ok(Async::Ready(Some(upgrade))) => { Ok(Async::Ready(Some(upgrade))) => {
self.current_upgrades.push(upgrade); self.current_upgrades.push(upgrade);
} }
Ok(Async::NotReady) => {}, Ok(Async::NotReady) => {}
Ok(Async::Ready(None)) => { Ok(Async::Ready(None)) => {
if self.connections.is_empty() && self.current_upgrades.is_empty() { if self.connections.is_empty() && self.current_upgrades.is_empty() {
return Ok(Async::Ready(None)); return Ok(Async::Ready(None));
@ -243,35 +268,42 @@ where S: Stream<Item = F, Error = IoError>,
// Check whether any upgrade (to a muxer) on an incoming connection is ready. // Check whether any upgrade (to a muxer) on an incoming connection is ready.
// We extract everything at the start, then insert back the elements that we still want at // We extract everything at the start, then insert back the elements that we still want at
// the next iteration. // the next iteration.
for n in (0 .. self.current_upgrades.len()).rev() { for n in (0..self.current_upgrades.len()).rev() {
let mut current_upgrade = self.current_upgrades.swap_remove(n); let mut current_upgrade = self.current_upgrades.swap_remove(n);
match current_upgrade.poll() { match current_upgrade.poll() {
Ok(Async::Ready((muxer, client_addr))) => { Ok(Async::Ready((muxer, client_addr))) => {
let next_incoming = muxer.clone().inbound(); let next_incoming = muxer.clone().inbound();
self.connections.push((muxer.clone(), next_incoming, client_addr.clone())); self.connections
.push((muxer.clone(), next_incoming, client_addr.clone()));
// We overwrite any current active connection to that multiaddr because we // We overwrite any current active connection to that multiaddr because we
// are the freshest possible connection. // are the freshest possible connection.
self.shared.lock().active_connections.insert(client_addr, muxer); self.shared
}, .lock()
.active_connections
.insert(client_addr, muxer);
}
Ok(Async::NotReady) => { Ok(Async::NotReady) => {
self.current_upgrades.push(current_upgrade); self.current_upgrades.push(current_upgrade);
}, }
Err(err) => { Err(err) => {
// Insert the rest of the pending upgrades, but not the current one. // Insert the rest of the pending upgrades, but not the current one.
return Ok(Async::Ready(Some(future::err(err)))); return Ok(Async::Ready(Some(future::err(err))));
}, }
} }
} }
// Check whether any incoming substream is ready. // Check whether any incoming substream is ready.
for n in (0 .. self.connections.len()).rev() { for n in (0..self.connections.len()).rev() {
let (muxer, mut next_incoming, client_addr) = self.connections.swap_remove(n); let (muxer, mut next_incoming, client_addr) = self.connections.swap_remove(n);
match next_incoming.poll() { match next_incoming.poll() {
Ok(Async::Ready(incoming)) => { Ok(Async::Ready(incoming)) => {
// A new substream is ready. // A new substream is ready.
let mut new_next = muxer.clone().inbound(); let mut new_next = muxer.clone().inbound();
self.connections.push((muxer, new_next, client_addr.clone())); self.connections
return Ok(Async::Ready(Some(Ok((incoming, client_addr)).into_future()))); .push((muxer, new_next, client_addr.clone()));
return Ok(Async::Ready(Some(
Ok((incoming, client_addr)).into_future(),
)));
} }
Ok(Async::NotReady) => { Ok(Async::NotReady) => {
self.connections.push((muxer, next_incoming, client_addr)); self.connections.push((muxer, next_incoming, client_addr));
@ -290,14 +322,16 @@ where S: Stream<Item = F, Error = IoError>,
/// Implementation of `Future` that yields the next incoming substream from a dialed connection. /// Implementation of `Future` that yields the next incoming substream from a dialed connection.
pub struct ConnectionReuseIncoming<M> pub struct ConnectionReuseIncoming<M>
where M: StreamMuxer where
M: StreamMuxer,
{ {
// Shared between the whole connection reuse system. // Shared between the whole connection reuse system.
shared: Arc<Mutex<Shared<M>>>, shared: Arc<Mutex<Shared<M>>>,
} }
impl<M> Future for ConnectionReuseIncoming<M> impl<M> Future for ConnectionReuseIncoming<M>
where M: Clone + StreamMuxer, where
M: Clone + StreamMuxer,
{ {
type Item = future::FutureResult<(M::Substream, Multiaddr), IoError>; type Item = future::FutureResult<(M::Substream, Multiaddr), IoError>;
type Error = IoError; type Error = IoError;
@ -312,17 +346,17 @@ impl<M> Future for ConnectionReuseIncoming<M>
match lock.add_to_next_rx.poll() { match lock.add_to_next_rx.poll() {
Ok(Async::Ready(Some(elem))) => { Ok(Async::Ready(Some(elem))) => {
lock.next_incoming.push(elem); lock.next_incoming.push(elem);
}, }
Ok(Async::NotReady) => break, Ok(Async::NotReady) => break,
Ok(Async::Ready(None)) | Err(_) => { Ok(Async::Ready(None)) | Err(_) => unreachable!(
unreachable!("the sender and receiver are both in the same struct, therefore \ "the sender and receiver are both in the same struct, therefore \
the link can never break") the link can never break"
}, ),
} }
} }
// Check whether any incoming substream is ready. // Check whether any incoming substream is ready.
for n in (0 .. lock.next_incoming.len()).rev() { for n in (0..lock.next_incoming.len()).rev() {
let (muxer, mut future, addr) = lock.next_incoming.swap_remove(n); let (muxer, mut future, addr) = lock.next_incoming.swap_remove(n);
match future.poll() { match future.poll() {
Ok(Async::Ready(value)) => { Ok(Async::Ready(value)) => {
@ -331,13 +365,13 @@ impl<M> Future for ConnectionReuseIncoming<M>
let next = muxer.clone().inbound(); let next = muxer.clone().inbound();
lock.next_incoming.push((muxer, next, addr.clone())); lock.next_incoming.push((muxer, next, addr.clone()));
return Ok(Async::Ready(future::ok((value, addr)))); return Ok(Async::Ready(future::ok((value, addr))));
}, }
Ok(Async::NotReady) => { Ok(Async::NotReady) => {
lock.next_incoming.push((muxer, future, addr)); lock.next_incoming.push((muxer, future, addr));
}, }
Err(_) => { Err(_) => {
// In case of error, we just not push back the element, which drops it. // In case of error, we just not push back the element, which drops it.
}, }
} }
} }

View File

@ -223,6 +223,6 @@ pub use self::connection_reuse::ConnectionReuse;
pub use self::multiaddr::Multiaddr; pub use self::multiaddr::Multiaddr;
pub use self::muxing::StreamMuxer; pub use self::muxing::StreamMuxer;
pub use self::swarm::{swarm, SwarmController, SwarmFuture}; pub use self::swarm::{swarm, SwarmController, SwarmFuture};
pub use self::transport::{ConnectionUpgrade, PlainTextConfig, Transport, UpgradedNode, OrUpgrade}; pub use self::transport::{ConnectionUpgrade, OrUpgrade, PlainTextConfig, Transport, UpgradedNode};
pub use self::transport::{Endpoint, SimpleProtocol, MuxedTransport, UpgradeExt}; pub use self::transport::{Endpoint, MuxedTransport, SimpleProtocol, UpgradeExt};
pub use self::transport::{DeniedConnectionUpgrade}; pub use self::transport::DeniedConnectionUpgrade;

View File

@ -19,7 +19,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
use std::io::Error as IoError; use std::io::Error as IoError;
use futures::{IntoFuture, Future, Stream, Async, Poll, future}; use futures::{future, Async, Future, IntoFuture, Poll, Stream};
use futures::sync::mpsc; use futures::sync::mpsc;
use {ConnectionUpgrade, Multiaddr, MuxedTransport, UpgradedNode}; use {ConnectionUpgrade, Multiaddr, MuxedTransport, UpgradedNode};
@ -31,9 +31,13 @@ use {ConnectionUpgrade, Multiaddr, MuxedTransport, UpgradedNode};
/// Produces a `SwarmController` and an implementation of `Future`. The controller can be used to /// Produces a `SwarmController` and an implementation of `Future`. The controller can be used to
/// control, and the `Future` must be driven to completion in order for things to work. /// control, and the `Future` must be driven to completion in order for things to work.
/// ///
pub fn swarm<T, C, H, F>(transport: T, upgrade: C, handler: H) pub fn swarm<T, C, H, F>(
-> (SwarmController<T, C>, SwarmFuture<T, C, H, F::Future>) transport: T,
where T: MuxedTransport + Clone + 'static, // TODO: 'static :-/ upgrade: C,
handler: H,
) -> (SwarmController<T, C>, SwarmFuture<T, C, H, F::Future>)
where
T: MuxedTransport + Clone + 'static, // TODO: 'static :-/
C: ConnectionUpgrade<T::RawConn> + Clone + 'static, // TODO: 'static :-/ C: ConnectionUpgrade<T::RawConn> + Clone + 'static, // TODO: 'static :-/
C::NamesIter: Clone, // TODO: not elegant C::NamesIter: Clone, // TODO: not elegant
H: FnMut(C::Output, Multiaddr) -> F, H: FnMut(C::Output, Multiaddr) -> F,
@ -71,18 +75,27 @@ pub fn swarm<T, C, H, F>(transport: T, upgrade: C, handler: H)
/// Allows control of what the swarm is doing. /// Allows control of what the swarm is doing.
pub struct SwarmController<T, C> pub struct SwarmController<T, C>
where T: MuxedTransport + 'static, // TODO: 'static :-/ where
T: MuxedTransport + 'static, // TODO: 'static :-/
C: ConnectionUpgrade<T::RawConn> + 'static, // TODO: 'static :-/ C: ConnectionUpgrade<T::RawConn> + 'static, // TODO: 'static :-/
{ {
transport: T, transport: T,
upgraded: UpgradedNode<T, C>, upgraded: UpgradedNode<T, C>,
new_listeners: mpsc::UnboundedSender<Box<Stream<Item = Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>, Error = IoError>>>, new_listeners: mpsc::UnboundedSender<
Box<
Stream<
Item = Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>,
Error = IoError,
>,
>,
>,
new_dialers: mpsc::UnboundedSender<Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>>, new_dialers: mpsc::UnboundedSender<Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>>,
new_toprocess: mpsc::UnboundedSender<Box<Future<Item = (), Error = IoError>>>, new_toprocess: mpsc::UnboundedSender<Box<Future<Item = (), Error = IoError>>>,
} }
impl<T, C> SwarmController<T, C> impl<T, C> SwarmController<T, C>
where T: MuxedTransport + Clone + 'static, // TODO: 'static :-/ where
T: MuxedTransport + Clone + 'static, // TODO: 'static :-/
C: ConnectionUpgrade<T::RawConn> + Clone + 'static, // TODO: 'static :-/ C: ConnectionUpgrade<T::RawConn> + Clone + 'static, // TODO: 'static :-/
C::NamesIter: Clone, // TODO: not elegant C::NamesIter: Clone, // TODO: not elegant
{ {
@ -91,20 +104,24 @@ impl<T, C> SwarmController<T, C>
/// calling `swarm`. /// calling `swarm`.
// TODO: consider returning a future so that errors can be processed? // TODO: consider returning a future so that errors can be processed?
pub fn dial_to_handler<Du>(&self, multiaddr: Multiaddr, upgrade: Du) -> Result<(), Multiaddr> pub fn dial_to_handler<Du>(&self, multiaddr: Multiaddr, upgrade: Du) -> Result<(), Multiaddr>
where Du: ConnectionUpgrade<T::RawConn> + Clone + 'static, // TODO: 'static :-/ where
Du: ConnectionUpgrade<T::RawConn> + Clone + 'static, // TODO: 'static :-/
Du::Output: Into<C::Output>, Du::Output: Into<C::Output>,
{ {
match self.transport.clone().with_upgrade(upgrade).dial(multiaddr.clone()) { match self.transport
.clone()
.with_upgrade(upgrade)
.dial(multiaddr.clone())
{
Ok(dial) => { Ok(dial) => {
let dial = Box::new(dial.map(|(d, client_addr)| (d.into(), client_addr))) as Box<Future<Item = _, Error = _>>; let dial = Box::new(dial.map(|(d, client_addr)| (d.into(), client_addr)))
as Box<Future<Item = _, Error = _>>;
// Ignoring errors if the receiver has been closed, because in that situation // Ignoring errors if the receiver has been closed, because in that situation
// nothing is going to be processed anyway. // nothing is going to be processed anyway.
let _ = self.new_dialers.unbounded_send(dial); let _ = self.new_dialers.unbounded_send(dial);
Ok(()) Ok(())
}, }
Err((_, multiaddr)) => { Err((_, multiaddr)) => Err(multiaddr),
Err(multiaddr)
},
} }
} }
@ -114,9 +131,14 @@ impl<T, C> SwarmController<T, C>
/// Contrary to `dial_to_handler`, the output of the upgrade is not given to the handler that /// Contrary to `dial_to_handler`, the output of the upgrade is not given to the handler that
/// was passed at initialization. /// was passed at initialization.
// TODO: consider returning a future so that errors can be processed? // TODO: consider returning a future so that errors can be processed?
pub fn dial_custom_handler<Du, Df, Dfu>(&self, multiaddr: Multiaddr, upgrade: Du, and_then: Df) pub fn dial_custom_handler<Du, Df, Dfu>(
-> Result<(), Multiaddr> &self,
where Du: ConnectionUpgrade<T::RawConn> + 'static, // TODO: 'static :-/ multiaddr: Multiaddr,
upgrade: Du,
and_then: Df,
) -> Result<(), Multiaddr>
where
Du: ConnectionUpgrade<T::RawConn> + 'static, // TODO: 'static :-/
Df: FnOnce(Du::Output, Multiaddr) -> Dfu + 'static, // TODO: 'static :-/ Df: FnOnce(Du::Output, Multiaddr) -> Dfu + 'static, // TODO: 'static :-/
Dfu: IntoFuture<Item = (), Error = IoError> + 'static, // TODO: 'static :-/ Dfu: IntoFuture<Item = (), Error = IoError> + 'static, // TODO: 'static :-/
{ {
@ -127,10 +149,8 @@ impl<T, C> SwarmController<T, C>
// nothing is going to be processed anyway. // nothing is going to be processed anyway.
let _ = self.new_toprocess.unbounded_send(dial); let _ = self.new_toprocess.unbounded_send(dial);
Ok(()) Ok(())
}, }
Err((_, multiaddr)) => { Err((_, multiaddr)) => Err(multiaddr),
Err(multiaddr)
},
} }
} }
@ -143,33 +163,50 @@ impl<T, C> SwarmController<T, C>
// nothing is going to be processed anyway. // nothing is going to be processed anyway.
let _ = self.new_listeners.unbounded_send(listener); let _ = self.new_listeners.unbounded_send(listener);
Ok(new_addr) Ok(new_addr)
}, }
Err((_, multiaddr)) => { Err((_, multiaddr)) => Err(multiaddr),
Err(multiaddr)
},
} }
} }
} }
/// Future that must be driven to completion in order for the swarm to work. /// Future that must be driven to completion in order for the swarm to work.
pub struct SwarmFuture<T, C, H, F> pub struct SwarmFuture<T, C, H, F>
where T: MuxedTransport + 'static, // TODO: 'static :-/ where
T: MuxedTransport + 'static, // TODO: 'static :-/
C: ConnectionUpgrade<T::RawConn> + 'static, // TODO: 'static :-/ C: ConnectionUpgrade<T::RawConn> + 'static, // TODO: 'static :-/
{ {
upgraded: UpgradedNode<T, C>, upgraded: UpgradedNode<T, C>,
handler: H, handler: H,
new_listeners: mpsc::UnboundedReceiver<Box<Stream<Item = Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>, Error = IoError>>>, new_listeners: mpsc::UnboundedReceiver<
next_incoming: Box<Future<Item = Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>, Error = IoError>>, Box<
listeners: Vec<Box<Stream<Item = Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>, Error = IoError>>>, Stream<
Item = Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>,
Error = IoError,
>,
>,
>,
next_incoming: Box<
Future<Item = Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>, Error = IoError>,
>,
listeners: Vec<
Box<
Stream<
Item = Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>,
Error = IoError,
>,
>,
>,
listeners_upgrade: Vec<Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>>, listeners_upgrade: Vec<Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>>,
dialers: Vec<Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>>, dialers: Vec<Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>>,
new_dialers: mpsc::UnboundedReceiver<Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>>, new_dialers:
mpsc::UnboundedReceiver<Box<Future<Item = (C::Output, Multiaddr), Error = IoError>>>,
to_process: Vec<future::Either<F, Box<Future<Item = (), Error = IoError>>>>, to_process: Vec<future::Either<F, Box<Future<Item = (), Error = IoError>>>>,
new_toprocess: mpsc::UnboundedReceiver<Box<Future<Item = (), Error = IoError>>>, new_toprocess: mpsc::UnboundedReceiver<Box<Future<Item = (), Error = IoError>>>,
} }
impl<T, C, H, If, F> Future for SwarmFuture<T, C, H, F> impl<T, C, H, If, F> Future for SwarmFuture<T, C, H, F>
where T: MuxedTransport + Clone + 'static, // TODO: 'static :-/, where
T: MuxedTransport + Clone + 'static, // TODO: 'static :-/,
C: ConnectionUpgrade<T::RawConn> + Clone + 'static, // TODO: 'static :-/ C: ConnectionUpgrade<T::RawConn> + Clone + 'static, // TODO: 'static :-/
C::NamesIter: Clone, // TODO: not elegant C::NamesIter: Clone, // TODO: not elegant
H: FnMut(C::Output, Multiaddr) -> If, H: FnMut(C::Output, Multiaddr) -> If,
@ -186,91 +223,94 @@ impl<T, C, H, If, F> Future for SwarmFuture<T, C, H, F>
Ok(Async::Ready(connec)) => { Ok(Async::Ready(connec)) => {
self.next_incoming = self.upgraded.clone().next_incoming(); self.next_incoming = self.upgraded.clone().next_incoming();
self.listeners_upgrade.push(connec); self.listeners_upgrade.push(connec);
}, }
Ok(Async::NotReady) => {}, Ok(Async::NotReady) => {}
// TODO: may not be the best idea because we're killing the whole server // TODO: may not be the best idea because we're killing the whole server
Err(_err) => { Err(_err) => {
self.next_incoming = self.upgraded.clone().next_incoming(); self.next_incoming = self.upgraded.clone().next_incoming();
}, }
}; };
match self.new_listeners.poll() { match self.new_listeners.poll() {
Ok(Async::Ready(Some(new_listener))) => { Ok(Async::Ready(Some(new_listener))) => {
self.listeners.push(new_listener); self.listeners.push(new_listener);
}, }
Ok(Async::Ready(None)) | Err(_) => { Ok(Async::Ready(None)) | Err(_) => {
// New listener sender has been closed. // New listener sender has been closed.
}, }
Ok(Async::NotReady) => {}, Ok(Async::NotReady) => {}
}; };
match self.new_dialers.poll() { match self.new_dialers.poll() {
Ok(Async::Ready(Some(new_dialer))) => { Ok(Async::Ready(Some(new_dialer))) => {
self.dialers.push(new_dialer); self.dialers.push(new_dialer);
}, }
Ok(Async::Ready(None)) | Err(_) => { Ok(Async::Ready(None)) | Err(_) => {
// New dialers sender has been closed. // New dialers sender has been closed.
}, }
Ok(Async::NotReady) => {}, Ok(Async::NotReady) => {}
}; };
match self.new_toprocess.poll() { match self.new_toprocess.poll() {
Ok(Async::Ready(Some(new_toprocess))) => { Ok(Async::Ready(Some(new_toprocess))) => {
self.to_process.push(future::Either::B(new_toprocess)); self.to_process.push(future::Either::B(new_toprocess));
}, }
Ok(Async::Ready(None)) | Err(_) => { Ok(Async::Ready(None)) | Err(_) => {
// New to-process sender has been closed. // New to-process sender has been closed.
}, }
Ok(Async::NotReady) => {}, Ok(Async::NotReady) => {}
}; };
for n in (0 .. self.listeners.len()).rev() { for n in (0..self.listeners.len()).rev() {
let mut listener = self.listeners.swap_remove(n); let mut listener = self.listeners.swap_remove(n);
match listener.poll() { match listener.poll() {
Ok(Async::Ready(Some(upgrade))) => { Ok(Async::Ready(Some(upgrade))) => {
self.listeners.push(listener); self.listeners.push(listener);
self.listeners_upgrade.push(upgrade); self.listeners_upgrade.push(upgrade);
}, }
Ok(Async::NotReady) => { Ok(Async::NotReady) => {
self.listeners.push(listener); self.listeners.push(listener);
}, }
Ok(Async::Ready(None)) => {}, Ok(Async::Ready(None)) => {}
Err(_err) => {}, // Ignoring errors Err(_err) => {} // Ignoring errors
}; };
} }
for n in (0 .. self.listeners_upgrade.len()).rev() { for n in (0..self.listeners_upgrade.len()).rev() {
let mut upgrade = self.listeners_upgrade.swap_remove(n); let mut upgrade = self.listeners_upgrade.swap_remove(n);
match upgrade.poll() { match upgrade.poll() {
Ok(Async::Ready((output, client_addr))) => { Ok(Async::Ready((output, client_addr))) => {
self.to_process.push(future::Either::A(handler(output, client_addr).into_future())); self.to_process.push(future::Either::A(
}, handler(output, client_addr).into_future(),
));
}
Ok(Async::NotReady) => { Ok(Async::NotReady) => {
self.listeners_upgrade.push(upgrade); self.listeners_upgrade.push(upgrade);
}, }
Err(_err) => {}, // Ignoring errors Err(_err) => {} // Ignoring errors
} }
} }
for n in (0 .. self.dialers.len()).rev() { for n in (0..self.dialers.len()).rev() {
let mut dialer = self.dialers.swap_remove(n); let mut dialer = self.dialers.swap_remove(n);
match dialer.poll() { match dialer.poll() {
Ok(Async::Ready((output, addr))) => { Ok(Async::Ready((output, addr))) => {
self.to_process.push(future::Either::A(handler(output, addr).into_future())); self.to_process
}, .push(future::Either::A(handler(output, addr).into_future()));
}
Ok(Async::NotReady) => { Ok(Async::NotReady) => {
self.dialers.push(dialer); self.dialers.push(dialer);
}, }
Err(_err) => {}, // Ignoring errors Err(_err) => {} // Ignoring errors
} }
} }
for n in (0 .. self.to_process.len()).rev() { for n in (0..self.to_process.len()).rev() {
let mut to_process = self.to_process.swap_remove(n); let mut to_process = self.to_process.swap_remove(n);
match to_process.poll() { match to_process.poll() {
Ok(Async::Ready(())) => {}, Ok(Async::Ready(())) => {}
Ok(Async::NotReady) => self.to_process.push(to_process), Ok(Async::NotReady) => self.to_process.push(to_process),
Err(_err) => {}, // Ignoring errors Err(_err) => {} // Ignoring errors
} }
} }

View File

@ -31,7 +31,7 @@
use bytes::Bytes; use bytes::Bytes;
use connection_reuse::ConnectionReuse; use connection_reuse::ConnectionReuse;
use futures::{Async, Poll, stream, Stream}; use futures::{stream, Async, Poll, Stream};
use futures::future::{self, FromErr, Future, FutureResult, IntoFuture}; use futures::future::{self, FromErr, Future, FutureResult, IntoFuture};
use multiaddr::Multiaddr; use multiaddr::Multiaddr;
use multistream_select; use multistream_select;
@ -138,7 +138,8 @@ pub trait Transport {
/// connection. /// connection.
#[inline] #[inline]
fn with_dummy_muxing(self) -> DummyMuxing<Self> fn with_dummy_muxing(self) -> DummyMuxing<Self>
where Self: Sized where
Self: Sized,
{ {
DummyMuxing { inner: self } DummyMuxing { inner: self }
} }
@ -157,13 +158,16 @@ pub trait MuxedTransport: Transport {
/// > **Note**: Doesn't produce incoming substreams coming from addresses we are listening on. /// > **Note**: Doesn't produce incoming substreams coming from addresses we are listening on.
/// > This only concerns nodes that we dialed with `dial()`. /// > This only concerns nodes that we dialed with `dial()`.
fn next_incoming(self) -> Self::Incoming fn next_incoming(self) -> Self::Incoming
where Self: Sized; where
Self: Sized;
/// Returns a stream of incoming connections. /// Returns a stream of incoming connections.
#[inline] #[inline]
fn incoming(self) -> stream::AndThen<stream::Repeat<Self, IoError>, fn(Self) -> Self::Incoming, fn incoming(
Self::Incoming> self,
where Self: Sized + Clone ) -> stream::AndThen<stream::Repeat<Self, IoError>, fn(Self) -> Self::Incoming, Self::Incoming>
where
Self: Sized + Clone,
{ {
stream::repeat(self).and_then(|me| me.next_incoming()) stream::repeat(self).and_then(|me| me.next_incoming())
} }
@ -218,7 +222,8 @@ where
type RawConn = EitherSocket<A::RawConn, B::RawConn>; type RawConn = EitherSocket<A::RawConn, B::RawConn>;
type Listener = EitherListenStream<A::Listener, B::Listener>; type Listener = EitherListenStream<A::Listener, B::Listener>;
type ListenerUpgrade = EitherListenUpgrade<A::ListenerUpgrade, B::ListenerUpgrade>; type ListenerUpgrade = EitherListenUpgrade<A::ListenerUpgrade, B::ListenerUpgrade>;
type Dial = EitherListenUpgrade<<A::Dial as IntoFuture>::Future, <B::Dial as IntoFuture>::Future>; type Dial =
EitherListenUpgrade<<A::Dial as IntoFuture>::Future, <B::Dial as IntoFuture>::Future>;
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), (Self, Multiaddr)> { fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), (Self, Multiaddr)> {
let (first, addr) = match self.0.listen_on(addr) { let (first, addr) = match self.0.listen_on(addr) {
@ -300,7 +305,8 @@ where
B::RawConn: 'static, // TODO: meh :-/ B::RawConn: 'static, // TODO: meh :-/
{ {
type Incoming = Box<Future<Item = Self::IncomingUpgrade, Error = IoError>>; type Incoming = Box<Future<Item = Self::IncomingUpgrade, Error = IoError>>;
type IncomingUpgrade = Box<Future<Item = (EitherSocket<A::RawConn, B::RawConn>, Multiaddr), Error = IoError>>; type IncomingUpgrade =
Box<Future<Item = (EitherSocket<A::RawConn, B::RawConn>, Multiaddr), Error = IoError>>;
#[inline] #[inline]
fn next_incoming(self) -> Self::Incoming { fn next_incoming(self) -> Self::Incoming {
@ -312,9 +318,7 @@ where
let fut = out.map(move |(v, addr)| (EitherSocket::Second(v), addr)); let fut = out.map(move |(v, addr)| (EitherSocket::Second(v), addr));
Box::new(fut) as Box<Future<Item = _, Error = _>> Box::new(fut) as Box<Future<Item = _, Error = _>>
}); });
let future = first.select(second) let future = first.select(second).map(|(i, _)| i).map_err(|(e, _)| e);
.map(|(i, _)| i)
.map_err(|(e, _)| e);
Box::new(future) as Box<_> Box::new(future) as Box<_>
} }
} }
@ -594,8 +598,13 @@ pub trait ConnectionUpgrade<C: AsyncRead + AsyncWrite> {
/// ///
/// Because performing the upgrade may not be instantaneous (eg. it may require a handshake), /// Because performing the upgrade may not be instantaneous (eg. it may require a handshake),
/// this function returns a future instead of the direct output. /// this function returns a future instead of the direct output.
fn upgrade(self, socket: C, id: Self::UpgradeIdentifier, ty: Endpoint, fn upgrade(
remote_addr: &Multiaddr) -> Self::Future; self,
socket: C,
id: Self::UpgradeIdentifier,
ty: Endpoint,
remote_addr: &Multiaddr,
) -> Self::Future;
} }
/// Type of connection for the upgrade. /// Type of connection for the upgrade.
@ -612,7 +621,8 @@ pub enum Endpoint {
pub struct DeniedConnectionUpgrade; pub struct DeniedConnectionUpgrade;
impl<C> ConnectionUpgrade<C> for DeniedConnectionUpgrade impl<C> ConnectionUpgrade<C> for DeniedConnectionUpgrade
where C: AsyncRead + AsyncWrite where
C: AsyncRead + AsyncWrite,
{ {
type NamesIter = iter::Empty<(Bytes, ())>; type NamesIter = iter::Empty<(Bytes, ())>;
type UpgradeIdentifier = (); // TODO: could use `!` type UpgradeIdentifier = (); // TODO: could use `!`
@ -635,7 +645,8 @@ pub trait UpgradeExt {
/// Builds a struct that will choose an upgrade between `self` and `other`, depending on what /// Builds a struct that will choose an upgrade between `self` and `other`, depending on what
/// the remote supports. /// the remote supports.
fn or_upgrade<T>(self, other: T) -> OrUpgrade<Self, T> fn or_upgrade<T>(self, other: T) -> OrUpgrade<Self, T>
where Self: Sized; where
Self: Sized;
} }
impl<T> UpgradeExt for T { impl<T> UpgradeExt for T {
@ -670,9 +681,13 @@ where
type Future = EitherConnUpgrFuture<A::Future, B::Future>; type Future = EitherConnUpgrFuture<A::Future, B::Future>;
#[inline] #[inline]
fn upgrade(self, socket: C, id: Self::UpgradeIdentifier, ty: Endpoint, fn upgrade(
remote_addr: &Multiaddr) -> Self::Future self,
{ socket: C,
id: Self::UpgradeIdentifier,
ty: Endpoint,
remote_addr: &Multiaddr,
) -> Self::Future {
match id { match id {
EitherUpgradeIdentifier::First(id) => { EitherUpgradeIdentifier::First(id) => {
EitherConnUpgrFuture::First(self.0.upgrade(socket, id, ty, remote_addr)) EitherConnUpgrFuture::First(self.0.upgrade(socket, id, ty, remote_addr))
@ -802,20 +817,23 @@ pub struct DummyMuxing<T> {
} }
impl<T> MuxedTransport for DummyMuxing<T> impl<T> MuxedTransport for DummyMuxing<T>
where T: Transport where
T: Transport,
{ {
type Incoming = future::Empty<Self::IncomingUpgrade, IoError>; type Incoming = future::Empty<Self::IncomingUpgrade, IoError>;
type IncomingUpgrade = future::Empty<(T::RawConn, Multiaddr), IoError>; type IncomingUpgrade = future::Empty<(T::RawConn, Multiaddr), IoError>;
fn next_incoming(self) -> Self::Incoming fn next_incoming(self) -> Self::Incoming
where Self: Sized where
Self: Sized,
{ {
future::empty() future::empty()
} }
} }
impl<T> Transport for DummyMuxing<T> impl<T> Transport for DummyMuxing<T>
where T: Transport where
T: Transport,
{ {
type RawConn = T::RawConn; type RawConn = T::RawConn;
type Listener = T::Listener; type Listener = T::Listener;
@ -825,21 +843,21 @@ impl<T> Transport for DummyMuxing<T>
#[inline] #[inline]
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), (Self, Multiaddr)> fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), (Self, Multiaddr)>
where where
Self: Sized Self: Sized,
{ {
self.inner.listen_on(addr).map_err(|(inner, addr)| { self.inner
(DummyMuxing { inner }, addr) .listen_on(addr)
}) .map_err(|(inner, addr)| (DummyMuxing { inner }, addr))
} }
#[inline] #[inline]
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, (Self, Multiaddr)> fn dial(self, addr: Multiaddr) -> Result<Self::Dial, (Self, Multiaddr)>
where where
Self: Sized Self: Sized,
{ {
self.inner.dial(addr).map_err(|(inner, addr)| { self.inner
(DummyMuxing { inner }, addr) .dial(addr)
}) .map_err(|(inner, addr)| (DummyMuxing { inner }, addr))
} }
#[inline] #[inline]
@ -867,7 +885,8 @@ where
/// `StreamMuxer` trait, the returned object will implement `Transport` and `MuxedTransport`. /// `StreamMuxer` trait, the returned object will implement `Transport` and `MuxedTransport`.
#[inline] #[inline]
pub fn into_connection_reuse(self) -> ConnectionReuse<T, C> pub fn into_connection_reuse(self) -> ConnectionReuse<T, C>
where C::Output: StreamMuxer where
C::Output: StreamMuxer,
{ {
From::from(self) From::from(self)
} }
@ -887,7 +906,8 @@ where
pub fn dial( pub fn dial(
self, self,
addr: Multiaddr, addr: Multiaddr,
) -> Result<Box<Future<Item = (C::Output, Multiaddr), Error = IoError> + 'a>, (Self, Multiaddr)> { ) -> Result<Box<Future<Item = (C::Output, Multiaddr), Error = IoError> + 'a>, (Self, Multiaddr)>
{
let upgrade = self.upgrade; let upgrade = self.upgrade;
let dialed_fut = match self.transports.dial(addr.clone()) { let dialed_fut = match self.transports.dial(addr.clone()) {
@ -924,19 +944,28 @@ where
/// ///
/// This function returns the next incoming substream. You are strongly encouraged to call it /// This function returns the next incoming substream. You are strongly encouraged to call it
/// if you have a muxed transport. /// if you have a muxed transport.
pub fn next_incoming(self) -> Box<Future<Item = Box<Future<Item = (C::Output, Multiaddr), Error = IoError> + 'a>, Error = IoError> + 'a> pub fn next_incoming(
where T: MuxedTransport, self,
) -> Box<
Future<
Item = Box<Future<Item = (C::Output, Multiaddr), Error = IoError> + 'a>,
Error = IoError,
>
+ 'a,
>
where
T: MuxedTransport,
C::NamesIter: Clone, // TODO: not elegant C::NamesIter: Clone, // TODO: not elegant
C: Clone, C: Clone,
{ {
let upgrade = self.upgrade; let upgrade = self.upgrade;
let future = self.transports.next_incoming() let future = self.transports.next_incoming().map(|future| {
.map(|future| {
// Try to negotiate the protocol. // Try to negotiate the protocol.
let future = future let future = future
.and_then(move |(connection, addr)| { .and_then(move |(connection, addr)| {
let iter = upgrade.protocol_names() let iter = upgrade
.protocol_names()
.map::<_, fn(_) -> _>(|(name, id)| (name, <Bytes as PartialEq>::eq, id)); .map::<_, fn(_) -> _>(|(name, id)| (name, <Bytes as PartialEq>::eq, id));
let negotiated = multistream_select::listener_select_proto(connection, iter) let negotiated = multistream_select::listener_select_proto(connection, iter)
.map_err(|err| IoError::new(IoErrorKind::Other, err)); .map_err(|err| IoError::new(IoErrorKind::Other, err));
@ -963,7 +992,16 @@ where
self, self,
addr: Multiaddr, addr: Multiaddr,
) -> Result< ) -> Result<
(Box<Stream<Item = Box<Future<Item = (C::Output, Multiaddr), Error = IoError> + 'a>, Error = IoError> + 'a>, Multiaddr), (
Box<
Stream<
Item = Box<Future<Item = (C::Output, Multiaddr), Error = IoError> + 'a>,
Error = IoError,
>
+ 'a,
>,
Multiaddr,
),
(Self, Multiaddr), (Self, Multiaddr),
> >
where where
@ -988,8 +1026,7 @@ where
// Note that failing to negotiate a protocol will never produce a future with an error. // Note that failing to negotiate a protocol will never produce a future with an error.
// Instead the `stream` will produce `Ok(Err(...))`. // Instead the `stream` will produce `Ok(Err(...))`.
// `stream` can only produce an `Err` if `listening_stream` produces an `Err`. // `stream` can only produce an `Err` if `listening_stream` produces an `Err`.
let stream = listening_stream let stream = listening_stream.map(move |connection| {
.map(move |connection| {
let upgrade = upgrade.clone(); let upgrade = upgrade.clone();
let connection = connection let connection = connection
// Try to negotiate the protocol // Try to negotiate the protocol
@ -999,8 +1036,12 @@ where
multistream_select::listener_select_proto(connection, iter) multistream_select::listener_select_proto(connection, iter)
.map_err(|err| IoError::new(IoErrorKind::Other, err)) .map_err(|err| IoError::new(IoErrorKind::Other, err))
.and_then(move |(upgrade_id, connection)| { .and_then(move |(upgrade_id, connection)| {
let fut = upgrade.upgrade(connection, upgrade_id, Endpoint::Listener, let fut = upgrade.upgrade(
&remote_addr); connection,
upgrade_id,
Endpoint::Listener,
&remote_addr,
);
fut.map(move |c| (c, remote_addr)) fut.map(move |c| (c, remote_addr))
}) })
.into_future() .into_future()

View File

@ -28,8 +28,8 @@ extern crate tokio_io;
use bytes::BytesMut; use bytes::BytesMut;
use futures::future::Future; use futures::future::Future;
use futures::{Stream, Sink}; use futures::{Sink, Stream};
use libp2p_swarm::{Multiaddr, Transport, StreamMuxer, MuxedTransport}; use libp2p_swarm::{Multiaddr, MuxedTransport, StreamMuxer, Transport};
use libp2p_tcp_transport::TcpConfig; use libp2p_tcp_transport::TcpConfig;
use tokio_core::reactor::Core; use tokio_core::reactor::Core;
use tokio_io::codec::length_delimited::Framed; use tokio_io::codec::length_delimited::Framed;
@ -46,7 +46,10 @@ impl<T> From<T> for OnlyOnce<T> {
} }
impl<T: Clone> Clone for OnlyOnce<T> { impl<T: Clone> Clone for OnlyOnce<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
OnlyOnce(self.0.clone(), atomic::AtomicBool::new(self.1.load(atomic::Ordering::SeqCst))) OnlyOnce(
self.0.clone(),
atomic::AtomicBool::new(self.1.load(atomic::Ordering::SeqCst)),
)
} }
} }
impl<T: Transport> Transport for OnlyOnce<T> { impl<T: Transport> Transport for OnlyOnce<T> {
@ -80,7 +83,8 @@ fn client_to_server_outbound() {
.into_connection_reuse(); .into_connection_reuse();
let (listener, addr) = transport let (listener, addr) = transport
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap_or_else(|_| panic!()); .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
.unwrap_or_else(|_| panic!());
tx.send(addr).unwrap(); tx.send(addr).unwrap();
let future = listener let future = listener
@ -90,7 +94,8 @@ fn client_to_server_outbound() {
.map(|client| client.0) .map(|client| client.0)
.map(|client| Framed::<_, BytesMut>::new(client)) .map(|client| Framed::<_, BytesMut>::new(client))
.and_then(|client| { .and_then(|client| {
client.into_future() client
.into_future()
.map_err(|(err, _)| err) .map_err(|(err, _)| err)
.map(|(msg, _)| msg) .map(|(msg, _)| msg)
}) })
@ -104,10 +109,11 @@ fn client_to_server_outbound() {
}); });
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
let transport = TcpConfig::new(core.handle()) let transport = TcpConfig::new(core.handle()).with_upgrade(multiplex::MultiplexConfig);
.with_upgrade(multiplex::MultiplexConfig);
let future = transport.dial(rx.recv().unwrap()).unwrap() let future = transport
.dial(rx.recv().unwrap())
.unwrap()
.and_then(|client| client.0.outbound()) .and_then(|client| client.0.outbound())
.map(|server| Framed::<_, BytesMut>::new(server)) .map(|server| Framed::<_, BytesMut>::new(server))
.and_then(|server| server.send("hello world".into())) .and_then(|server| server.send("hello world".into()))
@ -131,7 +137,8 @@ fn connection_reused_for_dialing() {
.into_connection_reuse(); .into_connection_reuse();
let (listener, addr) = transport let (listener, addr) = transport
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap_or_else(|_| panic!()); .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
.unwrap_or_else(|_| panic!());
tx.send(addr).unwrap(); tx.send(addr).unwrap();
let future = listener let future = listener
@ -140,7 +147,8 @@ fn connection_reused_for_dialing() {
.and_then(|(client, rest)| client.unwrap().map(move |c| (c.0, rest))) .and_then(|(client, rest)| client.unwrap().map(move |c| (c.0, rest)))
.map(|(client, rest)| (Framed::<_, BytesMut>::new(client), rest)) .map(|(client, rest)| (Framed::<_, BytesMut>::new(client), rest))
.and_then(|(client, rest)| { .and_then(|(client, rest)| {
client.into_future() client
.into_future()
.map(|v| (v, rest)) .map(|v| (v, rest))
.map_err(|(err, _)| err) .map_err(|(err, _)| err)
}) })
@ -155,10 +163,7 @@ fn connection_reused_for_dialing() {
.and_then(|(client, _)| client.unwrap()) .and_then(|(client, _)| client.unwrap())
.map(|client| client.0) .map(|client| client.0)
.map(|client| Framed::<_, BytesMut>::new(client)) .map(|client| Framed::<_, BytesMut>::new(client))
.and_then(|client| { .and_then(|client| client.into_future().map_err(|(err, _)| err))
client.into_future()
.map_err(|(err, _)| err)
})
.and_then(|(msg, _)| { .and_then(|(msg, _)| {
let msg = msg.unwrap(); let msg = msg.unwrap();
assert_eq!(msg, "second message"); assert_eq!(msg, "second message");
@ -175,19 +180,21 @@ fn connection_reused_for_dialing() {
let listen_addr = rx.recv().unwrap(); let listen_addr = rx.recv().unwrap();
let future = transport.clone().dial(listen_addr.clone()).unwrap_or_else(|_| panic!()) let future = transport
.clone()
.dial(listen_addr.clone())
.unwrap_or_else(|_| panic!())
.map(|server| Framed::<_, BytesMut>::new(server.0)) .map(|server| Framed::<_, BytesMut>::new(server.0))
.and_then(|server| { .and_then(|server| server.send("hello world".into()))
server.send("hello world".into())
})
.and_then(|first_connec| { .and_then(|first_connec| {
transport.clone().dial(listen_addr.clone()).unwrap_or_else(|_| panic!()) transport
.clone()
.dial(listen_addr.clone())
.unwrap_or_else(|_| panic!())
.map(|server| Framed::<_, BytesMut>::new(server.0)) .map(|server| Framed::<_, BytesMut>::new(server.0))
.map(|server| (first_connec, server)) .map(|server| (first_connec, server))
}) })
.and_then(|(_first, second)| { .and_then(|(_first, second)| second.send("second message".into()))
second.send("second message".into())
})
.map(|_| ()); .map(|_| ());
core.run(future).unwrap(); core.run(future).unwrap();
@ -204,11 +211,13 @@ fn use_opened_listen_to_dial() {
let bg_thread = thread::spawn(move || { let bg_thread = thread::spawn(move || {
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
let transport = OnlyOnce::from(TcpConfig::new(core.handle())) let transport =
.with_upgrade(multiplex::MultiplexConfig); OnlyOnce::from(TcpConfig::new(core.handle())).with_upgrade(multiplex::MultiplexConfig);
let (listener, addr) = transport.clone() let (listener, addr) = transport
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap_or_else(|_| panic!()); .clone()
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
.unwrap_or_else(|_| panic!());
tx.send(addr).unwrap(); tx.send(addr).unwrap();
let future = listener let future = listener
@ -220,11 +229,10 @@ fn use_opened_listen_to_dial() {
let c2 = c.clone(); let c2 = c.clone();
c.clone().inbound().map(move |i| (c2, i)) c.clone().inbound().map(move |i| (c2, i))
}) })
.map(|(muxer, client)| { .map(|(muxer, client)| (muxer, Framed::<_, BytesMut>::new(client)))
(muxer, Framed::<_, BytesMut>::new(client))
})
.and_then(|(muxer, client)| { .and_then(|(muxer, client)| {
client.into_future() client
.into_future()
.map(move |msg| (muxer, msg)) .map(move |msg| (muxer, msg))
.map_err(|(err, _)| err) .map_err(|(err, _)| err)
}) })
@ -233,13 +241,8 @@ fn use_opened_listen_to_dial() {
assert_eq!(msg, "hello world"); assert_eq!(msg, "hello world");
muxer.outbound() muxer.outbound()
}) })
.map(|client| { .map(|client| Framed::<_, BytesMut>::new(client))
Framed::<_, BytesMut>::new(client) .and_then(|client| client.into_future().map_err(|(err, _)| err))
})
.and_then(|client| {
client.into_future()
.map_err(|(err, _)| err)
})
.and_then(|(msg, _)| { .and_then(|(msg, _)| {
let msg = msg.unwrap(); let msg = msg.unwrap();
assert_eq!(msg, "second message"); assert_eq!(msg, "second message");
@ -256,20 +259,21 @@ fn use_opened_listen_to_dial() {
let listen_addr = rx.recv().unwrap(); let listen_addr = rx.recv().unwrap();
let future = transport.clone().dial(listen_addr.clone()).unwrap_or_else(|_| panic!()) let future = transport
.clone()
.dial(listen_addr.clone())
.unwrap_or_else(|_| panic!())
.map(|server| Framed::<_, BytesMut>::new(server.0)) .map(|server| Framed::<_, BytesMut>::new(server.0))
.and_then(|server| { .and_then(|server| server.send("hello world".into()))
server.send("hello world".into())
})
.and_then(|first_connec| { .and_then(|first_connec| {
transport.clone().next_incoming() transport
.clone()
.next_incoming()
.and_then(|server| server) .and_then(|server| server)
.map(|server| Framed::<_, BytesMut>::new(server.0)) .map(|server| Framed::<_, BytesMut>::new(server.0))
.map(|server| (first_connec, server)) .map(|server| (first_connec, server))
}) })
.and_then(|(_first, second)| { .and_then(|(_first, second)| second.send("second message".into()))
second.send("second message".into())
})
.map(|_| ()); .map(|_| ());
core.run(future).unwrap(); core.run(future).unwrap();

View File

@ -49,20 +49,20 @@
//! The `TcpConfig` structs implements the `Transport` trait of the `swarm` library. See the //! The `TcpConfig` structs implements the `Transport` trait of the `swarm` library. See the
//! documentation of `swarm` and of libp2p in general to learn how to use the `Transport` trait. //! documentation of `swarm` and of libp2p in general to learn how to use the `Transport` trait.
extern crate futures;
extern crate libp2p_swarm as swarm; extern crate libp2p_swarm as swarm;
extern crate multiaddr;
extern crate tokio_core; extern crate tokio_core;
extern crate tokio_io; extern crate tokio_io;
extern crate multiaddr;
extern crate futures;
use std::io::Error as IoError; use std::io::Error as IoError;
use std::iter; use std::iter;
use std::net::SocketAddr; use std::net::SocketAddr;
use tokio_core::reactor::Handle; use tokio_core::reactor::Handle;
use tokio_core::net::{TcpStream, TcpListener}; use tokio_core::net::{TcpListener, TcpStream};
use futures::future::{self, Future, FutureResult, IntoFuture}; use futures::future::{self, Future, FutureResult, IntoFuture};
use futures::stream::Stream; use futures::stream::Stream;
use multiaddr::{Multiaddr, AddrComponent, ToMultiaddr}; use multiaddr::{AddrComponent, Multiaddr, ToMultiaddr};
use swarm::Transport; use swarm::Transport;
/// Represents the configuration for a TCP/IP transport capability for libp2p. /// Represents the configuration for a TCP/IP transport capability for libp2p.
@ -99,15 +99,18 @@ impl Transport for TcpConfig {
// just return the original multiaddr. // just return the original multiaddr.
let new_addr = match listener { let new_addr = match listener {
Ok(ref l) => if let Ok(new_s_addr) = l.local_addr() { Ok(ref l) => if let Ok(new_s_addr) = l.local_addr() {
new_s_addr.to_multiaddr().expect("multiaddr generated from socket addr is \ new_s_addr.to_multiaddr().expect(
always valid") "multiaddr generated from socket addr is \
always valid",
)
} else { } else {
addr addr
} },
Err(_) => addr, Err(_) => addr,
}; };
let future = future::result(listener).map(|listener| { let future = future::result(listener)
.map(|listener| {
// Pull out a stream of sockets for incoming connections // Pull out a stream of sockets for incoming connections
listener.incoming().map(|(sock, addr)| { listener.incoming().map(|(sock, addr)| {
let addr = addr.to_multiaddr() let addr = addr.to_multiaddr()
@ -127,8 +130,7 @@ impl Transport for TcpConfig {
/// or gives back the multiaddress. /// or gives back the multiaddress.
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, (Self, Multiaddr)> { fn dial(self, addr: Multiaddr) -> Result<Self::Dial, (Self, Multiaddr)> {
if let Ok(socket_addr) = multiaddr_to_socketaddr(&addr) { if let Ok(socket_addr) = multiaddr_to_socketaddr(&addr) {
let fut = TcpStream::connect(&socket_addr, &self.event_loop) let fut = TcpStream::connect(&socket_addr, &self.event_loop).map(|t| (t, addr));
.map(|t| (t, addr));
Ok(Box::new(fut) as Box<_>) Ok(Box::new(fut) as Box<_>)
} else { } else {
Err((self, addr)) Err((self, addr))
@ -145,15 +147,15 @@ impl Transport for TcpConfig {
// Check that `server` is a valid TCP/IP address. // Check that `server` is a valid TCP/IP address.
match (&server_protocols[0], &server_protocols[1]) { match (&server_protocols[0], &server_protocols[1]) {
(&AddrComponent::IP4(_), &AddrComponent::TCP(_)) | (&AddrComponent::IP4(_), &AddrComponent::TCP(_))
(&AddrComponent::IP6(_), &AddrComponent::TCP(_)) => {} | (&AddrComponent::IP6(_), &AddrComponent::TCP(_)) => {}
_ => return None, _ => return None,
} }
// Check that `observed` is a valid TCP/IP address. // Check that `observed` is a valid TCP/IP address.
match (&observed_protocols[0], &observed_protocols[1]) { match (&observed_protocols[0], &observed_protocols[1]) {
(&AddrComponent::IP4(_), &AddrComponent::TCP(_)) | (&AddrComponent::IP4(_), &AddrComponent::TCP(_))
(&AddrComponent::IP6(_), &AddrComponent::TCP(_)) => {} | (&AddrComponent::IP6(_), &AddrComponent::TCP(_)) => {}
_ => return None, _ => return None,
} }
@ -186,7 +188,7 @@ fn multiaddr_to_socketaddr(addr: &Multiaddr) -> Result<SocketAddr, ()> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{TcpConfig, multiaddr_to_socketaddr}; use super::{multiaddr_to_socketaddr, TcpConfig};
use std; use std;
use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use tokio_core::reactor::Core; use tokio_core::reactor::Core;
@ -200,7 +202,10 @@ mod tests {
fn multiaddr_to_tcp_conversion() { fn multiaddr_to_tcp_conversion() {
use std::net::Ipv6Addr; use std::net::Ipv6Addr;
assert!(multiaddr_to_socketaddr(&"/ip4/127.0.0.1/udp/1234".parse::<Multiaddr>().unwrap()).is_err()); assert!(
multiaddr_to_socketaddr(&"/ip4/127.0.0.1/udp/1234".parse::<Multiaddr>().unwrap())
.is_err()
);
assert_eq!( assert_eq!(
multiaddr_to_socketaddr(&"/ip4/127.0.0.1/tcp/12345".parse::<Multiaddr>().unwrap()), multiaddr_to_socketaddr(&"/ip4/127.0.0.1/tcp/12345".parse::<Multiaddr>().unwrap()),
@ -210,7 +215,9 @@ mod tests {
)) ))
); );
assert_eq!( assert_eq!(
multiaddr_to_socketaddr(&"/ip4/255.255.255.255/tcp/8080".parse::<Multiaddr>().unwrap()), multiaddr_to_socketaddr(&"/ip4/255.255.255.255/tcp/8080"
.parse::<Multiaddr>()
.unwrap()),
Ok(SocketAddr::new( Ok(SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(255, 255, 255, 255)), IpAddr::V4(Ipv4Addr::new(255, 255, 255, 255)),
8080, 8080,
@ -225,7 +232,8 @@ mod tests {
); );
assert_eq!( assert_eq!(
multiaddr_to_socketaddr(&"/ip6/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/tcp/8080" multiaddr_to_socketaddr(&"/ip6/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/tcp/8080"
.parse::<Multiaddr>().unwrap()), .parse::<Multiaddr>()
.unwrap()),
Ok(SocketAddr::new( Ok(SocketAddr::new(
IpAddr::V6(Ipv6Addr::new( IpAddr::V6(Ipv6Addr::new(
65535, 65535,
@ -316,7 +324,9 @@ mod tests {
let core = Core::new().unwrap(); let core = Core::new().unwrap();
let tcp = TcpConfig::new(core.handle()); let tcp = TcpConfig::new(core.handle());
let addr = "/ip4/127.0.0.1/tcp/12345/tcp/12345".parse::<Multiaddr>().unwrap(); let addr = "/ip4/127.0.0.1/tcp/12345/tcp/12345"
.parse::<Multiaddr>()
.unwrap();
assert!(tcp.listen_on(addr).is_err()); assert!(tcp.listen_on(addr).is_err());
} }
@ -329,6 +339,9 @@ mod tests {
let observed = "/ip4/80.81.82.83/tcp/25000".parse::<Multiaddr>().unwrap(); let observed = "/ip4/80.81.82.83/tcp/25000".parse::<Multiaddr>().unwrap();
let out = tcp.nat_traversal(&server, &observed); let out = tcp.nat_traversal(&server, &observed);
assert_eq!(out.unwrap(), "/ip4/80.81.82.83/tcp/10000".parse::<Multiaddr>().unwrap()); assert_eq!(
out.unwrap(),
"/ip4/80.81.82.83/tcp/10000".parse::<Multiaddr>().unwrap()
);
} }
} }

View File

@ -219,19 +219,19 @@ impl Transport for BrowserWsConfig {
// Check that `server` is a valid TCP/IP address. // Check that `server` is a valid TCP/IP address.
match (&server_proto0, &server_proto1, &server_proto2) { match (&server_proto0, &server_proto1, &server_proto2) {
(&AddrComponent::IP4(_), &AddrComponent::TCP(_), &AddrComponent::WS) | (&AddrComponent::IP4(_), &AddrComponent::TCP(_), &AddrComponent::WS)
(&AddrComponent::IP6(_), &AddrComponent::TCP(_), &AddrComponent::WS) | | (&AddrComponent::IP6(_), &AddrComponent::TCP(_), &AddrComponent::WS)
(&AddrComponent::IP4(_), &AddrComponent::TCP(_), &AddrComponent::WSS) | | (&AddrComponent::IP4(_), &AddrComponent::TCP(_), &AddrComponent::WSS)
(&AddrComponent::IP6(_), &AddrComponent::TCP(_), &AddrComponent::WSS) => {} | (&AddrComponent::IP6(_), &AddrComponent::TCP(_), &AddrComponent::WSS) => {}
_ => return None, _ => return None,
} }
// Check that `observed` is a valid TCP/IP address. // Check that `observed` is a valid TCP/IP address.
match (&obs_proto0, &obs_proto1, &obs_proto2) { match (&obs_proto0, &obs_proto1, &obs_proto2) {
(&AddrComponent::IP4(_), &AddrComponent::TCP(_), &AddrComponent::WS) | (&AddrComponent::IP4(_), &AddrComponent::TCP(_), &AddrComponent::WS)
(&AddrComponent::IP6(_), &AddrComponent::TCP(_), &AddrComponent::WS) | | (&AddrComponent::IP6(_), &AddrComponent::TCP(_), &AddrComponent::WS)
(&AddrComponent::IP4(_), &AddrComponent::TCP(_), &AddrComponent::WSS) | | (&AddrComponent::IP4(_), &AddrComponent::TCP(_), &AddrComponent::WSS)
(&AddrComponent::IP6(_), &AddrComponent::TCP(_), &AddrComponent::WSS) => {} | (&AddrComponent::IP6(_), &AddrComponent::TCP(_), &AddrComponent::WSS) => {}
_ => return None, _ => return None,
} }

View File

@ -52,14 +52,14 @@ impl<T> WsConfig<T> {
impl<T> Transport for WsConfig<T> impl<T> Transport for WsConfig<T>
where where
T: Transport + 'static, // TODO: this 'static is pretty arbitrary and is necessary because of the websocket library // TODO: this 'static is pretty arbitrary and is necessary because of the websocket library
T::RawConn: Send, // TODO: this Send is pretty arbitrary and is necessary because of the websocket library T: Transport + 'static,
// TODO: this Send is pretty arbitrary and is necessary because of the websocket library
T::RawConn: Send,
{ {
type RawConn = Box<AsyncStream>; type RawConn = Box<AsyncStream>;
type Listener = stream::Map< type Listener =
T::Listener, stream::Map<T::Listener, fn(<T as Transport>::ListenerUpgrade) -> Self::ListenerUpgrade>;
fn(<T as Transport>::ListenerUpgrade) -> Self::ListenerUpgrade,
>;
type ListenerUpgrade = Box<Future<Item = (Self::RawConn, Multiaddr), Error = IoError>>; type ListenerUpgrade = Box<Future<Item = (Self::RawConn, Multiaddr), Error = IoError>>;
type Dial = Box<Future<Item = (Self::RawConn, Multiaddr), Error = IoError>>; type Dial = Box<Future<Item = (Self::RawConn, Multiaddr), Error = IoError>>;
@ -159,11 +159,16 @@ where
} }
}; };
let dial = inner_dial.into_future().and_then(move |(connec, client_addr)| { let dial = inner_dial
.into_future()
.and_then(move |(connec, client_addr)| {
// We pass a dummy address to `ClientBuilder` because it is never used anywhere // We pass a dummy address to `ClientBuilder` because it is never used anywhere
// in the negotiation anyway, and we use `async_connect_on` to pass a stream. // in the negotiation anyway, and we use `async_connect_on` to pass a stream.
ClientBuilder::new(if is_wss { "wss://127.0.0.1" } else { "ws://127.0.0.1" }) ClientBuilder::new(if is_wss {
.expect("hard-coded ws address is always valid") "wss://127.0.0.1"
} else {
"ws://127.0.0.1"
}).expect("hard-coded ws address is always valid")
.async_connect_on(connec) .async_connect_on(connec)
.map_err(|err| IoError::new(IoErrorKind::Other, err)) .map_err(|err| IoError::new(IoErrorKind::Other, err))
.map(|(client, _)| { .map(|(client, _)| {
@ -205,8 +210,12 @@ where
_ => return None, _ => return None,
}; };
self.transport.nat_traversal(&server, &observed) self.transport
.map(move |mut result| { result.append(last_proto); result }) .nat_traversal(&server, &observed)
.map(move |mut result| {
result.append(last_proto);
result
})
} }
} }
@ -275,30 +284,54 @@ mod tests {
{ {
let server = "/ip4/127.0.0.1/tcp/10000/ws".parse::<Multiaddr>().unwrap(); let server = "/ip4/127.0.0.1/tcp/10000/ws".parse::<Multiaddr>().unwrap();
let observed = "/ip4/80.81.82.83/tcp/25000/ws".parse::<Multiaddr>().unwrap(); let observed = "/ip4/80.81.82.83/tcp/25000/ws"
assert_eq!(ws_config.nat_traversal(&server, &observed).unwrap(), .parse::<Multiaddr>()
"/ip4/80.81.82.83/tcp/10000/ws".parse::<Multiaddr>().unwrap()); .unwrap();
assert_eq!(
ws_config.nat_traversal(&server, &observed).unwrap(),
"/ip4/80.81.82.83/tcp/10000/ws"
.parse::<Multiaddr>()
.unwrap()
);
} }
{ {
let server = "/ip4/127.0.0.1/tcp/10000/wss".parse::<Multiaddr>().unwrap(); let server = "/ip4/127.0.0.1/tcp/10000/wss".parse::<Multiaddr>().unwrap();
let observed = "/ip4/80.81.82.83/tcp/25000/wss".parse::<Multiaddr>().unwrap(); let observed = "/ip4/80.81.82.83/tcp/25000/wss"
assert_eq!(ws_config.nat_traversal(&server, &observed).unwrap(), .parse::<Multiaddr>()
"/ip4/80.81.82.83/tcp/10000/wss".parse::<Multiaddr>().unwrap()); .unwrap();
assert_eq!(
ws_config.nat_traversal(&server, &observed).unwrap(),
"/ip4/80.81.82.83/tcp/10000/wss"
.parse::<Multiaddr>()
.unwrap()
);
} }
{ {
let server = "/ip4/127.0.0.1/tcp/10000/ws".parse::<Multiaddr>().unwrap(); let server = "/ip4/127.0.0.1/tcp/10000/ws".parse::<Multiaddr>().unwrap();
let observed = "/ip4/80.81.82.83/tcp/25000/wss".parse::<Multiaddr>().unwrap(); let observed = "/ip4/80.81.82.83/tcp/25000/wss"
assert_eq!(ws_config.nat_traversal(&server, &observed).unwrap(), .parse::<Multiaddr>()
"/ip4/80.81.82.83/tcp/10000/ws".parse::<Multiaddr>().unwrap()); .unwrap();
assert_eq!(
ws_config.nat_traversal(&server, &observed).unwrap(),
"/ip4/80.81.82.83/tcp/10000/ws"
.parse::<Multiaddr>()
.unwrap()
);
} }
{ {
let server = "/ip4/127.0.0.1/tcp/10000/wss".parse::<Multiaddr>().unwrap(); let server = "/ip4/127.0.0.1/tcp/10000/wss".parse::<Multiaddr>().unwrap();
let observed = "/ip4/80.81.82.83/tcp/25000/ws".parse::<Multiaddr>().unwrap(); let observed = "/ip4/80.81.82.83/tcp/25000/ws"
assert_eq!(ws_config.nat_traversal(&server, &observed).unwrap(), .parse::<Multiaddr>()
"/ip4/80.81.82.83/tcp/10000/wss".parse::<Multiaddr>().unwrap()); .unwrap();
assert_eq!(
ws_config.nat_traversal(&server, &observed).unwrap(),
"/ip4/80.81.82.83/tcp/10000/wss"
.parse::<Multiaddr>()
.unwrap()
);
} }
} }
} }

View File

@ -381,7 +381,7 @@ mod tests {
assert_eq!( assert_eq!(
substream substream
.name() .name()
.and_then(|bytes| { String::from_utf8(bytes.to_vec()).ok() }), .and_then(|bytes| String::from_utf8(bytes.to_vec()).ok()),
Some(id.to_string()) Some(id.to_string())
); );
@ -395,7 +395,7 @@ mod tests {
assert_eq!( assert_eq!(
substream substream
.name() .name()
.and_then(|bytes| { String::from_utf8(bytes.to_vec()).ok() }), .and_then(|bytes| String::from_utf8(bytes.to_vec()).ok()),
Some(id.to_string()) Some(id.to_string())
); );
@ -445,7 +445,7 @@ mod tests {
assert_eq!( assert_eq!(
substream substream
.name() .name()
.and_then(|bytes| { String::from_utf8(bytes.to_vec()).ok() }), .and_then(|bytes| String::from_utf8(bytes.to_vec()).ok()),
Some(id.to_string()) Some(id.to_string())
); );

View File

@ -27,10 +27,10 @@ extern crate tokio_core;
extern crate tokio_io; extern crate tokio_io;
use futures::future::Future; use futures::future::Future;
use futures::{Stream, Sink}; use futures::{Sink, Stream};
use std::sync::mpsc; use std::sync::mpsc;
use std::thread; use std::thread;
use swarm::{Transport, StreamMuxer}; use swarm::{StreamMuxer, Transport};
use tcp::TcpConfig; use tcp::TcpConfig;
use tokio_core::reactor::Core; use tokio_core::reactor::Core;
use tokio_io::codec::length_delimited::Framed; use tokio_io::codec::length_delimited::Framed;
@ -43,11 +43,11 @@ fn client_to_server_outbound() {
let bg_thread = thread::spawn(move || { let bg_thread = thread::spawn(move || {
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
let transport = TcpConfig::new(core.handle()) let transport = TcpConfig::new(core.handle()).with_upgrade(multiplex::MultiplexConfig);
.with_upgrade(multiplex::MultiplexConfig);
let (listener, addr) = transport let (listener, addr) = transport
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap(); .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
.unwrap();
tx.send(addr).unwrap(); tx.send(addr).unwrap();
let future = listener let future = listener
@ -57,7 +57,8 @@ fn client_to_server_outbound() {
.and_then(|client| client.outbound()) .and_then(|client| client.outbound())
.map(|client| Framed::<_, bytes::BytesMut>::new(client)) .map(|client| Framed::<_, bytes::BytesMut>::new(client))
.and_then(|client| { .and_then(|client| {
client.into_future() client
.into_future()
.map_err(|(err, _)| err) .map_err(|(err, _)| err)
.map(|(msg, _)| msg) .map(|(msg, _)| msg)
}) })
@ -71,10 +72,11 @@ fn client_to_server_outbound() {
}); });
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
let transport = TcpConfig::new(core.handle()) let transport = TcpConfig::new(core.handle()).with_upgrade(multiplex::MultiplexConfig);
.with_upgrade(multiplex::MultiplexConfig);
let future = transport.dial(rx.recv().unwrap()).unwrap() let future = transport
.dial(rx.recv().unwrap())
.unwrap()
.and_then(|client| client.0.inbound()) .and_then(|client| client.0.inbound())
.map(|server| Framed::<_, bytes::BytesMut>::new(server)) .map(|server| Framed::<_, bytes::BytesMut>::new(server))
.and_then(|server| server.send("hello world".into())) .and_then(|server| server.send("hello world".into()))
@ -92,11 +94,11 @@ fn client_to_server_inbound() {
let bg_thread = thread::spawn(move || { let bg_thread = thread::spawn(move || {
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
let transport = TcpConfig::new(core.handle()) let transport = TcpConfig::new(core.handle()).with_upgrade(multiplex::MultiplexConfig);
.with_upgrade(multiplex::MultiplexConfig);
let (listener, addr) = transport let (listener, addr) = transport
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap(); .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
.unwrap();
tx.send(addr).unwrap(); tx.send(addr).unwrap();
let future = listener let future = listener
@ -106,7 +108,8 @@ fn client_to_server_inbound() {
.and_then(|client| client.inbound()) .and_then(|client| client.inbound())
.map(|client| Framed::<_, bytes::BytesMut>::new(client)) .map(|client| Framed::<_, bytes::BytesMut>::new(client))
.and_then(|client| { .and_then(|client| {
client.into_future() client
.into_future()
.map_err(|(err, _)| err) .map_err(|(err, _)| err)
.map(|(msg, _)| msg) .map(|(msg, _)| msg)
}) })
@ -120,10 +123,11 @@ fn client_to_server_inbound() {
}); });
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
let transport = TcpConfig::new(core.handle()) let transport = TcpConfig::new(core.handle()).with_upgrade(multiplex::MultiplexConfig);
.with_upgrade(multiplex::MultiplexConfig);
let future = transport.dial(rx.recv().unwrap()).unwrap() let future = transport
.dial(rx.recv().unwrap())
.unwrap()
.and_then(|(client, _)| client.outbound()) .and_then(|(client, _)| client.outbound())
.map(|server| Framed::<_, bytes::BytesMut>::new(server)) .map(|server| Framed::<_, bytes::BytesMut>::new(server))
.and_then(|server| server.send("hello world".into())) .and_then(|server| server.send("hello world".into()))

View File

@ -24,7 +24,7 @@
use ProtocolChoiceError; use ProtocolChoiceError;
use bytes::Bytes; use bytes::Bytes;
use futures::{Future, Sink, Stream}; use futures::{Future, Sink, Stream};
use futures::future::{result, loop_fn, Loop}; use futures::future::{loop_fn, result, Loop};
use protocol::Dialer; use protocol::Dialer;
use protocol::DialerToListenerMessage; use protocol::DialerToListenerMessage;
@ -48,10 +48,11 @@ pub fn dialer_select_proto<'a, R, I, M, P>(
inner: R, inner: R,
protocols: I, protocols: I,
) -> Box<Future<Item = (P, R), Error = ProtocolChoiceError> + 'a> ) -> Box<Future<Item = (P, R), Error = ProtocolChoiceError> + 'a>
where R: AsyncRead + AsyncWrite + 'a, where
R: AsyncRead + AsyncWrite + 'a,
I: Iterator<Item = (Bytes, M, P)> + 'a, I: Iterator<Item = (Bytes, M, P)> + 'a,
M: FnMut(&Bytes, &Bytes) -> bool + 'a, M: FnMut(&Bytes, &Bytes) -> bool + 'a,
P: 'a P: 'a,
{ {
// We choose between the "serial" and "parallel" strategies based on the number of protocols. // We choose between the "serial" and "parallel" strategies based on the number of protocols.
if protocols.size_hint().1.map(|n| n <= 3).unwrap_or(false) { if protocols.size_hint().1.map(|n| n <= 3).unwrap_or(false) {
@ -70,19 +71,21 @@ pub fn dialer_select_proto_serial<'a, R, I, P>(
inner: R, inner: R,
mut protocols: I, mut protocols: I,
) -> Box<Future<Item = (P, R), Error = ProtocolChoiceError> + 'a> ) -> Box<Future<Item = (P, R), Error = ProtocolChoiceError> + 'a>
where R: AsyncRead + AsyncWrite + 'a, where
R: AsyncRead + AsyncWrite + 'a,
I: Iterator<Item = (Bytes, P)> + 'a, I: Iterator<Item = (Bytes, P)> + 'a,
P: 'a P: 'a,
{ {
let future = Dialer::new(inner) let future = Dialer::new(inner).from_err().and_then(move |dialer| {
.from_err()
.and_then(move |dialer| {
// Similar to a `loop` keyword. // Similar to a `loop` keyword.
loop_fn(dialer, move |dialer| { loop_fn(dialer, move |dialer| {
result(protocols.next().ok_or(ProtocolChoiceError::NoProtocolFound)) result(protocols.next().ok_or(ProtocolChoiceError::NoProtocolFound))
// If the `protocols` iterator produced an element, send it to the dialer // If the `protocols` iterator produced an element, send it to the dialer
.and_then(|(proto_name, proto_value)| { .and_then(|(proto_name, proto_value)| {
dialer.send(DialerToListenerMessage::ProtocolRequest { name: proto_name.clone() }) let req = DialerToListenerMessage::ProtocolRequest {
name: proto_name.clone()
};
dialer.send(req)
.map(|d| (d, proto_name, proto_value)) .map(|d| (d, proto_name, proto_value))
.from_err() .from_err()
}) })
@ -126,16 +129,19 @@ pub fn dialer_select_proto_parallel<'a, R, I, M, P>(
inner: R, inner: R,
protocols: I, protocols: I,
) -> Box<Future<Item = (P, R), Error = ProtocolChoiceError> + 'a> ) -> Box<Future<Item = (P, R), Error = ProtocolChoiceError> + 'a>
where R: AsyncRead + AsyncWrite + 'a, where
R: AsyncRead + AsyncWrite + 'a,
I: Iterator<Item = (Bytes, M, P)> + 'a, I: Iterator<Item = (Bytes, M, P)> + 'a,
M: FnMut(&Bytes, &Bytes) -> bool + 'a, M: FnMut(&Bytes, &Bytes) -> bool + 'a,
P: 'a P: 'a,
{ {
let future = Dialer::new(inner) let future = Dialer::new(inner)
.from_err() .from_err()
.and_then( .and_then(move |dialer| {
move |dialer| dialer.send(DialerToListenerMessage::ProtocolsListRequest).from_err(), dialer
) .send(DialerToListenerMessage::ProtocolsListRequest)
.from_err()
})
.and_then(move |dialer| dialer.into_future().map_err(|(e, _)| e.into())) .and_then(move |dialer| dialer.into_future().map_err(|(e, _)| e.into()))
.and_then(move |(msg, dialer)| { .and_then(move |(msg, dialer)| {
let list = match msg { let list = match msg {
@ -161,12 +167,16 @@ pub fn dialer_select_proto_parallel<'a, R, I, M, P>(
Ok((proto_name, proto_val, dialer)) Ok((proto_name, proto_val, dialer))
}) })
.and_then(|(proto_name, proto_val, dialer)| { .and_then(|(proto_name, proto_val, dialer)| {
dialer.send(DialerToListenerMessage::ProtocolRequest { name: proto_name.clone() }) dialer
.send(DialerToListenerMessage::ProtocolRequest {
name: proto_name.clone(),
})
.from_err() .from_err()
.map(|dialer| (proto_name, proto_val, dialer)) .map(|dialer| (proto_name, proto_val, dialer))
}) })
.and_then(|(proto_name, proto_val, dialer)| { .and_then(|(proto_name, proto_val, dialer)| {
dialer.into_future() dialer
.into_future()
.map(|(msg, rest)| (proto_name, proto_val, msg, rest)) .map(|(msg, rest)| (proto_name, proto_val, msg, rest))
.map_err(|(err, _)| err.into()) .map_err(|(err, _)| err.into())
}) })

View File

@ -56,23 +56,19 @@ impl error::Error for ProtocolChoiceError {
#[inline] #[inline]
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
ProtocolChoiceError::MultistreamSelectError(_) => { ProtocolChoiceError::MultistreamSelectError(_) => "error in the protocol",
"error in the protocol"
},
ProtocolChoiceError::UnexpectedMessage => { ProtocolChoiceError::UnexpectedMessage => {
"received a message from the remote that makes no sense in the current context" "received a message from the remote that makes no sense in the current context"
}, }
ProtocolChoiceError::NoProtocolFound => { ProtocolChoiceError::NoProtocolFound => {
"we don't support any protocol in common with the remote" "we don't support any protocol in common with the remote"
}, }
} }
} }
fn cause(&self) -> Option<&error::Error> { fn cause(&self) -> Option<&error::Error> {
match *self { match *self {
ProtocolChoiceError::MultistreamSelectError(ref err) => { ProtocolChoiceError::MultistreamSelectError(ref err) => Some(err),
Some(err)
}
_ => None, _ => None,
} }
} }

View File

@ -28,7 +28,7 @@
use std::io::{Error as IoError, ErrorKind as IoErrorKind}; use std::io::{Error as IoError, ErrorKind as IoErrorKind};
use std::marker::PhantomData; use std::marker::PhantomData;
use futures::{Async, StartSend, Poll, Sink, Stream}; use futures::{Async, Poll, Sink, StartSend, Stream};
use smallvec::SmallVec; use smallvec::SmallVec;
use tokio_io::AsyncRead; use tokio_io::AsyncRead;
@ -56,16 +56,18 @@ enum State {
// We are currently reading the length of the next frame of data. // We are currently reading the length of the next frame of data.
ReadingLength, ReadingLength,
// We are currently reading the frame of data itself. // We are currently reading the frame of data itself.
ReadingData { ReadingData { frame_len: u16 },
frame_len: u16
},
} }
impl<I, S> LengthDelimitedFramedRead<I, S> { impl<I, S> LengthDelimitedFramedRead<I, S> {
pub fn new(inner: S) -> LengthDelimitedFramedRead<I, S> { pub fn new(inner: S) -> LengthDelimitedFramedRead<I, S> {
LengthDelimitedFramedRead { LengthDelimitedFramedRead {
inner: inner, inner: inner,
internal_buffer: { let mut v = SmallVec::new(); v.push(0); v }, internal_buffer: {
let mut v = SmallVec::new();
v.push(0);
v
},
internal_buffer_pos: 0, internal_buffer_pos: 0,
state: State::ReadingLength, state: State::ReadingLength,
marker: PhantomData, marker: PhantomData,
@ -92,8 +94,9 @@ impl<I, S> LengthDelimitedFramedRead<I, S> {
} }
impl<I, S> Stream for LengthDelimitedFramedRead<I, S> impl<I, S> Stream for LengthDelimitedFramedRead<I, S>
where S: AsyncRead, where
I: for<'r> From<&'r [u8]> S: AsyncRead,
I: for<'r> From<&'r [u8]>,
{ {
type Item = I; type Item = I;
type Error = IoError; type Error = IoError;
@ -105,26 +108,27 @@ impl<I, S> Stream for LengthDelimitedFramedRead<I, S>
match self.state { match self.state {
State::ReadingLength => { State::ReadingLength => {
match self.inner.read(&mut self.internal_buffer[self.internal_buffer_pos..]) { match self.inner
.read(&mut self.internal_buffer[self.internal_buffer_pos..])
{
Ok(0) => { Ok(0) => {
// EOF // EOF
if self.internal_buffer_pos == 0 { if self.internal_buffer_pos == 0 {
return Ok(Async::Ready(None)); return Ok(Async::Ready(None));
} else { } else {
return Err(IoError::new(IoErrorKind::BrokenPipe, return Err(IoError::new(IoErrorKind::BrokenPipe, "unexpected eof"));
"unexpected eof")); }
} }
},
Ok(n) => { Ok(n) => {
debug_assert_eq!(n, 1); debug_assert_eq!(n, 1);
self.internal_buffer_pos += n; self.internal_buffer_pos += n;
}, }
Err(ref err) if err.kind() == IoErrorKind::WouldBlock => { Err(ref err) if err.kind() == IoErrorKind::WouldBlock => {
return Ok(Async::NotReady); return Ok(Async::NotReady);
}, }
Err(err) => { Err(err) => {
return Err(err); return Err(err);
}, }
}; };
debug_assert_eq!(self.internal_buffer.len(), self.internal_buffer_pos); debug_assert_eq!(self.internal_buffer.len(), self.internal_buffer_pos);
@ -135,12 +139,13 @@ impl<I, S> Stream for LengthDelimitedFramedRead<I, S>
let frame_len = decode_length_prefix(&self.internal_buffer); let frame_len = decode_length_prefix(&self.internal_buffer);
if frame_len >= 1 { if frame_len >= 1 {
self.state = State::ReadingData { frame_len: frame_len }; self.state = State::ReadingData {
frame_len: frame_len,
};
self.internal_buffer.clear(); self.internal_buffer.clear();
self.internal_buffer.reserve(frame_len as usize); self.internal_buffer.reserve(frame_len as usize);
self.internal_buffer.extend((0 .. frame_len).map(|_| 0)); self.internal_buffer.extend((0..frame_len).map(|_| 0));
self.internal_buffer_pos = 0; self.internal_buffer_pos = 0;
} else { } else {
debug_assert_eq!(frame_len, 0); debug_assert_eq!(frame_len, 0);
self.state = State::ReadingLength; self.state = State::ReadingLength;
@ -149,29 +154,32 @@ impl<I, S> Stream for LengthDelimitedFramedRead<I, S>
self.internal_buffer_pos = 0; self.internal_buffer_pos = 0;
return Ok(Async::Ready(Some(From::from(&[][..])))); return Ok(Async::Ready(Some(From::from(&[][..]))));
} }
} else if self.internal_buffer_pos >= 2 { } else if self.internal_buffer_pos >= 2 {
// Length prefix is too long. See module doc for info about max frame len. // Length prefix is too long. See module doc for info about max frame len.
return Err(IoError::new(IoErrorKind::InvalidData, "frame length too long")); return Err(IoError::new(
IoErrorKind::InvalidData,
"frame length too long",
));
} else { } else {
// Prepare for next read. // Prepare for next read.
self.internal_buffer.push(0); self.internal_buffer.push(0);
} }
}, }
State::ReadingData { frame_len } => { State::ReadingData { frame_len } => {
match self.inner.read(&mut self.internal_buffer[self.internal_buffer_pos..]) { match self.inner
.read(&mut self.internal_buffer[self.internal_buffer_pos..])
{
Ok(0) => { Ok(0) => {
return Err(IoError::new(IoErrorKind::BrokenPipe, "unexpected eof")); return Err(IoError::new(IoErrorKind::BrokenPipe, "unexpected eof"));
}, }
Ok(n) => self.internal_buffer_pos += n, Ok(n) => self.internal_buffer_pos += n,
Err(ref err) if err.kind() == IoErrorKind::WouldBlock => { Err(ref err) if err.kind() == IoErrorKind::WouldBlock => {
return Ok(Async::NotReady); return Ok(Async::NotReady);
}, }
Err(err) => { Err(err) => {
return Err(err); return Err(err);
}, }
}; };
if self.internal_buffer_pos >= frame_len as usize { if self.internal_buffer_pos >= frame_len as usize {
@ -183,14 +191,15 @@ impl<I, S> Stream for LengthDelimitedFramedRead<I, S>
self.internal_buffer_pos = 0; self.internal_buffer_pos = 0;
return Ok(Async::Ready(Some(out_data))); return Ok(Async::Ready(Some(out_data)));
} }
}, }
} }
} }
} }
} }
impl<I, S> Sink for LengthDelimitedFramedRead<I, S> impl<I, S> Sink for LengthDelimitedFramedRead<I, S>
where S: Sink where
S: Sink,
{ {
type SinkItem = S::SinkItem; type SinkItem = S::SinkItem;
type SinkError = S::SinkError; type SinkError = S::SinkError;
@ -250,25 +259,34 @@ mod tests {
fn two_bytes_long_packet() { fn two_bytes_long_packet() {
let len = 5000u16; let len = 5000u16;
assert!(len < (1 << 15)); assert!(len < (1 << 15));
let frame = (0 .. len).map(|n| (n & 0xff) as u8).collect::<Vec<_>>(); let frame = (0..len).map(|n| (n & 0xff) as u8).collect::<Vec<_>>();
let mut data = vec![(len & 0x7f) as u8 | 0x80, (len >> 7) as u8]; let mut data = vec![(len & 0x7f) as u8 | 0x80, (len >> 7) as u8];
data.extend(frame.clone().into_iter()); data.extend(frame.clone().into_iter());
let framed = LengthDelimitedFramedRead::<Vec<u8>, _>::new(Cursor::new(data)); let framed = LengthDelimitedFramedRead::<Vec<u8>, _>::new(Cursor::new(data));
let recved = framed.into_future().map(|(m, _)| m).map_err(|_| ()).wait().unwrap(); let recved = framed
.into_future()
.map(|(m, _)| m)
.map_err(|_| ())
.wait()
.unwrap();
assert_eq!(recved.unwrap(), frame); assert_eq!(recved.unwrap(), frame);
} }
#[test] #[test]
fn packet_len_too_long() { fn packet_len_too_long() {
let mut data = vec![0x81, 0x81, 0x1]; let mut data = vec![0x81, 0x81, 0x1];
data.extend((0 .. 16513).map(|_| 0)); data.extend((0..16513).map(|_| 0));
let framed = LengthDelimitedFramedRead::<Vec<u8>, _>::new(Cursor::new(data)); let framed = LengthDelimitedFramedRead::<Vec<u8>, _>::new(Cursor::new(data));
let recved = framed.into_future().map(|(m, _)| m).map_err(|(err, _)| err).wait(); let recved = framed
.into_future()
.map(|(m, _)| m)
.map_err(|(err, _)| err)
.wait();
match recved { match recved {
Err(io_err) => assert_eq!(io_err.kind(), ErrorKind::InvalidData), Err(io_err) => assert_eq!(io_err.kind(), ErrorKind::InvalidData),
_ => panic!() _ => panic!(),
} }
} }
@ -278,7 +296,16 @@ mod tests {
let framed = LengthDelimitedFramedRead::<Vec<u8>, _>::new(Cursor::new(data)); let framed = LengthDelimitedFramedRead::<Vec<u8>, _>::new(Cursor::new(data));
let recved = framed.collect().wait().unwrap(); let recved = framed.collect().wait().unwrap();
assert_eq!(recved, vec![vec![], vec![], vec![9, 8, 7, 6, 5, 4], vec![], vec![9, 8, 7]]); assert_eq!(
recved,
vec![
vec![],
vec![],
vec![9, 8, 7, 6, 5, 4],
vec![],
vec![9, 8, 7],
]
);
} }
#[test] #[test]
@ -289,7 +316,7 @@ mod tests {
let recved = framed.collect().wait(); let recved = framed.collect().wait();
match recved { match recved {
Err(io_err) => assert_eq!(io_err.kind(), ErrorKind::BrokenPipe), Err(io_err) => assert_eq!(io_err.kind(), ErrorKind::BrokenPipe),
_ => panic!() _ => panic!(),
} }
} }
@ -301,7 +328,7 @@ mod tests {
let recved = framed.collect().wait(); let recved = framed.collect().wait();
match recved { match recved {
Err(io_err) => assert_eq!(io_err.kind(), ErrorKind::BrokenPipe), Err(io_err) => assert_eq!(io_err.kind(), ErrorKind::BrokenPipe),
_ => panic!() _ => panic!(),
} }
} }
@ -313,7 +340,7 @@ mod tests {
let recved = framed.collect().wait(); let recved = framed.collect().wait();
match recved { match recved {
Err(io_err) => assert_eq!(io_err.kind(), ErrorKind::BrokenPipe), Err(io_err) => assert_eq!(io_err.kind(), ErrorKind::BrokenPipe),
_ => panic!() _ => panic!(),
} }
} }
} }

View File

@ -50,24 +50,28 @@ pub fn listener_select_proto<'a, R, I, M, P>(
inner: R, inner: R,
protocols: I, protocols: I,
) -> Box<Future<Item = (P, R), Error = ProtocolChoiceError> + 'a> ) -> Box<Future<Item = (P, R), Error = ProtocolChoiceError> + 'a>
where R: AsyncRead + AsyncWrite + 'a, where
R: AsyncRead + AsyncWrite + 'a,
I: Iterator<Item = (Bytes, M, P)> + Clone + 'a, I: Iterator<Item = (Bytes, M, P)> + Clone + 'a,
M: FnMut(&Bytes, &Bytes) -> bool + 'a, M: FnMut(&Bytes, &Bytes) -> bool + 'a,
P: 'a P: 'a,
{ {
let future = Listener::new(inner).from_err().and_then(move |listener| { let future = Listener::new(inner).from_err().and_then(move |listener| {
loop_fn(listener, move |listener| { loop_fn(listener, move |listener| {
let protocols = protocols.clone(); let protocols = protocols.clone();
listener.into_future() listener
.into_future()
.map_err(|(e, _)| e.into()) .map_err(|(e, _)| e.into())
.and_then(move |(message, listener)| match message { .and_then(move |(message, listener)| match message {
Some(DialerToListenerMessage::ProtocolsListRequest) => { Some(DialerToListenerMessage::ProtocolsListRequest) => {
let msg = ListenerToDialerMessage::ProtocolsListResponse { let msg = ListenerToDialerMessage::ProtocolsListResponse {
list: protocols.map(|(p, _, _)| p).collect(), list: protocols.map(|(p, _, _)| p).collect(),
}; };
let fut = listener.send(msg).from_err().map(move |listener| (None, listener)); let fut = listener
.send(msg)
.from_err()
.map(move |listener| (None, listener));
Box::new(fut) as Box<Future<Item = _, Error = ProtocolChoiceError>> Box::new(fut) as Box<Future<Item = _, Error = ProtocolChoiceError>>
} }
Some(DialerToListenerMessage::ProtocolRequest { name }) => { Some(DialerToListenerMessage::ProtocolRequest { name }) => {
@ -75,20 +79,20 @@ pub fn listener_select_proto<'a, R, I, M, P>(
let mut send_back = ListenerToDialerMessage::NotAvailable; let mut send_back = ListenerToDialerMessage::NotAvailable;
for (supported, mut matches, value) in protocols { for (supported, mut matches, value) in protocols {
if matches(&name, &supported) { if matches(&name, &supported) {
send_back = ListenerToDialerMessage::ProtocolAck { name: name.clone() }; send_back =
ListenerToDialerMessage::ProtocolAck { name: name.clone() };
outcome = Some(value); outcome = Some(value);
break; break;
} }
} }
let fut = listener.send(send_back) let fut = listener
.send(send_back)
.from_err() .from_err()
.map(move |listener| (outcome, listener)); .map(move |listener| (outcome, listener));
Box::new(fut) as Box<Future<Item = _, Error = ProtocolChoiceError>> Box::new(fut) as Box<Future<Item = _, Error = ProtocolChoiceError>>
} }
None => { None => Box::new(err(ProtocolChoiceError::NoProtocolFound)) as Box<_>,
Box::new(err(ProtocolChoiceError::NoProtocolFound)) as Box<_>
}
}) })
.map(|(outcome, listener): (_, Listener<R>)| match outcome { .map(|(outcome, listener): (_, Listener<R>)| match outcome {
Some(outcome) => Loop::Break((outcome, listener.into_inner())), Some(outcome) => Loop::Break((outcome, listener.into_inner())),

View File

@ -27,7 +27,7 @@ use protocol::DialerToListenerMessage;
use protocol::ListenerToDialerMessage; use protocol::ListenerToDialerMessage;
use protocol::MULTISTREAM_PROTOCOL_WITH_LF; use protocol::MULTISTREAM_PROTOCOL_WITH_LF;
use protocol::MultistreamSelectError; use protocol::MultistreamSelectError;
use std::io::{Cursor, Read, BufRead}; use std::io::{BufRead, Cursor, Read};
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::length_delimited::Builder as LengthDelimitedBuilder; use tokio_io::codec::length_delimited::Builder as LengthDelimitedBuilder;
use tokio_io::codec::length_delimited::FramedWrite as LengthDelimitedFramedWrite; use tokio_io::codec::length_delimited::FramedWrite as LengthDelimitedFramedWrite;
@ -41,22 +41,26 @@ pub struct Dialer<R> {
} }
impl<R> Dialer<R> impl<R> Dialer<R>
where R: AsyncRead + AsyncWrite where
R: AsyncRead + AsyncWrite,
{ {
/// Takes ownership of a socket and starts the handshake. If the handshake succeeds, the /// Takes ownership of a socket and starts the handshake. If the handshake succeeds, the
/// future returns a `Dialer`. /// future returns a `Dialer`.
pub fn new<'a>(inner: R) -> Box<Future<Item = Dialer<R>, Error = MultistreamSelectError> + 'a> pub fn new<'a>(inner: R) -> Box<Future<Item = Dialer<R>, Error = MultistreamSelectError> + 'a>
where R: 'a where
R: 'a,
{ {
let write = LengthDelimitedBuilder::new().length_field_length(1).new_write(inner); let write = LengthDelimitedBuilder::new()
.length_field_length(1)
.new_write(inner);
let inner = LengthDelimitedFramedRead::new(write); let inner = LengthDelimitedFramedRead::new(write);
let future = let future = inner
inner.send(BytesMut::from(MULTISTREAM_PROTOCOL_WITH_LF)).from_err().map(|inner| { .send(BytesMut::from(MULTISTREAM_PROTOCOL_WITH_LF))
Dialer { .from_err()
.map(|inner| Dialer {
inner: inner, inner: inner,
handshake_finished: false, handshake_finished: false,
}
}); });
Box::new(future) Box::new(future)
} }
@ -69,7 +73,8 @@ impl<R> Dialer<R>
} }
impl<R> Sink for Dialer<R> impl<R> Sink for Dialer<R>
where R: AsyncRead + AsyncWrite where
R: AsyncRead + AsyncWrite,
{ {
type SinkItem = DialerToListenerMessage; type SinkItem = DialerToListenerMessage;
type SinkError = MultistreamSelectError; type SinkError = MultistreamSelectError;
@ -99,9 +104,9 @@ impl<R> Sink for Dialer<R>
DialerToListenerMessage::ProtocolsListRequest => { DialerToListenerMessage::ProtocolsListRequest => {
match self.inner.start_send(BytesMut::from(&b"ls\n"[..])) { match self.inner.start_send(BytesMut::from(&b"ls\n"[..])) {
Ok(AsyncSink::Ready) => Ok(AsyncSink::Ready), Ok(AsyncSink::Ready) => Ok(AsyncSink::Ready),
Ok(AsyncSink::NotReady(_)) => { Ok(AsyncSink::NotReady(_)) => Ok(AsyncSink::NotReady(
Ok(AsyncSink::NotReady(DialerToListenerMessage::ProtocolsListRequest)) DialerToListenerMessage::ProtocolsListRequest,
} )),
Err(err) => Err(err.into()), Err(err) => Err(err.into()),
} }
} }
@ -115,7 +120,8 @@ impl<R> Sink for Dialer<R>
} }
impl<R> Stream for Dialer<R> impl<R> Stream for Dialer<R>
where R: AsyncRead + AsyncWrite where
R: AsyncRead + AsyncWrite,
{ {
type Item = ListenerToDialerMessage; type Item = ListenerToDialerMessage;
type Error = MultistreamSelectError; type Error = MultistreamSelectError;
@ -141,20 +147,21 @@ impl<R> Stream for Dialer<R>
if frame.get(0) == Some(&b'/') && frame.last() == Some(&b'\n') { if frame.get(0) == Some(&b'/') && frame.last() == Some(&b'\n') {
let frame_len = frame.len(); let frame_len = frame.len();
let protocol = frame.split_to(frame_len - 1); let protocol = frame.split_to(frame_len - 1);
return Ok( return Ok(Async::Ready(Some(ListenerToDialerMessage::ProtocolAck {
Async::Ready(Some(ListenerToDialerMessage::ProtocolAck { name: protocol })), name: protocol,
); })));
} else if frame == &b"na\n"[..] { } else if frame == &b"na\n"[..] {
return Ok(Async::Ready(Some(ListenerToDialerMessage::NotAvailable))); return Ok(Async::Ready(Some(ListenerToDialerMessage::NotAvailable)));
} else { } else {
// A varint number of protocols // A varint number of protocols
let mut reader = Cursor::new(frame); let mut reader = Cursor::new(frame);
let num_protocols: usize = varint::decode(reader.by_ref())?; let num_protocols: usize = varint::decode(reader.by_ref())?;
let mut iter = BufRead::split(reader, b'\r'); let mut iter = BufRead::split(reader, b'\r');
if !iter.next().ok_or(MultistreamSelectError::UnknownMessage)??.is_empty() { if !iter.next()
.ok_or(MultistreamSelectError::UnknownMessage)??
.is_empty()
{
return Err(MultistreamSelectError::UnknownMessage); return Err(MultistreamSelectError::UnknownMessage);
} }
@ -173,9 +180,9 @@ impl<R> Stream for Dialer<R>
return Err(MultistreamSelectError::UnknownMessage); return Err(MultistreamSelectError::UnknownMessage);
} }
return Ok(Async::Ready(Some(ListenerToDialerMessage::ProtocolsListResponse { return Ok(Async::Ready(Some(
list: out ListenerToDialerMessage::ProtocolsListResponse { list: out },
}))); )));
} }
} }
} }
@ -198,7 +205,11 @@ mod tests {
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap(); let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
let listener_addr = listener.local_addr().unwrap(); let listener_addr = listener.local_addr().unwrap();
let server = listener.incoming().into_future().map(|_| ()).map_err(|(e, _)| e.into()); let server = listener
.incoming()
.into_future()
.map(|_| ())
.map_err(|(e, _)| e.into());
let client = TcpStream::connect(&listener_addr, &core.handle()) let client = TcpStream::connect(&listener_addr, &core.handle())
.from_err() .from_err()

View File

@ -63,29 +63,23 @@ impl error::Error for MultistreamSelectError {
#[inline] #[inline]
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
MultistreamSelectError::IoError(_) => { MultistreamSelectError::IoError(_) => "I/O error",
"I/O error"
},
MultistreamSelectError::FailedHandshake => { MultistreamSelectError::FailedHandshake => {
"the remote doesn't use the same multistream-select protocol as we do" "the remote doesn't use the same multistream-select protocol as we do"
}, }
MultistreamSelectError::UnknownMessage => { MultistreamSelectError::UnknownMessage => "received an unknown message from the remote",
"received an unknown message from the remote"
},
MultistreamSelectError::WrongProtocolName => { MultistreamSelectError::WrongProtocolName => {
"protocol names must always start with `/`, otherwise this error is returned" "protocol names must always start with `/`, otherwise this error is returned"
}, }
MultistreamSelectError::VarintParseError(_) => { MultistreamSelectError::VarintParseError(_) => {
"failure to parse variable-length integer" "failure to parse variable-length integer"
}, }
} }
} }
fn cause(&self) -> Option<&error::Error> { fn cause(&self) -> Option<&error::Error> {
match *self { match *self {
MultistreamSelectError::IoError(ref err) => { MultistreamSelectError::IoError(ref err) => Some(err),
Some(err)
}
_ => None, _ => None,
} }
} }

View File

@ -39,17 +39,22 @@ pub struct Listener<R> {
} }
impl<R> Listener<R> impl<R> Listener<R>
where R: AsyncRead + AsyncWrite where
R: AsyncRead + AsyncWrite,
{ {
/// Takes ownership of a socket and starts the handshake. If the handshake succeeds, the /// Takes ownership of a socket and starts the handshake. If the handshake succeeds, the
/// future returns a `Listener`. /// future returns a `Listener`.
pub fn new<'a>(inner: R) -> Box<Future<Item = Listener<R>, Error = MultistreamSelectError> + 'a> pub fn new<'a>(inner: R) -> Box<Future<Item = Listener<R>, Error = MultistreamSelectError> + 'a>
where R: 'a where
R: 'a,
{ {
let write = LengthDelimitedBuilder::new().length_field_length(1).new_write(inner); let write = LengthDelimitedBuilder::new()
.length_field_length(1)
.new_write(inner);
let inner = LengthDelimitedFramedRead::<Bytes, _>::new(write); let inner = LengthDelimitedFramedRead::<Bytes, _>::new(write);
let future = inner.into_future() let future = inner
.into_future()
.map_err(|(e, _)| e.into()) .map_err(|(e, _)| e.into())
.and_then(|(msg, rest)| { .and_then(|(msg, rest)| {
if msg.as_ref().map(|b| &b[..]) != Some(MULTISTREAM_PROTOCOL_WITH_LF) { if msg.as_ref().map(|b| &b[..]) != Some(MULTISTREAM_PROTOCOL_WITH_LF) {
@ -58,7 +63,9 @@ impl<R> Listener<R>
Ok(rest) Ok(rest)
}) })
.and_then(|socket| { .and_then(|socket| {
socket.send(BytesMut::from(MULTISTREAM_PROTOCOL_WITH_LF)).from_err() socket
.send(BytesMut::from(MULTISTREAM_PROTOCOL_WITH_LF))
.from_err()
}) })
.map(|inner| Listener { inner: inner }); .map(|inner| Listener { inner: inner });
@ -74,7 +81,8 @@ impl<R> Listener<R>
} }
impl<R> Sink for Listener<R> impl<R> Sink for Listener<R>
where R: AsyncRead + AsyncWrite where
R: AsyncRead + AsyncWrite,
{ {
type SinkItem = ListenerToDialerMessage; type SinkItem = ListenerToDialerMessage;
type SinkError = MultistreamSelectError; type SinkError = MultistreamSelectError;
@ -94,9 +102,9 @@ impl<R> Sink for Listener<R>
let protocol_len = protocol.len(); let protocol_len = protocol.len();
protocol.truncate(protocol_len - 1); protocol.truncate(protocol_len - 1);
let protocol = protocol.freeze(); let protocol = protocol.freeze();
Ok( Ok(AsyncSink::NotReady(ListenerToDialerMessage::ProtocolAck {
AsyncSink::NotReady(ListenerToDialerMessage::ProtocolAck { name: protocol }), name: protocol,
) }))
} }
Err(err) => Err(err.into()), Err(err) => Err(err.into()),
} }
@ -141,7 +149,8 @@ impl<R> Sink for Listener<R>
} }
impl<R> Stream for Listener<R> impl<R> Stream for Listener<R>
where R: AsyncRead + AsyncWrite where
R: AsyncRead + AsyncWrite,
{ {
type Item = DialerToListenerMessage; type Item = DialerToListenerMessage;
type Error = MultistreamSelectError; type Error = MultistreamSelectError;
@ -158,13 +167,13 @@ impl<R> Stream for Listener<R>
if frame.get(0) == Some(&b'/') && frame.last() == Some(&b'\n') { if frame.get(0) == Some(&b'/') && frame.last() == Some(&b'\n') {
let frame_len = frame.len(); let frame_len = frame.len();
let protocol = frame.split_to(frame_len - 1); let protocol = frame.split_to(frame_len - 1);
return Ok(Async::Ready( return Ok(Async::Ready(Some(
Some(DialerToListenerMessage::ProtocolRequest { name: protocol }), DialerToListenerMessage::ProtocolRequest { name: protocol },
)); )));
} else if frame == &b"ls\n"[..] { } else if frame == &b"ls\n"[..] {
return Ok(Async::Ready(Some(DialerToListenerMessage::ProtocolsListRequest))); return Ok(Async::Ready(Some(
DialerToListenerMessage::ProtocolsListRequest,
)));
} else { } else {
return Err(MultistreamSelectError::UnknownMessage); return Err(MultistreamSelectError::UnknownMessage);
} }
@ -189,7 +198,8 @@ mod tests {
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap(); let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
let listener_addr = listener.local_addr().unwrap(); let listener_addr = listener.local_addr().unwrap();
let server = listener.incoming() let server = listener
.incoming()
.into_future() .into_future()
.map_err(|(e, _)| e.into()) .map_err(|(e, _)| e.into())
.and_then(move |(connec, _)| Listener::new(connec.unwrap().0)) .and_then(move |(connec, _)| Listener::new(connec.unwrap().0))

View File

@ -24,13 +24,13 @@
extern crate tokio_core; extern crate tokio_core;
use {listener_select_proto, dialer_select_proto}; use {dialer_select_proto, listener_select_proto};
use ProtocolChoiceError; use ProtocolChoiceError;
use bytes::Bytes; use bytes::Bytes;
use dialer_select::{dialer_select_proto_parallel, dialer_select_proto_serial}; use dialer_select::{dialer_select_proto_parallel, dialer_select_proto_serial};
use futures::{Sink, Stream}; use futures::{Sink, Stream};
use futures::Future; use futures::Future;
use protocol::{Dialer, Listener, DialerToListenerMessage, ListenerToDialerMessage}; use protocol::{Dialer, DialerToListenerMessage, Listener, ListenerToDialerMessage};
use self::tokio_core::net::TcpListener; use self::tokio_core::net::TcpListener;
use self::tokio_core::net::TcpStream; use self::tokio_core::net::TcpStream;
use self::tokio_core::reactor::Core; use self::tokio_core::reactor::Core;
@ -42,7 +42,8 @@ fn negotiate_with_self_succeeds() {
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap(); let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
let listener_addr = listener.local_addr().unwrap(); let listener_addr = listener.local_addr().unwrap();
let server = listener.incoming() let server = listener
.incoming()
.into_future() .into_future()
.map_err(|(e, _)| e.into()) .map_err(|(e, _)| e.into())
.and_then(move |(connec, _)| Listener::new(connec.unwrap().0)) .and_then(move |(connec, _)| Listener::new(connec.unwrap().0))
@ -82,7 +83,8 @@ fn select_proto_basic() {
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap(); let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
let listener_addr = listener.local_addr().unwrap(); let listener_addr = listener.local_addr().unwrap();
let server = listener.incoming() let server = listener
.incoming()
.into_future() .into_future()
.map(|s| s.0.unwrap().0) .map(|s| s.0.unwrap().0)
.map_err(|(e, _)| e.into()) .map_err(|(e, _)| e.into())
@ -90,18 +92,17 @@ fn select_proto_basic() {
let protos = vec![ let protos = vec![
(Bytes::from("/proto1"), <Bytes as PartialEq>::eq, 0), (Bytes::from("/proto1"), <Bytes as PartialEq>::eq, 0),
(Bytes::from("/proto2"), <Bytes as PartialEq>::eq, 1), (Bytes::from("/proto2"), <Bytes as PartialEq>::eq, 1),
] ].into_iter();
.into_iter();
listener_select_proto(connec, protos).map(|r| r.0) listener_select_proto(connec, protos).map(|r| r.0)
}); });
let client = let client = TcpStream::connect(&listener_addr, &core.handle())
TcpStream::connect(&listener_addr, &core.handle()).from_err().and_then(move |connec| { .from_err()
.and_then(move |connec| {
let protos = vec![ let protos = vec![
(Bytes::from("/proto3"), <Bytes as PartialEq>::eq, 2), (Bytes::from("/proto3"), <Bytes as PartialEq>::eq, 2),
(Bytes::from("/proto2"), <Bytes as PartialEq>::eq, 3), (Bytes::from("/proto2"), <Bytes as PartialEq>::eq, 3),
] ].into_iter();
.into_iter();
dialer_select_proto(connec, protos).map(|r| r.0) dialer_select_proto(connec, protos).map(|r| r.0)
}); });
@ -117,7 +118,8 @@ fn no_protocol_found() {
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap(); let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
let listener_addr = listener.local_addr().unwrap(); let listener_addr = listener.local_addr().unwrap();
let server = listener.incoming() let server = listener
.incoming()
.into_future() .into_future()
.map(|s| s.0.unwrap().0) .map(|s| s.0.unwrap().0)
.map_err(|(e, _)| e.into()) .map_err(|(e, _)| e.into())
@ -125,18 +127,17 @@ fn no_protocol_found() {
let protos = vec![ let protos = vec![
(Bytes::from("/proto1"), <Bytes as PartialEq>::eq, 1), (Bytes::from("/proto1"), <Bytes as PartialEq>::eq, 1),
(Bytes::from("/proto2"), <Bytes as PartialEq>::eq, 2), (Bytes::from("/proto2"), <Bytes as PartialEq>::eq, 2),
] ].into_iter();
.into_iter();
listener_select_proto(connec, protos).map(|r| r.0) listener_select_proto(connec, protos).map(|r| r.0)
}); });
let client = let client = TcpStream::connect(&listener_addr, &core.handle())
TcpStream::connect(&listener_addr, &core.handle()).from_err().and_then(move |connec| { .from_err()
.and_then(move |connec| {
let protos = vec![ let protos = vec![
(Bytes::from("/proto3"), <Bytes as PartialEq>::eq, 3), (Bytes::from("/proto3"), <Bytes as PartialEq>::eq, 3),
(Bytes::from("/proto4"), <Bytes as PartialEq>::eq, 4), (Bytes::from("/proto4"), <Bytes as PartialEq>::eq, 4),
] ].into_iter();
.into_iter();
dialer_select_proto(connec, protos).map(|r| r.0) dialer_select_proto(connec, protos).map(|r| r.0)
}); });
@ -153,7 +154,8 @@ fn select_proto_parallel() {
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap(); let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
let listener_addr = listener.local_addr().unwrap(); let listener_addr = listener.local_addr().unwrap();
let server = listener.incoming() let server = listener
.incoming()
.into_future() .into_future()
.map(|s| s.0.unwrap().0) .map(|s| s.0.unwrap().0)
.map_err(|(e, _)| e.into()) .map_err(|(e, _)| e.into())
@ -161,18 +163,17 @@ fn select_proto_parallel() {
let protos = vec![ let protos = vec![
(Bytes::from("/proto1"), <Bytes as PartialEq>::eq, 0), (Bytes::from("/proto1"), <Bytes as PartialEq>::eq, 0),
(Bytes::from("/proto2"), <Bytes as PartialEq>::eq, 1), (Bytes::from("/proto2"), <Bytes as PartialEq>::eq, 1),
] ].into_iter();
.into_iter();
listener_select_proto(connec, protos).map(|r| r.0) listener_select_proto(connec, protos).map(|r| r.0)
}); });
let client = let client = TcpStream::connect(&listener_addr, &core.handle())
TcpStream::connect(&listener_addr, &core.handle()).from_err().and_then(move |connec| { .from_err()
.and_then(move |connec| {
let protos = vec![ let protos = vec![
(Bytes::from("/proto3"), <Bytes as PartialEq>::eq, 2), (Bytes::from("/proto3"), <Bytes as PartialEq>::eq, 2),
(Bytes::from("/proto2"), <Bytes as PartialEq>::eq, 3), (Bytes::from("/proto2"), <Bytes as PartialEq>::eq, 3),
] ].into_iter();
.into_iter();
dialer_select_proto_parallel(connec, protos).map(|r| r.0) dialer_select_proto_parallel(connec, protos).map(|r| r.0)
}); });
@ -188,7 +189,8 @@ fn select_proto_serial() {
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap(); let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
let listener_addr = listener.local_addr().unwrap(); let listener_addr = listener.local_addr().unwrap();
let server = listener.incoming() let server = listener
.incoming()
.into_future() .into_future()
.map(|s| s.0.unwrap().0) .map(|s| s.0.unwrap().0)
.map_err(|(e, _)| e.into()) .map_err(|(e, _)| e.into())
@ -196,13 +198,13 @@ fn select_proto_serial() {
let protos = vec![ let protos = vec![
(Bytes::from("/proto1"), <Bytes as PartialEq>::eq, 0), (Bytes::from("/proto1"), <Bytes as PartialEq>::eq, 0),
(Bytes::from("/proto2"), <Bytes as PartialEq>::eq, 1), (Bytes::from("/proto2"), <Bytes as PartialEq>::eq, 1),
] ].into_iter();
.into_iter();
listener_select_proto(connec, protos).map(|r| r.0) listener_select_proto(connec, protos).map(|r| r.0)
}); });
let client = let client = TcpStream::connect(&listener_addr, &core.handle())
TcpStream::connect(&listener_addr, &core.handle()).from_err().and_then(move |connec| { .from_err()
.and_then(move |connec| {
let protos = vec![(Bytes::from("/proto3"), 2), (Bytes::from("/proto2"), 3)].into_iter(); let protos = vec![(Bytes::from("/proto3"), 2), (Bytes::from("/proto2"), 3)].into_iter();
dialer_select_proto_serial(connec, protos).map(|r| r.0) dialer_select_proto_serial(connec, protos).map(|r| r.0)
}); });

View File

@ -1,4 +1,4 @@
use std::{net, fmt, error, io, num, string}; use std::{error, fmt, io, net, num, string};
use cid; use cid;
use byteorder; use byteorder;
@ -35,7 +35,7 @@ impl error::Error for Error {
fn cause(&self) -> Option<&error::Error> { fn cause(&self) -> Option<&error::Error> {
match *self { match *self {
Error::ParsingError(ref err) => Some(&**err), Error::ParsingError(ref err) => Some(&**err),
_ => None _ => None,
} }
} }
} }

View File

@ -9,12 +9,12 @@ extern crate integer_encoding;
mod protocol; mod protocol;
mod errors; mod errors;
pub use errors::{Result, Error}; pub use errors::{Error, Result};
pub use protocol::{ProtocolId, ProtocolArgSize, AddrComponent}; pub use protocol::{AddrComponent, ProtocolArgSize, ProtocolId};
use std::fmt; use std::fmt;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6, IpAddr, Ipv4Addr, Ipv6Addr}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::str::FromStr; use std::str::FromStr;
/// Representation of a Multiaddr. /// Representation of a Multiaddr.
@ -135,7 +135,9 @@ impl Multiaddr {
/// ///
#[inline] #[inline]
pub fn append(&mut self, component: AddrComponent) { pub fn append(&mut self, component: AddrComponent) {
component.write_bytes(&mut self.bytes).expect("writing to a Vec never fails") component
.write_bytes(&mut self.bytes)
.expect("writing to a Vec never fails")
} }
/// Remove the outermost address. /// Remove the outermost address.
@ -189,7 +191,9 @@ impl Multiaddr {
} }
if !matches { if !matches {
return Ok(Multiaddr { bytes: self.bytes.clone() }); return Ok(Multiaddr {
bytes: self.bytes.clone(),
});
} }
let mut bytes = self.bytes.clone(); let mut bytes = self.bytes.clone();
@ -241,7 +245,8 @@ impl Multiaddr {
impl From<AddrComponent> for Multiaddr { impl From<AddrComponent> for Multiaddr {
fn from(addr: AddrComponent) -> Multiaddr { fn from(addr: AddrComponent) -> Multiaddr {
let mut out = Vec::new(); let mut out = Vec::new();
addr.write_bytes(&mut out).expect("writing to a Vec never fails"); addr.write_bytes(&mut out)
.expect("writing to a Vec never fails");
Multiaddr { bytes: out } Multiaddr { bytes: out }
} }
} }
@ -258,11 +263,13 @@ impl<'a> IntoIterator for &'a Multiaddr {
impl FromIterator<AddrComponent> for Multiaddr { impl FromIterator<AddrComponent> for Multiaddr {
fn from_iter<T>(iter: T) -> Self fn from_iter<T>(iter: T) -> Self
where T: IntoIterator<Item = AddrComponent> where
T: IntoIterator<Item = AddrComponent>,
{ {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
for cmp in iter { for cmp in iter {
cmp.write_bytes(&mut bytes).expect("writing to a Vec never fails"); cmp.write_bytes(&mut bytes)
.expect("writing to a Vec never fails");
} }
Multiaddr { bytes: bytes } Multiaddr { bytes: bytes }
} }
@ -286,14 +293,16 @@ impl FromStr for Multiaddr {
let addr_component = match protocol.size() { let addr_component = match protocol.size() {
ProtocolArgSize::Fixed { bytes: 0 } => { ProtocolArgSize::Fixed { bytes: 0 } => {
protocol.parse_data("")? // TODO: bad design protocol.parse_data("")? // TODO: bad design
}, }
_ => { _ => {
let data = parts.next().ok_or(Error::MissingAddress)?; let data = parts.next().ok_or(Error::MissingAddress)?;
protocol.parse_data(data)? protocol.parse_data(data)?
}, }
}; };
addr_component.write_bytes(&mut bytes).expect("writing to a Vec never fails"); addr_component
.write_bytes(&mut bytes)
.expect("writing to a Vec never fails");
} }
Ok(Multiaddr { bytes: bytes }) Ok(Multiaddr { bytes: bytes })
@ -311,8 +320,8 @@ impl<'a> Iterator for Iter<'a> {
return None; return None;
} }
let (component, next_data) = AddrComponent::from_bytes(self.0) let (component, next_data) =
.expect("multiaddr is known to be valid"); AddrComponent::from_bytes(self.0).expect("multiaddr is known to be valid");
self.0 = next_data; self.0 = next_data;
Some(component) Some(component)
} }

View File

@ -1,12 +1,12 @@
use std::net::{Ipv4Addr, Ipv6Addr}; use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr; use std::str::FromStr;
use std::convert::From; use std::convert::From;
use std::io::{Cursor, Write, Result as IoResult}; use std::io::{Cursor, Result as IoResult, Write};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use cid::Cid; use cid::Cid;
use integer_encoding::{VarInt, VarIntWriter}; use integer_encoding::{VarInt, VarIntWriter};
use {Result, Error}; use {Error, Result};
///! # ProtocolId ///! # ProtocolId
///! ///!
@ -117,7 +117,6 @@ impl FromStr for ProtocolId {
} }
} }
impl ProtocolId { impl ProtocolId {
/// Convert a `u64` based code to a `ProtocolId`. /// Convert a `u64` based code to a `ProtocolId`.
/// ///
@ -232,12 +231,8 @@ impl ProtocolId {
let addr = Ipv6Addr::from_str(a)?; let addr = Ipv6Addr::from_str(a)?;
Ok(AddrComponent::IP6(addr)) Ok(AddrComponent::IP6(addr))
} }
ProtocolId::DNS4 => { ProtocolId::DNS4 => Ok(AddrComponent::DNS4(a.to_owned())),
Ok(AddrComponent::DNS4(a.to_owned())) ProtocolId::DNS6 => Ok(AddrComponent::DNS6(a.to_owned())),
}
ProtocolId::DNS6 => {
Ok(AddrComponent::DNS6(a.to_owned()))
}
ProtocolId::TCP => { ProtocolId::TCP => {
let parsed: u16 = a.parse()?; let parsed: u16 = a.parse()?;
Ok(AddrComponent::TCP(parsed)) Ok(AddrComponent::TCP(parsed))
@ -265,9 +260,7 @@ impl ProtocolId {
ProtocolId::ONION => unimplemented!(), // TODO: ProtocolId::ONION => unimplemented!(), // TODO:
ProtocolId::QUIC => Ok(AddrComponent::QUIC), ProtocolId::QUIC => Ok(AddrComponent::QUIC),
ProtocolId::UTP => Ok(AddrComponent::UTP), ProtocolId::UTP => Ok(AddrComponent::UTP),
ProtocolId::UNIX => { ProtocolId::UNIX => Ok(AddrComponent::UNIX(a.to_owned())),
Ok(AddrComponent::UNIX(a.to_owned()))
}
ProtocolId::UDT => Ok(AddrComponent::UDT), ProtocolId::UDT => Ok(AddrComponent::UDT),
ProtocolId::HTTP => Ok(AddrComponent::HTTP), ProtocolId::HTTP => Ok(AddrComponent::HTTP),
ProtocolId::HTTPS => Ok(AddrComponent::HTTPS), ProtocolId::HTTPS => Ok(AddrComponent::HTTPS),
@ -346,13 +339,11 @@ impl AddrComponent {
let protocol_id = ProtocolId::from(proto_num)?; let protocol_id = ProtocolId::from(proto_num)?;
let (data_offset, data_size) = match protocol_id.size() { let (data_offset, data_size) = match protocol_id.size() {
ProtocolArgSize::Fixed { bytes } => { ProtocolArgSize::Fixed { bytes } => (0, bytes),
(0, bytes)
},
ProtocolArgSize::Variable => { ProtocolArgSize::Variable => {
let (data_size, varint_len) = u64::decode_var(&input[proto_id_len..]); // TODO: will panic if ID too large let (data_size, varint_len) = u64::decode_var(&input[proto_id_len..]); // TODO: will panic if ID too large
(varint_len, data_size as usize) (varint_len, data_size as usize)
}, }
}; };
let (data, rest) = input[proto_id_len..][data_offset..].split_at(data_size); let (data, rest) = input[proto_id_len..][data_offset..].split_at(data_size);
@ -360,7 +351,7 @@ impl AddrComponent {
let addr_component = match protocol_id { let addr_component = match protocol_id {
ProtocolId::IP4 => { ProtocolId::IP4 => {
AddrComponent::IP4(Ipv4Addr::new(data[0], data[1], data[2], data[3])) AddrComponent::IP4(Ipv4Addr::new(data[0], data[1], data[2], data[3]))
}, }
ProtocolId::IP6 => { ProtocolId::IP6 => {
let mut rdr = Cursor::new(data); let mut rdr = Cursor::new(data);
let mut seg = vec![]; let mut seg = vec![];
@ -369,22 +360,20 @@ impl AddrComponent {
seg.push(rdr.read_u16::<BigEndian>()?); seg.push(rdr.read_u16::<BigEndian>()?);
} }
let addr = Ipv6Addr::new(seg[0], let addr = Ipv6Addr::new(
seg[0],
seg[1], seg[1],
seg[2], seg[2],
seg[3], seg[3],
seg[4], seg[4],
seg[5], seg[5],
seg[6], seg[6],
seg[7]); seg[7],
);
AddrComponent::IP6(addr) AddrComponent::IP6(addr)
} }
ProtocolId::DNS4 => { ProtocolId::DNS4 => AddrComponent::DNS4(String::from_utf8(data.to_owned())?),
AddrComponent::DNS4(String::from_utf8(data.to_owned())?) ProtocolId::DNS6 => AddrComponent::DNS6(String::from_utf8(data.to_owned())?),
}
ProtocolId::DNS6 => {
AddrComponent::DNS6(String::from_utf8(data.to_owned())?)
}
ProtocolId::TCP => { ProtocolId::TCP => {
let mut rdr = Cursor::new(data); let mut rdr = Cursor::new(data);
let num = rdr.read_u16::<BigEndian>()?; let num = rdr.read_u16::<BigEndian>()?;
@ -405,9 +394,7 @@ impl AddrComponent {
let num = rdr.read_u16::<BigEndian>()?; let num = rdr.read_u16::<BigEndian>()?;
AddrComponent::SCTP(num) AddrComponent::SCTP(num)
} }
ProtocolId::UNIX => { ProtocolId::UNIX => AddrComponent::UNIX(String::from_utf8(data.to_owned())?),
AddrComponent::UNIX(String::from_utf8(data.to_owned())?)
}
ProtocolId::P2P => { ProtocolId::P2P => {
let bytes = Cid::from(data)?.to_bytes(); let bytes = Cid::from(data)?.to_bytes();
AddrComponent::P2P(bytes) AddrComponent::P2P(bytes)
@ -441,13 +428,13 @@ impl AddrComponent {
AddrComponent::IP4(addr) => { AddrComponent::IP4(addr) => {
out.write_all(&addr.octets())?; out.write_all(&addr.octets())?;
} }
AddrComponent::IP6(addr) => { AddrComponent::IP6(addr) => for &segment in &addr.segments() {
for &segment in &addr.segments() {
out.write_u16::<BigEndian>(segment)?; out.write_u16::<BigEndian>(segment)?;
} },
} AddrComponent::TCP(port)
AddrComponent::TCP(port) | AddrComponent::UDP(port) | AddrComponent::DCCP(port) | | AddrComponent::UDP(port)
AddrComponent::SCTP(port) => { | AddrComponent::DCCP(port)
| AddrComponent::SCTP(port) => {
out.write_u16::<BigEndian>(port)?; out.write_u16::<BigEndian>(port)?;
} }
AddrComponent::DNS4(s) | AddrComponent::DNS6(s) | AddrComponent::UNIX(s) => { AddrComponent::DNS4(s) | AddrComponent::DNS6(s) | AddrComponent::UNIX(s) => {
@ -461,18 +448,18 @@ impl AddrComponent {
} }
AddrComponent::ONION(_) => { AddrComponent::ONION(_) => {
unimplemented!() // TODO: unimplemented!() // TODO:
}, }
AddrComponent::QUIC | AddrComponent::QUIC
AddrComponent::UTP | | AddrComponent::UTP
AddrComponent::UDT | | AddrComponent::UDT
AddrComponent::HTTP | | AddrComponent::HTTP
AddrComponent::HTTPS | | AddrComponent::HTTPS
AddrComponent::WS | | AddrComponent::WS
AddrComponent::WSS | | AddrComponent::WSS
AddrComponent::Libp2pWebsocketStar | | AddrComponent::Libp2pWebsocketStar
AddrComponent::Libp2pWebrtcStar | | AddrComponent::Libp2pWebrtcStar
AddrComponent::Libp2pWebrtcDirect | | AddrComponent::Libp2pWebrtcDirect
AddrComponent::P2pCircuit => {} | AddrComponent::P2pCircuit => {}
}; };
Ok(()) Ok(())
@ -497,15 +484,15 @@ impl ToString for AddrComponent {
// TODO: meh for cloning // TODO: meh for cloning
let c = Cid::from(bytes.clone()).expect("cid is known to be valid"); let c = Cid::from(bytes.clone()).expect("cid is known to be valid");
format!("/p2p/{}", c) format!("/p2p/{}", c)
}, }
AddrComponent::IPFS(ref bytes) => { AddrComponent::IPFS(ref bytes) => {
// TODO: meh for cloning // TODO: meh for cloning
let c = Cid::from(bytes.clone()).expect("cid is known to be valid"); let c = Cid::from(bytes.clone()).expect("cid is known to be valid");
format!("/ipfs/{}", c) format!("/ipfs/{}", c)
}, }
AddrComponent::HTTP => format!("/http"), AddrComponent::HTTP => format!("/http"),
AddrComponent::HTTPS => format!("/https"), AddrComponent::HTTPS => format!("/https"),
AddrComponent::ONION(_) => unimplemented!(),//format!("/onion"), // TODO: AddrComponent::ONION(_) => unimplemented!(), //format!("/onion"), // TODO:
AddrComponent::QUIC => format!("/quic"), AddrComponent::QUIC => format!("/quic"),
AddrComponent::WS => format!("/ws"), AddrComponent::WS => format!("/ws"),
AddrComponent::WSS => format!("/wss"), AddrComponent::WSS => format!("/wss"),

View File

@ -1,9 +1,9 @@
extern crate multiaddr;
extern crate data_encoding; extern crate data_encoding;
extern crate multiaddr;
use data_encoding::hex; use data_encoding::hex;
use multiaddr::*; use multiaddr::*;
use std::net::{SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr}; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
#[test] #[test]
fn protocol_to_code() { fn protocol_to_code() {
@ -15,11 +15,16 @@ fn protocol_to_name() {
assert_eq!(ProtocolId::TCP.to_string(), "tcp"); assert_eq!(ProtocolId::TCP.to_string(), "tcp");
} }
fn assert_bytes(source: &str, target: &str, protocols: Vec<ProtocolId>) -> () { fn assert_bytes(source: &str, target: &str, protocols: Vec<ProtocolId>) -> () {
let address = source.parse::<Multiaddr>().unwrap(); let address = source.parse::<Multiaddr>().unwrap();
assert_eq!(hex::encode(address.to_bytes().as_slice()), target); assert_eq!(hex::encode(address.to_bytes().as_slice()), target);
assert_eq!(address.iter().map(|addr| addr.protocol_id()).collect::<Vec<_>>(), protocols); assert_eq!(
address
.iter()
.map(|addr| addr.protocol_id())
.collect::<Vec<_>>(),
protocols
);
} }
fn ma_valid(source: &str, target: &str, protocols: Vec<ProtocolId>) -> () { fn ma_valid(source: &str, target: &str, protocols: Vec<ProtocolId>) -> () {
assert_bytes(source, target, protocols); assert_bytes(source, target, protocols);
@ -45,9 +50,11 @@ fn construct_success() {
ma_valid("/ip4/1.2.3.4", "0401020304", vec![IP4]); ma_valid("/ip4/1.2.3.4", "0401020304", vec![IP4]);
ma_valid("/ip4/0.0.0.0", "0400000000", vec![IP4]); ma_valid("/ip4/0.0.0.0", "0400000000", vec![IP4]);
ma_valid("/ip6/::1", "2900000000000000000000000000000001", vec![IP6]); ma_valid("/ip6/::1", "2900000000000000000000000000000001", vec![IP6]);
ma_valid("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21", ma_valid(
"/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21",
"29260100094F819700803ECA6566E80C21", "29260100094F819700803ECA6566E80C21",
vec![IP6]); vec![IP6],
);
ma_valid("/udp/0", "110000", vec![UDP]); ma_valid("/udp/0", "110000", vec![UDP]);
ma_valid("/tcp/0", "060000", vec![TCP]); ma_valid("/tcp/0", "060000", vec![TCP]);
ma_valid("/sctp/0", "84010000", vec![SCTP]); ma_valid("/sctp/0", "84010000", vec![SCTP]);
@ -56,59 +63,80 @@ fn construct_success() {
ma_valid("/sctp/1234", "840104D2", vec![SCTP]); ma_valid("/sctp/1234", "840104D2", vec![SCTP]);
ma_valid("/udp/65535", "11FFFF", vec![UDP]); ma_valid("/udp/65535", "11FFFF", vec![UDP]);
ma_valid("/tcp/65535", "06FFFF", vec![TCP]); ma_valid("/tcp/65535", "06FFFF", vec![TCP]);
ma_valid("/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", ma_valid(
"/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
"A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B", "A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
vec![IPFS]); vec![IPFS],
);
ma_valid("/udp/1234/sctp/1234", "1104D2840104D2", vec![UDP, SCTP]); ma_valid("/udp/1234/sctp/1234", "1104D2840104D2", vec![UDP, SCTP]);
ma_valid("/udp/1234/udt", "1104D2AD02", vec![UDP, UDT]); ma_valid("/udp/1234/udt", "1104D2AD02", vec![UDP, UDT]);
ma_valid("/udp/1234/utp", "1104D2AE02", vec![UDP, UTP]); ma_valid("/udp/1234/utp", "1104D2AE02", vec![UDP, UTP]);
ma_valid("/tcp/1234/http", "0604D2E003", vec![TCP, HTTP]); ma_valid("/tcp/1234/http", "0604D2E003", vec![TCP, HTTP]);
ma_valid("/tcp/1234/https", "0604D2BB03", vec![TCP, HTTPS]); ma_valid("/tcp/1234/https", "0604D2BB03", vec![TCP, HTTPS]);
ma_valid("/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", ma_valid(
"/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
"A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2", "A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2",
vec![IPFS, TCP]); vec![IPFS, TCP],
ma_valid("/ip4/127.0.0.1/udp/1234", );
ma_valid(
"/ip4/127.0.0.1/udp/1234",
"047F0000011104D2", "047F0000011104D2",
vec![IP4, UDP]); vec![IP4, UDP],
);
ma_valid("/ip4/127.0.0.1/udp/0", "047F000001110000", vec![IP4, UDP]); ma_valid("/ip4/127.0.0.1/udp/0", "047F000001110000", vec![IP4, UDP]);
ma_valid("/ip4/127.0.0.1/tcp/1234", ma_valid(
"/ip4/127.0.0.1/tcp/1234",
"047F0000010604D2", "047F0000010604D2",
vec![IP4, TCP]); vec![IP4, TCP],
ma_valid("/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", );
ma_valid(
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
"047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B", "047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
vec![IP4, IPFS]); vec![IP4, IPFS],
ma_valid("/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", );
ma_valid(
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
"047F000001A503221220D52EBB89D85B02A284948203A\ "047F000001A503221220D52EBB89D85B02A284948203A\
62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2", 62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2",
vec![IP4, IPFS, TCP]); vec![IP4, IPFS, TCP],
);
// /unix/a/b/c/d/e, // /unix/a/b/c/d/e,
// /unix/stdio, // /unix/stdio,
// /ip4/1.2.3.4/tcp/80/unix/a/b/c/d/e/f, // /ip4/1.2.3.4/tcp/80/unix/a/b/c/d/e/f,
// /ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234/unix/stdio // /ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234/unix/stdio
ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:\ ma_valid(
"/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:\
7095/tcp/8000/ws/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", 7095/tcp/8000/ws/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
"29200108A07AC542013AC986FFFE317095061F40DD03A5\ "29200108A07AC542013AC986FFFE317095061F40DD03A5\
03221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B", 03221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
vec![IP6, TCP, WS, IPFS]); vec![IP6, TCP, WS, IPFS],
ma_valid("/p2p-webrtc-star/ip4/127.0.0.\ );
ma_valid(
"/p2p-webrtc-star/ip4/127.0.0.\
1/tcp/9090/ws/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", 1/tcp/9090/ws/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
"9302047F000001062382DD03A503221220D52EBB89D85B\ "9302047F000001062382DD03A503221220D52EBB89D85B\
02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B", 02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
vec![Libp2pWebrtcStar, IP4, TCP, WS, IPFS]); vec![Libp2pWebrtcStar, IP4, TCP, WS, IPFS],
ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:\ );
ma_valid(
"/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:\
7095/tcp/8000/wss/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", 7095/tcp/8000/wss/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
"29200108A07AC542013AC986FFFE317095061F40DE03A503221220D52EBB8\ "29200108A07AC542013AC986FFFE317095061F40DE03A503221220D52EBB8\
9D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B", 9D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
vec![IP6, TCP, WSS, IPFS]); vec![IP6, TCP, WSS, IPFS],
ma_valid("/ip4/127.0.0.1/tcp/9090/p2p-circuit/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", );
ma_valid(
"/ip4/127.0.0.1/tcp/9090/p2p-circuit/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
"047F000001062382A202A503221220D52EBB89D85B\ "047F000001062382A202A503221220D52EBB89D85B\
02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B", 02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
vec![IP4, TCP, P2pCircuit, IPFS]); vec![IP4, TCP, P2pCircuit, IPFS],
);
} }
#[test] #[test]
fn construct_fail() { fn construct_fail() {
let addresses = ["/ip4", let addresses = [
"/ip4",
"/ip4/::1", "/ip4/::1",
"/ip4/fdpsofodsajfdoisa", "/ip4/fdpsofodsajfdoisa",
"/ip6", "/ip6",
@ -132,40 +160,59 @@ fn construct_fail() {
"/ip4/127.0.0.1/tcp", "/ip4/127.0.0.1/tcp",
"/ip4/127.0.0.1/ipfs", "/ip4/127.0.0.1/ipfs",
"/ip4/127.0.0.1/ipfs/tcp", "/ip4/127.0.0.1/ipfs/tcp",
"/p2p-circuit/50"]; "/p2p-circuit/50",
];
for address in &addresses { for address in &addresses {
assert!(address.parse::<Multiaddr>().is_err(), address.to_string()); assert!(address.parse::<Multiaddr>().is_err(), address.to_string());
} }
} }
#[test] #[test]
fn to_multiaddr() { fn to_multiaddr() {
assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_multiaddr().unwrap(), assert_eq!(
"/ip4/127.0.0.1".parse::<Multiaddr>().unwrap()); Ipv4Addr::new(127, 0, 0, 1).to_multiaddr().unwrap(),
assert_eq!(Ipv6Addr::new(0x2601, 0x9, 0x4f81, 0x9700, 0x803e, 0xca65, 0x66e8, 0xc21) "/ip4/127.0.0.1".parse::<Multiaddr>().unwrap()
);
assert_eq!(
Ipv6Addr::new(0x2601, 0x9, 0x4f81, 0x9700, 0x803e, 0xca65, 0x66e8, 0xc21)
.to_multiaddr() .to_multiaddr()
.unwrap(), .unwrap(),
"/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".parse::<Multiaddr>().unwrap()); "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21"
assert_eq!("/ip4/127.0.0.1/tcp/1234".to_string().to_multiaddr().unwrap(), .parse::<Multiaddr>()
"/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap()); .unwrap()
assert_eq!("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".to_multiaddr().unwrap(), );
"/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".parse::<Multiaddr>().unwrap()); assert_eq!(
assert_eq!(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 1234).to_multiaddr().unwrap(), "/ip4/127.0.0.1/tcp/1234"
"/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap()); .to_string()
assert_eq!(SocketAddrV6::new(Ipv6Addr::new(0x2601, .to_multiaddr()
0x9, .unwrap(),
0x4f81, "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap()
0x9700, );
0x803e, assert_eq!(
0xca65, "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21"
0x66e8, .to_multiaddr()
0xc21), .unwrap(),
"/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21"
.parse::<Multiaddr>()
.unwrap()
);
assert_eq!(
SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 1234)
.to_multiaddr()
.unwrap(),
"/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap()
);
assert_eq!(
SocketAddrV6::new(
Ipv6Addr::new(0x2601, 0x9, 0x4f81, 0x9700, 0x803e, 0xca65, 0x66e8, 0xc21),
1234, 1234,
0, 0,
0) 0
.to_multiaddr() ).to_multiaddr()
.unwrap(), .unwrap(),
"/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21/tcp/1234".parse::<Multiaddr>().unwrap()); "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21/tcp/1234"
.parse::<Multiaddr>()
.unwrap()
);
} }

View File

@ -1,17 +0,0 @@
verbose=false
max_width=100
comment_width=100
tab_spaces=4
fn_call_width=100
struct_lit_width=32
fn_call_style="Visual"
single_line_if_else_max_width=100
trailing_comma="Vertical"
chain_indent="Visual"
chain_one_line_max=100
reorder_imports=true
format_strings=false
hard_tabs=true
wrap_match_arms=false
error_on_line_overflow=false
where_style="Legacy"

View File

@ -39,16 +39,24 @@ use std::io::Error as IoError;
use std::io::ErrorKind as IoErrorKind; use std::io::ErrorKind as IoErrorKind;
use std::io::{Read, Write}; use std::io::{Read, Write};
use bytes::{Buf, IntoBuf}; use bytes::{Buf, IntoBuf};
use futures::{Async, AsyncSink, Poll, Stream, Sink}; use futures::{Async, AsyncSink, Poll, Sink, Stream};
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
/// Wraps around a `Stream + Sink` whose items are buffers. Implements `AsyncRead` and `AsyncWrite`. /// Wraps around a `Stream + Sink` whose items are buffers. Implements `AsyncRead` and `AsyncWrite`.
pub struct RwStreamSink<S> where S: Stream, S::Item: IntoBuf { pub struct RwStreamSink<S>
where
S: Stream,
S::Item: IntoBuf,
{
inner: S, inner: S,
current_item: Option<<S::Item as IntoBuf>::Buf>, current_item: Option<<S::Item as IntoBuf>::Buf>,
} }
impl<S> RwStreamSink<S> where S: Stream, S::Item: IntoBuf { impl<S> RwStreamSink<S>
where
S: Stream,
S::Item: IntoBuf,
{
/// Wraps around `inner`. /// Wraps around `inner`.
#[inline] #[inline]
pub fn new(inner: S) -> RwStreamSink<S> { pub fn new(inner: S) -> RwStreamSink<S> {
@ -60,7 +68,8 @@ impl<S> RwStreamSink<S> where S: Stream, S::Item: IntoBuf {
} }
impl<S> Read for RwStreamSink<S> impl<S> Read for RwStreamSink<S>
where S: Stream<Error = IoError>, where
S: Stream<Error = IoError>,
S::Item: IntoBuf, S::Item: IntoBuf,
{ {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, IoError> { fn read(&mut self, buf: &mut [u8]) -> Result<usize, IoError> {
@ -82,14 +91,14 @@ impl<S> Read for RwStreamSink<S>
} else { } else {
return Ok(written); return Ok(written);
} }
}, }
Err(err) => { Err(err) => {
if written == 0 { if written == 0 {
return Err(err); return Err(err);
} else { } else {
return Ok(written); return Ok(written);
} }
}, }
}; };
} }
@ -103,22 +112,27 @@ impl<S> Read for RwStreamSink<S>
return Ok(written); return Ok(written);
} }
current_item.by_ref().take(to_copy).copy_to_slice(&mut buf[written..(written+to_copy)]); current_item
.by_ref()
.take(to_copy)
.copy_to_slice(&mut buf[written..(written + to_copy)]);
written += to_copy; written += to_copy;
} }
} }
} }
impl<S> AsyncRead for RwStreamSink<S> impl<S> AsyncRead for RwStreamSink<S>
where S: Stream<Error = IoError>, where
S::Item: IntoBuf S: Stream<Error = IoError>,
S::Item: IntoBuf,
{ {
} }
impl<S> Write for RwStreamSink<S> impl<S> Write for RwStreamSink<S>
where S: Stream + Sink<SinkError = IoError>, where
S: Stream + Sink<SinkError = IoError>,
S::SinkItem: for<'r> From<&'r [u8]>, S::SinkItem: for<'r> From<&'r [u8]>,
S::Item: IntoBuf S::Item: IntoBuf,
{ {
#[inline] #[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize, IoError> { fn write(&mut self, buf: &[u8]) -> Result<usize, IoError> {
@ -137,9 +151,10 @@ impl<S> Write for RwStreamSink<S>
} }
impl<S> AsyncWrite for RwStreamSink<S> impl<S> AsyncWrite for RwStreamSink<S>
where S: Stream + Sink<SinkError = IoError>, where
S: Stream + Sink<SinkError = IoError>,
S::SinkItem: for<'r> From<&'r [u8]>, S::SinkItem: for<'r> From<&'r [u8]>,
S::Item: IntoBuf S::Item: IntoBuf,
{ {
#[inline] #[inline]
fn shutdown(&mut self) -> Poll<(), IoError> { fn shutdown(&mut self) -> Poll<(), IoError> {
@ -150,24 +165,33 @@ impl<S> AsyncWrite for RwStreamSink<S>
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use bytes::Bytes; use bytes::Bytes;
use futures::{Sink, Stream, Future, Poll, StartSend}; use futures::{Future, Poll, Sink, StartSend, Stream};
use futures::sync::mpsc::channel; use futures::sync::mpsc::channel;
use std::io::Read; use std::io::Read;
use RwStreamSink; use RwStreamSink;
// This struct merges a stream and a sink and is quite useful for tests. // This struct merges a stream and a sink and is quite useful for tests.
struct Wrapper<St, Si>(St, Si); struct Wrapper<St, Si>(St, Si);
impl<St, Si> Stream for Wrapper<St, Si> where St: Stream { impl<St, Si> Stream for Wrapper<St, Si>
where
St: Stream,
{
type Item = St::Item; type Item = St::Item;
type Error = St::Error; type Error = St::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
self.0.poll() self.0.poll()
} }
} }
impl<St, Si> Sink for Wrapper<St, Si> where Si: Sink { impl<St, Si> Sink for Wrapper<St, Si>
where
Si: Sink,
{
type SinkItem = Si::SinkItem; type SinkItem = Si::SinkItem;
type SinkError = Si::SinkError; type SinkError = Si::SinkError;
fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> { fn start_send(
&mut self,
item: Self::SinkItem,
) -> StartSend<Self::SinkItem, Self::SinkError> {
self.1.start_send(item) self.1.start_send(item)
} }
fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
@ -185,7 +209,8 @@ mod tests {
tx2.send(Bytes::from("hel")) tx2.send(Bytes::from("hel"))
.and_then(|tx| tx.send(Bytes::from("lo wor"))) .and_then(|tx| tx.send(Bytes::from("lo wor")))
.and_then(|tx| tx.send(Bytes::from("ld"))) .and_then(|tx| tx.send(Bytes::from("ld")))
.wait().unwrap(); .wait()
.unwrap();
let mut data1 = [0u8; 5]; let mut data1 = [0u8; 5];
assert_eq!(wrapper.read(&mut data1).unwrap(), 5); assert_eq!(wrapper.read(&mut data1).unwrap(), 5);

View File

@ -23,20 +23,20 @@
//! Encoding and decoding state machines for protobuf varints //! Encoding and decoding state machines for protobuf varints
// TODO: Non-allocating `BigUint`? // TODO: Non-allocating `BigUint`?
extern crate bytes;
#[macro_use]
extern crate error_chain;
extern crate futures;
extern crate num_bigint; extern crate num_bigint;
extern crate num_traits; extern crate num_traits;
extern crate tokio_io; extern crate tokio_io;
extern crate bytes;
extern crate futures;
#[macro_use]
extern crate error_chain;
use bytes::{BufMut, Bytes, BytesMut, IntoBuf}; use bytes::{BufMut, Bytes, BytesMut, IntoBuf};
use futures::{Poll, Async}; use futures::{Async, Poll};
use num_bigint::BigUint; use num_bigint::BigUint;
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Encoder, Decoder}; use tokio_io::codec::{Decoder, Encoder};
use std::io; use std::io;
use std::io::prelude::*; use std::io::prelude::*;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -143,7 +143,10 @@ macro_rules! impl_decoderstate {
($t:ty, $make_fn:expr, $shift_fn:expr) => { ($t:ty, $make_fn:expr, $shift_fn:expr) => {
impl DecoderHelper for $t { impl DecoderHelper for $t {
#[inline] #[inline]
fn decode_one(decoder: &mut DecoderState<Self>, byte: u8) -> ::errors::Result<Option<$t>> { fn decode_one(
decoder: &mut DecoderState<Self>,
byte: u8,
) -> ::errors::Result<Option<$t>> {
let res = decoder.accumulator.take().and_then(|accumulator| { let res = decoder.accumulator.take().and_then(|accumulator| {
let out = accumulator | match $shift_fn( let out = accumulator | match $shift_fn(
$make_fn(byte & 0x7F), $make_fn(byte & 0x7F),
@ -439,16 +442,14 @@ impl<T> Decoder for VarintCodec<T> {
self.inner = VarintCodecInner::WaitingForData(len); self.inner = VarintCodecInner::WaitingForData(len);
return Ok(None); return Ok(None);
} }
}, }
VarintCodecInner::WaitingForLen(mut decoder) => { VarintCodecInner::WaitingForLen(mut decoder) => match decoder.decode(src)? {
match decoder.decode(src)? {
None => { None => {
self.inner = VarintCodecInner::WaitingForLen(decoder); self.inner = VarintCodecInner::WaitingForLen(decoder);
return Ok(None); return Ok(None);
}, }
Some(len) => { Some(len) => {
self.inner = VarintCodecInner::WaitingForData(len); self.inner = VarintCodecInner::WaitingForData(len);
},
} }
}, },
VarintCodecInner::Poisoned => panic!("varint codec was poisoned"), VarintCodecInner::Poisoned => panic!("varint codec was poisoned"),
@ -458,7 +459,8 @@ impl<T> Decoder for VarintCodec<T> {
} }
impl<D> Encoder for VarintCodec<D> impl<D> Encoder for VarintCodec<D>
where D: IntoBuf + AsRef<[u8]>, where
D: IntoBuf + AsRef<[u8]>,
{ {
type Item = D; type Item = D;
type Error = io::Error; type Error = io::Error;
@ -507,7 +509,7 @@ pub fn encode<T: EncoderHelper + Bits>(input: T) -> Bytes {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{decode, VarintDecoder, EncoderState}; use super::{decode, EncoderState, VarintDecoder};
use tokio_io::codec::FramedRead; use tokio_io::codec::FramedRead;
use num_bigint::BigUint; use num_bigint::BigUint;
use futures::{Future, Stream}; use futures::{Future, Stream};