mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-22 22:31:33 +00:00
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:
@ -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
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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 {
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
@ -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| {
|
||||||
|
@ -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 = _>>
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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),
|
||||||
|
@ -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]
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@ -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,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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!());
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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());
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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();
|
||||||
|
@ -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()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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()))
|
||||||
|
@ -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())
|
||||||
})
|
})
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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())),
|
||||||
|
@ -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()
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
|
@ -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)
|
||||||
});
|
});
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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"),
|
||||||
|
@ -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()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
17
rustfmt.toml
17
rustfmt.toml
@ -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"
|
|
@ -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);
|
||||||
|
@ -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};
|
||||||
|
Reference in New Issue
Block a user