2017-11-07 18:25:10 +01:00
|
|
|
// Copyright 2017 Parity Technologies (UK) Ltd.
|
2018-03-07 16:20:55 +01:00
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
// copy of this software and associated documentation files (the "Software"),
|
|
|
|
// to deal in the Software without restriction, including without limitation
|
|
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
2017-11-08 10:11:58 +01:00
|
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
|
|
//
|
2018-03-07 16:20:55 +01:00
|
|
|
// The above copyright notice and this permission notice shall be included in
|
2017-11-08 10:11:58 +01:00
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
2018-03-07 16:20:55 +01:00
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
2017-11-08 10:11:58 +01:00
|
|
|
// DEALINGS IN THE SOFTWARE.
|
2017-11-07 18:25:10 +01:00
|
|
|
|
|
|
|
//! Contains the `dialer_select_proto` code, which allows selecting a protocol thanks to
|
|
|
|
//! `multistream-select` for the dialer.
|
|
|
|
|
2019-01-09 15:09:35 +01:00
|
|
|
use futures::{future::Either, prelude::*, stream::StreamFuture};
|
|
|
|
use crate::protocol::{
|
|
|
|
Dialer,
|
|
|
|
DialerFuture,
|
|
|
|
DialerToListenerMessage,
|
|
|
|
ListenerToDialerMessage
|
|
|
|
};
|
2018-12-11 10:45:28 +01:00
|
|
|
use log::trace;
|
2018-08-30 23:25:16 +02:00
|
|
|
use std::mem;
|
|
|
|
use tokio_io::{AsyncRead, AsyncWrite};
|
2019-03-19 17:27:30 +01:00
|
|
|
use crate::{Negotiated, ProtocolChoiceError};
|
2017-11-05 12:21:34 +01:00
|
|
|
|
2018-08-30 23:25:16 +02:00
|
|
|
/// Future, returned by `dialer_select_proto`, which selects a protocol and dialer
|
|
|
|
/// either sequentially of by considering all protocols in parallel.
|
2018-12-11 15:13:10 +01:00
|
|
|
pub type DialerSelectFuture<R, I> = Either<DialerSelectSeq<R, I>, DialerSelectPar<R, I>>;
|
2017-11-05 12:21:34 +01:00
|
|
|
|
|
|
|
/// Helps selecting a protocol amongst the ones supported.
|
|
|
|
///
|
|
|
|
/// This function expects a socket and a list of protocols. It uses the `multistream-select`
|
|
|
|
/// protocol to choose with the remote a protocol amongst the ones produced by the iterator.
|
|
|
|
///
|
|
|
|
/// The iterator must produce a tuple of a protocol name advertised to the remote, a function that
|
|
|
|
/// checks whether a protocol name matches the protocol, and a protocol "identifier" of type `P`
|
|
|
|
/// (you decide what `P` is). The parameters of the match function are the name proposed by the
|
|
|
|
/// remote, and the protocol name that we passed (so that you don't have to clone the name). On
|
|
|
|
/// success, the function returns the identifier (of type `P`), plus the socket which now uses that
|
|
|
|
/// chosen protocol.
|
2018-12-11 15:13:10 +01:00
|
|
|
pub fn dialer_select_proto<R, I>(inner: R, protocols: I) -> DialerSelectFuture<R, I::IntoIter>
|
2018-03-07 16:20:55 +01:00
|
|
|
where
|
2018-08-14 15:23:30 +02:00
|
|
|
R: AsyncRead + AsyncWrite,
|
2018-12-11 15:13:10 +01:00
|
|
|
I: IntoIterator,
|
|
|
|
I::Item: AsRef<[u8]>
|
2017-11-05 12:21:34 +01:00
|
|
|
{
|
2018-12-11 15:13:10 +01:00
|
|
|
let iter = protocols.into_iter();
|
2018-03-07 16:20:55 +01:00
|
|
|
// We choose between the "serial" and "parallel" strategies based on the number of protocols.
|
2018-12-11 15:13:10 +01:00
|
|
|
if iter.size_hint().1.map(|n| n <= 3).unwrap_or(false) {
|
|
|
|
Either::A(dialer_select_proto_serial(inner, iter))
|
2018-03-07 16:20:55 +01:00
|
|
|
} else {
|
2018-12-11 15:13:10 +01:00
|
|
|
Either::B(dialer_select_proto_parallel(inner, iter))
|
2018-03-07 16:20:55 +01:00
|
|
|
}
|
2017-11-05 12:21:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Helps selecting a protocol amongst the ones supported.
|
|
|
|
///
|
|
|
|
/// Same as `dialer_select_proto`. Tries protocols one by one. The iterator doesn't need to produce
|
|
|
|
/// match functions, because it's not needed.
|
2019-01-09 15:09:35 +01:00
|
|
|
pub fn dialer_select_proto_serial<R, I>(inner: R, protocols: I) -> DialerSelectSeq<R, I::IntoIter>
|
2018-03-07 16:20:55 +01:00
|
|
|
where
|
2018-08-14 15:23:30 +02:00
|
|
|
R: AsyncRead + AsyncWrite,
|
2019-01-09 15:09:35 +01:00
|
|
|
I: IntoIterator,
|
2018-12-11 15:13:10 +01:00
|
|
|
I::Item: AsRef<[u8]>
|
2017-11-05 12:21:34 +01:00
|
|
|
{
|
2019-01-09 15:09:35 +01:00
|
|
|
let protocols = protocols.into_iter();
|
2018-08-30 23:25:16 +02:00
|
|
|
DialerSelectSeq {
|
2019-01-30 15:41:54 +01:00
|
|
|
inner: DialerSelectSeqState::AwaitDialer { dialer_fut: Dialer::dial(inner), protocols }
|
2018-08-30 23:25:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Future, returned by `dialer_select_proto_serial` which selects a protocol
|
|
|
|
/// and dialer sequentially.
|
2019-01-09 15:09:35 +01:00
|
|
|
pub struct DialerSelectSeq<R, I>
|
|
|
|
where
|
|
|
|
R: AsyncRead + AsyncWrite,
|
|
|
|
I: Iterator,
|
|
|
|
I::Item: AsRef<[u8]>
|
|
|
|
{
|
2018-12-11 15:13:10 +01:00
|
|
|
inner: DialerSelectSeqState<R, I>
|
2018-08-30 23:25:16 +02:00
|
|
|
}
|
|
|
|
|
2019-01-09 15:09:35 +01:00
|
|
|
enum DialerSelectSeqState<R, I>
|
|
|
|
where
|
|
|
|
R: AsyncRead + AsyncWrite,
|
|
|
|
I: Iterator,
|
|
|
|
I::Item: AsRef<[u8]>
|
|
|
|
{
|
2018-08-30 23:25:16 +02:00
|
|
|
AwaitDialer {
|
2019-01-09 15:09:35 +01:00
|
|
|
dialer_fut: DialerFuture<R, I::Item>,
|
2018-08-30 23:25:16 +02:00
|
|
|
protocols: I
|
|
|
|
},
|
|
|
|
NextProtocol {
|
2019-01-09 15:09:35 +01:00
|
|
|
dialer: Dialer<R, I::Item>,
|
|
|
|
proto_name: I::Item,
|
2018-08-30 23:25:16 +02:00
|
|
|
protocols: I
|
|
|
|
},
|
2019-01-09 15:09:35 +01:00
|
|
|
FlushProtocol {
|
|
|
|
dialer: Dialer<R, I::Item>,
|
2018-12-11 15:13:10 +01:00
|
|
|
proto_name: I::Item,
|
2018-08-30 23:25:16 +02:00
|
|
|
protocols: I
|
|
|
|
},
|
|
|
|
AwaitProtocol {
|
2019-01-09 15:09:35 +01:00
|
|
|
stream: StreamFuture<Dialer<R, I::Item>>,
|
2018-12-11 15:13:10 +01:00
|
|
|
proto_name: I::Item,
|
2018-08-30 23:25:16 +02:00
|
|
|
protocols: I
|
|
|
|
},
|
|
|
|
Undefined
|
|
|
|
}
|
|
|
|
|
2018-12-11 15:13:10 +01:00
|
|
|
impl<R, I> Future for DialerSelectSeq<R, I>
|
2018-08-30 23:25:16 +02:00
|
|
|
where
|
|
|
|
R: AsyncRead + AsyncWrite,
|
2019-01-09 15:09:35 +01:00
|
|
|
I: Iterator,
|
|
|
|
I::Item: AsRef<[u8]> + Clone
|
2018-08-30 23:25:16 +02:00
|
|
|
{
|
2019-03-19 17:27:30 +01:00
|
|
|
type Item = (I::Item, Negotiated<R>);
|
2018-08-30 23:25:16 +02:00
|
|
|
type Error = ProtocolChoiceError;
|
|
|
|
|
|
|
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
|
|
loop {
|
|
|
|
match mem::replace(&mut self.inner, DialerSelectSeqState::Undefined) {
|
2019-01-09 15:09:35 +01:00
|
|
|
DialerSelectSeqState::AwaitDialer { mut dialer_fut, mut protocols } => {
|
2018-08-30 23:25:16 +02:00
|
|
|
let dialer = match dialer_fut.poll()? {
|
|
|
|
Async::Ready(d) => d,
|
|
|
|
Async::NotReady => {
|
|
|
|
self.inner = DialerSelectSeqState::AwaitDialer { dialer_fut, protocols };
|
|
|
|
return Ok(Async::NotReady)
|
2017-11-05 12:21:34 +01:00
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
};
|
2019-01-09 15:09:35 +01:00
|
|
|
let proto_name = protocols.next().ok_or(ProtocolChoiceError::NoProtocolFound)?;
|
|
|
|
self.inner = DialerSelectSeqState::NextProtocol {
|
|
|
|
dialer,
|
|
|
|
protocols,
|
|
|
|
proto_name
|
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
}
|
2019-01-09 15:09:35 +01:00
|
|
|
DialerSelectSeqState::NextProtocol { mut dialer, protocols, proto_name } => {
|
|
|
|
trace!("sending {:?}", proto_name.as_ref());
|
2018-08-30 23:25:16 +02:00
|
|
|
let req = DialerToListenerMessage::ProtocolRequest {
|
2019-01-09 15:09:35 +01:00
|
|
|
name: proto_name.clone()
|
2018-08-30 23:25:16 +02:00
|
|
|
};
|
2019-01-09 15:09:35 +01:00
|
|
|
match dialer.start_send(req)? {
|
|
|
|
AsyncSink::Ready => {
|
|
|
|
self.inner = DialerSelectSeqState::FlushProtocol {
|
|
|
|
dialer,
|
|
|
|
proto_name,
|
|
|
|
protocols
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AsyncSink::NotReady(_) => {
|
|
|
|
self.inner = DialerSelectSeqState::NextProtocol {
|
|
|
|
dialer,
|
|
|
|
protocols,
|
|
|
|
proto_name
|
|
|
|
};
|
|
|
|
return Ok(Async::NotReady)
|
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
}
|
|
|
|
}
|
2019-01-09 15:09:35 +01:00
|
|
|
DialerSelectSeqState::FlushProtocol { mut dialer, proto_name, protocols } => {
|
|
|
|
match dialer.poll_complete()? {
|
|
|
|
Async::Ready(()) => {
|
|
|
|
let stream = dialer.into_future();
|
|
|
|
self.inner = DialerSelectSeqState::AwaitProtocol {
|
|
|
|
stream,
|
|
|
|
proto_name,
|
|
|
|
protocols
|
|
|
|
}
|
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
Async::NotReady => {
|
2019-01-09 15:09:35 +01:00
|
|
|
self.inner = DialerSelectSeqState::FlushProtocol {
|
|
|
|
dialer,
|
2018-08-30 23:25:16 +02:00
|
|
|
proto_name,
|
|
|
|
protocols
|
|
|
|
};
|
|
|
|
return Ok(Async::NotReady)
|
|
|
|
}
|
2019-01-09 15:09:35 +01:00
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
}
|
2019-01-09 15:09:35 +01:00
|
|
|
DialerSelectSeqState::AwaitProtocol { mut stream, proto_name, mut protocols } => {
|
2018-08-30 23:25:16 +02:00
|
|
|
let (m, r) = match stream.poll() {
|
|
|
|
Ok(Async::Ready(x)) => x,
|
|
|
|
Ok(Async::NotReady) => {
|
|
|
|
self.inner = DialerSelectSeqState::AwaitProtocol {
|
|
|
|
stream,
|
|
|
|
proto_name,
|
|
|
|
protocols
|
|
|
|
};
|
|
|
|
return Ok(Async::NotReady)
|
|
|
|
}
|
|
|
|
Err((e, _)) => return Err(ProtocolChoiceError::from(e))
|
|
|
|
};
|
|
|
|
trace!("received {:?}", m);
|
|
|
|
match m.ok_or(ProtocolChoiceError::UnexpectedMessage)? {
|
2018-12-11 15:13:10 +01:00
|
|
|
ListenerToDialerMessage::ProtocolAck { ref name }
|
|
|
|
if name.as_ref() == proto_name.as_ref() =>
|
|
|
|
{
|
2019-03-19 17:27:30 +01:00
|
|
|
return Ok(Async::Ready((proto_name, Negotiated(r.into_inner()))))
|
2019-01-09 15:09:35 +01:00
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
ListenerToDialerMessage::NotAvailable => {
|
2019-01-09 15:09:35 +01:00
|
|
|
let proto_name = protocols.next()
|
|
|
|
.ok_or(ProtocolChoiceError::NoProtocolFound)?;
|
|
|
|
self.inner = DialerSelectSeqState::NextProtocol {
|
|
|
|
dialer: r,
|
|
|
|
protocols,
|
|
|
|
proto_name
|
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
}
|
|
|
|
_ => return Err(ProtocolChoiceError::UnexpectedMessage)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DialerSelectSeqState::Undefined =>
|
|
|
|
panic!("DialerSelectSeqState::poll called after completion")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-05 12:21:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Helps selecting a protocol amongst the ones supported.
|
|
|
|
///
|
|
|
|
/// Same as `dialer_select_proto`. Queries the list of supported protocols from the remote, then
|
|
|
|
/// chooses the most appropriate one.
|
2019-01-09 15:09:35 +01:00
|
|
|
pub fn dialer_select_proto_parallel<R, I>(inner: R, protocols: I) -> DialerSelectPar<R, I::IntoIter>
|
2018-03-07 16:20:55 +01:00
|
|
|
where
|
2019-01-09 15:09:35 +01:00
|
|
|
R: AsyncRead + AsyncWrite,
|
|
|
|
I: IntoIterator,
|
|
|
|
I::Item: AsRef<[u8]>
|
2017-11-05 12:21:34 +01:00
|
|
|
{
|
2019-01-09 15:09:35 +01:00
|
|
|
let protocols = protocols.into_iter();
|
2018-08-30 23:25:16 +02:00
|
|
|
DialerSelectPar {
|
2019-01-30 15:41:54 +01:00
|
|
|
inner: DialerSelectParState::AwaitDialer { dialer_fut: Dialer::dial(inner), protocols }
|
2018-08-30 23:25:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Future, returned by `dialer_select_proto_parallel`, which selects a protocol and dialer in
|
|
|
|
/// parellel, by first requesting the liste of protocols supported by the remote endpoint and
|
|
|
|
/// then selecting the most appropriate one by applying a match predicate to the result.
|
2019-01-09 15:09:35 +01:00
|
|
|
pub struct DialerSelectPar<R, I>
|
|
|
|
where
|
|
|
|
R: AsyncRead + AsyncWrite,
|
|
|
|
I: Iterator,
|
|
|
|
I::Item: AsRef<[u8]>
|
|
|
|
{
|
2018-12-11 15:13:10 +01:00
|
|
|
inner: DialerSelectParState<R, I>
|
2018-08-30 23:25:16 +02:00
|
|
|
}
|
|
|
|
|
2019-01-09 15:09:35 +01:00
|
|
|
enum DialerSelectParState<R, I>
|
|
|
|
where
|
|
|
|
R: AsyncRead + AsyncWrite,
|
|
|
|
I: Iterator,
|
|
|
|
I::Item: AsRef<[u8]>
|
|
|
|
{
|
2018-08-30 23:25:16 +02:00
|
|
|
AwaitDialer {
|
2019-01-09 15:09:35 +01:00
|
|
|
dialer_fut: DialerFuture<R, I::Item>,
|
2018-08-30 23:25:16 +02:00
|
|
|
protocols: I
|
|
|
|
},
|
2019-01-09 15:09:35 +01:00
|
|
|
ProtocolList {
|
|
|
|
dialer: Dialer<R, I::Item>,
|
2018-08-30 23:25:16 +02:00
|
|
|
protocols: I
|
|
|
|
},
|
2019-01-09 15:09:35 +01:00
|
|
|
FlushListRequest {
|
|
|
|
dialer: Dialer<R, I::Item>,
|
2018-08-30 23:25:16 +02:00
|
|
|
protocols: I
|
|
|
|
},
|
2019-01-09 15:09:35 +01:00
|
|
|
AwaitListResponse {
|
|
|
|
stream: StreamFuture<Dialer<R, I::Item>>,
|
|
|
|
protocols: I,
|
|
|
|
},
|
|
|
|
Protocol {
|
|
|
|
dialer: Dialer<R, I::Item>,
|
|
|
|
proto_name: I::Item
|
|
|
|
},
|
|
|
|
FlushProtocol {
|
|
|
|
dialer: Dialer<R, I::Item>,
|
2018-12-11 15:13:10 +01:00
|
|
|
proto_name: I::Item
|
2018-08-30 23:25:16 +02:00
|
|
|
},
|
|
|
|
AwaitProtocol {
|
2019-01-09 15:09:35 +01:00
|
|
|
stream: StreamFuture<Dialer<R, I::Item>>,
|
2018-12-11 15:13:10 +01:00
|
|
|
proto_name: I::Item
|
2018-08-30 23:25:16 +02:00
|
|
|
},
|
|
|
|
Undefined
|
|
|
|
}
|
|
|
|
|
2018-12-11 15:13:10 +01:00
|
|
|
impl<R, I> Future for DialerSelectPar<R, I>
|
2018-08-30 23:25:16 +02:00
|
|
|
where
|
|
|
|
R: AsyncRead + AsyncWrite,
|
2019-01-09 15:09:35 +01:00
|
|
|
I: Iterator,
|
|
|
|
I::Item: AsRef<[u8]> + Clone
|
2018-08-30 23:25:16 +02:00
|
|
|
{
|
2019-03-19 17:27:30 +01:00
|
|
|
type Item = (I::Item, Negotiated<R>);
|
2018-08-30 23:25:16 +02:00
|
|
|
type Error = ProtocolChoiceError;
|
|
|
|
|
|
|
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
|
|
loop {
|
|
|
|
match mem::replace(&mut self.inner, DialerSelectParState::Undefined) {
|
|
|
|
DialerSelectParState::AwaitDialer { mut dialer_fut, protocols } => {
|
2019-01-09 15:09:35 +01:00
|
|
|
match dialer_fut.poll()? {
|
|
|
|
Async::Ready(dialer) => {
|
|
|
|
self.inner = DialerSelectParState::ProtocolList { dialer, protocols }
|
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
Async::NotReady => {
|
|
|
|
self.inner = DialerSelectParState::AwaitDialer { dialer_fut, protocols };
|
|
|
|
return Ok(Async::NotReady)
|
|
|
|
}
|
2019-01-09 15:09:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
DialerSelectParState::ProtocolList { mut dialer, protocols } => {
|
2018-08-30 23:25:16 +02:00
|
|
|
trace!("requesting protocols list");
|
2019-01-09 15:09:35 +01:00
|
|
|
match dialer.start_send(DialerToListenerMessage::ProtocolsListRequest)? {
|
|
|
|
AsyncSink::Ready => {
|
|
|
|
self.inner = DialerSelectParState::FlushListRequest {
|
|
|
|
dialer,
|
|
|
|
protocols
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AsyncSink::NotReady(_) => {
|
|
|
|
self.inner = DialerSelectParState::ProtocolList { dialer, protocols };
|
|
|
|
return Ok(Async::NotReady)
|
|
|
|
}
|
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
}
|
2019-01-09 15:09:35 +01:00
|
|
|
DialerSelectParState::FlushListRequest { mut dialer, protocols } => {
|
|
|
|
match dialer.poll_complete()? {
|
|
|
|
Async::Ready(()) => {
|
|
|
|
self.inner = DialerSelectParState::AwaitListResponse {
|
|
|
|
stream: dialer.into_future(),
|
|
|
|
protocols
|
|
|
|
}
|
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
Async::NotReady => {
|
2019-01-09 15:09:35 +01:00
|
|
|
self.inner = DialerSelectParState::FlushListRequest {
|
|
|
|
dialer,
|
|
|
|
protocols
|
|
|
|
};
|
2018-08-30 23:25:16 +02:00
|
|
|
return Ok(Async::NotReady)
|
|
|
|
}
|
2019-01-09 15:09:35 +01:00
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
}
|
2019-01-09 15:09:35 +01:00
|
|
|
DialerSelectParState::AwaitListResponse { mut stream, protocols } => {
|
|
|
|
let (resp, dialer) = match stream.poll() {
|
2018-08-30 23:25:16 +02:00
|
|
|
Ok(Async::Ready(x)) => x,
|
|
|
|
Ok(Async::NotReady) => {
|
2019-01-09 15:09:35 +01:00
|
|
|
self.inner = DialerSelectParState::AwaitListResponse { stream, protocols };
|
2018-08-30 23:25:16 +02:00
|
|
|
return Ok(Async::NotReady)
|
|
|
|
}
|
|
|
|
Err((e, _)) => return Err(ProtocolChoiceError::from(e))
|
|
|
|
};
|
2019-01-09 15:09:35 +01:00
|
|
|
trace!("protocols list response: {:?}", resp);
|
|
|
|
let list =
|
|
|
|
if let Some(ListenerToDialerMessage::ProtocolsListResponse { list }) = resp {
|
|
|
|
list
|
|
|
|
} else {
|
|
|
|
return Err(ProtocolChoiceError::UnexpectedMessage)
|
|
|
|
};
|
2018-08-30 23:25:16 +02:00
|
|
|
let mut found = None;
|
2018-12-11 15:13:10 +01:00
|
|
|
for local_name in protocols {
|
2018-08-30 23:25:16 +02:00
|
|
|
for remote_name in &list {
|
2018-12-11 15:13:10 +01:00
|
|
|
if remote_name.as_ref() == local_name.as_ref() {
|
|
|
|
found = Some(local_name);
|
2018-08-30 23:25:16 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if found.is_some() {
|
|
|
|
break;
|
|
|
|
}
|
2018-03-07 16:20:55 +01:00
|
|
|
}
|
2018-12-11 15:13:10 +01:00
|
|
|
let proto_name = found.ok_or(ProtocolChoiceError::NoProtocolFound)?;
|
2019-01-09 15:09:35 +01:00
|
|
|
self.inner = DialerSelectParState::Protocol { dialer, proto_name }
|
2018-03-07 16:20:55 +01:00
|
|
|
}
|
2019-01-09 15:09:35 +01:00
|
|
|
DialerSelectParState::Protocol { mut dialer, proto_name } => {
|
|
|
|
trace!("requesting protocol: {:?}", proto_name.as_ref());
|
|
|
|
let req = DialerToListenerMessage::ProtocolRequest {
|
|
|
|
name: proto_name.clone()
|
|
|
|
};
|
|
|
|
match dialer.start_send(req)? {
|
|
|
|
AsyncSink::Ready => {
|
|
|
|
self.inner = DialerSelectParState::FlushProtocol { dialer, proto_name }
|
|
|
|
}
|
|
|
|
AsyncSink::NotReady(_) => {
|
|
|
|
self.inner = DialerSelectParState::Protocol { dialer, proto_name };
|
|
|
|
return Ok(Async::NotReady)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DialerSelectParState::FlushProtocol { mut dialer, proto_name } => {
|
|
|
|
match dialer.poll_complete()? {
|
|
|
|
Async::Ready(()) => {
|
|
|
|
self.inner = DialerSelectParState::AwaitProtocol {
|
|
|
|
stream: dialer.into_future(),
|
2018-12-11 15:13:10 +01:00
|
|
|
proto_name
|
2019-01-09 15:09:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Async::NotReady => {
|
|
|
|
self.inner = DialerSelectParState::FlushProtocol { dialer, proto_name };
|
2018-08-30 23:25:16 +02:00
|
|
|
return Ok(Async::NotReady)
|
|
|
|
}
|
2019-01-09 15:09:35 +01:00
|
|
|
}
|
2018-03-07 16:20:55 +01:00
|
|
|
}
|
2018-12-11 15:13:10 +01:00
|
|
|
DialerSelectParState::AwaitProtocol { mut stream, proto_name } => {
|
2019-01-09 15:09:35 +01:00
|
|
|
let (resp, dialer) = match stream.poll() {
|
2018-08-30 23:25:16 +02:00
|
|
|
Ok(Async::Ready(x)) => x,
|
|
|
|
Ok(Async::NotReady) => {
|
2019-01-09 15:09:35 +01:00
|
|
|
self.inner = DialerSelectParState::AwaitProtocol { stream, proto_name };
|
2018-08-30 23:25:16 +02:00
|
|
|
return Ok(Async::NotReady)
|
|
|
|
}
|
|
|
|
Err((e, _)) => return Err(ProtocolChoiceError::from(e))
|
|
|
|
};
|
2019-01-09 15:09:35 +01:00
|
|
|
trace!("received {:?}", resp);
|
|
|
|
match resp {
|
2018-12-11 15:13:10 +01:00
|
|
|
Some(ListenerToDialerMessage::ProtocolAck { ref name })
|
|
|
|
if name.as_ref() == proto_name.as_ref() =>
|
|
|
|
{
|
2019-03-19 17:27:30 +01:00
|
|
|
return Ok(Async::Ready((proto_name, Negotiated(dialer.into_inner()))))
|
2018-08-30 23:25:16 +02:00
|
|
|
}
|
|
|
|
_ => return Err(ProtocolChoiceError::UnexpectedMessage)
|
|
|
|
}
|
2018-05-08 20:43:00 +02:00
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
DialerSelectParState::Undefined =>
|
|
|
|
panic!("DialerSelectParState::poll called after completion")
|
2018-03-07 16:20:55 +01:00
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
}
|
|
|
|
}
|
2017-11-05 12:21:34 +01:00
|
|
|
}
|
2018-08-30 23:25:16 +02:00
|
|
|
|