2018-12-10 16:00:16 +01:00
|
|
|
// Copyright 2018 Parity Technologies (UK) Ltd.
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
|
2020-12-03 13:30:52 +01:00
|
|
|
use crate::service::{MdnsPacket, MdnsService, build_query_response, build_service_discovery_response};
|
|
|
|
use async_io::Timer;
|
2018-12-10 16:00:16 +01:00
|
|
|
use futures::prelude::*;
|
Multiple connections per peer (#1440)
* Allow multiple connections per peer in libp2p-core.
Instead of trying to enforce a single connection per peer,
which involves quite a bit of additional complexity e.g.
to prioritise simultaneously opened connections and can
have other undesirable consequences [1], we now
make multiple connections per peer a feature.
The gist of these changes is as follows:
The concept of a "node" with an implicit 1-1 correspondence
to a connection has been replaced with the "first-class"
concept of a "connection". The code from `src/nodes` has moved
(with varying degrees of modification) to `src/connection`.
A `HandledNode` has become a `Connection`, a `NodeHandler` a
`ConnectionHandler`, the `CollectionStream` was the basis for
the new `connection::Pool`, and so forth.
Conceptually, a `Network` contains a `connection::Pool` which
in turn internally employs the `connection::Manager` for
handling the background `connection::manager::Task`s, one
per connection, as before. These are all considered implementation
details. On the public API, `Peer`s are managed as before through
the `Network`, except now the API has changed with the shift of focus
to (potentially multiple) connections per peer. The `NetworkEvent`s have
accordingly also undergone changes.
The Swarm APIs remain largely unchanged, except for the fact that
`inject_replaced` is no longer called. It may now practically happen
that multiple `ProtocolsHandler`s are associated with a single
`NetworkBehaviour`, one per connection. If implementations of
`NetworkBehaviour` rely somehow on communicating with exactly
one `ProtocolsHandler`, this may cause issues, but it is unlikely.
[1]: https://github.com/paritytech/substrate/issues/4272
* Fix intra-rustdoc links.
* Update core/src/connection/pool.rs
Co-Authored-By: Max Inden <mail@max-inden.de>
* Address some review feedback and fix doc links.
* Allow responses to be sent on the same connection.
* Remove unnecessary remainders of inject_replaced.
* Update swarm/src/behaviour.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Update swarm/src/lib.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Update core/src/connection/manager.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Update core/src/connection/manager.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Update core/src/connection/pool.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Incorporate more review feedback.
* Move module declaration below imports.
* Update core/src/connection/manager.rs
Co-Authored-By: Toralf Wittner <tw@dtex.org>
* Update core/src/connection/manager.rs
Co-Authored-By: Toralf Wittner <tw@dtex.org>
* Simplify as per review.
* Fix rustoc link.
* Add try_notify_handler and simplify.
* Relocate DialingConnection and DialingAttempt.
For better visibility constraints.
* Small cleanup.
* Small cleanup. More robust EstablishedConnectionIter.
* Clarify semantics of `DialingPeer::connect`.
* Don't call inject_disconnected on InvalidPeerId.
To preserve the previous behavior and ensure calls to
`inject_disconnected` are always paired with calls to
`inject_connected`.
* Provide public ConnectionId constructor.
Mainly needed for testing purposes, e.g. in substrate.
* Move the established connection limit check to the right place.
* Clean up connection error handling.
Separate connection errors into those occuring during
connection setup or upon rejecting a newly established
connection (the `PendingConnectionError`) and those
errors occurring on previously established connections,
i.e. for which a `ConnectionEstablished` event has
been emitted by the connection pool earlier.
* Revert change in log level and clarify an invariant.
* Remove inject_replaced entirely.
* Allow notifying all connection handlers.
Thereby simplify by introducing a new enum `NotifyHandler`,
used with a single constructor `NetworkBehaviourAction::NotifyHandler`.
* Finishing touches.
Small API simplifications and code deduplication.
Some more useful debug logging.
Co-authored-by: Max Inden <mail@max-inden.de>
Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>
Co-authored-by: Toralf Wittner <tw@dtex.org>
2020-03-04 13:49:25 +01:00
|
|
|
use libp2p_core::{
|
|
|
|
Multiaddr,
|
|
|
|
PeerId,
|
|
|
|
address_translation,
|
|
|
|
connection::ConnectionId,
|
|
|
|
multiaddr::Protocol
|
|
|
|
};
|
2019-07-04 14:47:59 +02:00
|
|
|
use libp2p_swarm::{
|
|
|
|
NetworkBehaviour,
|
|
|
|
NetworkBehaviourAction,
|
|
|
|
PollParameters,
|
|
|
|
ProtocolsHandler,
|
|
|
|
protocols_handler::DummyProtocolsHandler
|
|
|
|
};
|
2018-12-10 16:00:16 +01:00
|
|
|
use smallvec::SmallVec;
|
2020-12-03 13:30:52 +01:00
|
|
|
use std::{cmp, fmt, io, iter, mem, pin::Pin, time::{Duration, Instant}, task::Context, task::Poll};
|
2018-12-10 16:00:16 +01:00
|
|
|
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
const MDNS_RESPONSE_TTL: std::time::Duration = Duration::from_secs(5 * 60);
|
|
|
|
|
2018-12-10 16:00:16 +01:00
|
|
|
/// A `NetworkBehaviour` for mDNS. Automatically discovers peers on the local network and adds
|
|
|
|
/// them to the topology.
|
2020-12-03 13:30:52 +01:00
|
|
|
pub struct Mdns {
|
2018-12-10 16:00:16 +01:00
|
|
|
/// The inner service.
|
2020-12-03 13:30:52 +01:00
|
|
|
service: MdnsBusyWrapper,
|
2018-12-10 16:00:16 +01:00
|
|
|
|
2019-01-26 23:57:53 +01:00
|
|
|
/// List of nodes that we have discovered, the address, and when their TTL expires.
|
|
|
|
///
|
|
|
|
/// Each combination of `PeerId` and `Multiaddr` can only appear once, but the same `PeerId`
|
|
|
|
/// can appear multiple times.
|
|
|
|
discovered_nodes: SmallVec<[(PeerId, Multiaddr, Instant); 8]>,
|
|
|
|
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
/// Future that fires when the TTL of at least one node in `discovered_nodes` expires.
|
2019-01-26 23:57:53 +01:00
|
|
|
///
|
|
|
|
/// `None` if `discovered_nodes` is empty.
|
2020-12-03 13:30:52 +01:00
|
|
|
closest_expiration: Option<Timer>,
|
2018-12-10 16:00:16 +01:00
|
|
|
}
|
|
|
|
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
/// `MdnsService::next` takes ownership of `self`, returning a future that resolves with both itself
|
|
|
|
/// and a `MdnsPacket` (similar to the old Tokio socket send style). The two states are thus `Free`
|
|
|
|
/// with an `MdnsService` or `Busy` with a future returning the original `MdnsService` and an
|
|
|
|
/// `MdnsPacket`.
|
2020-12-03 13:30:52 +01:00
|
|
|
enum MdnsBusyWrapper {
|
|
|
|
Free(MdnsService),
|
|
|
|
Busy(Pin<Box<dyn Future<Output = (MdnsService, MdnsPacket)> + Send>>),
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
Poisoned,
|
|
|
|
}
|
|
|
|
|
2020-12-03 13:30:52 +01:00
|
|
|
impl fmt::Debug for MdnsBusyWrapper {
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
match self {
|
2020-12-03 13:30:52 +01:00
|
|
|
Self::Free(service) => {
|
|
|
|
fmt.debug_struct("MdnsBusyWrapper::Free")
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
.field("service", service)
|
|
|
|
.finish()
|
|
|
|
},
|
2020-12-03 13:30:52 +01:00
|
|
|
Self::Busy(_) => {
|
|
|
|
fmt.debug_struct("MdnsBusyWrapper::Busy")
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
.finish()
|
|
|
|
}
|
2020-12-03 13:30:52 +01:00
|
|
|
Self::Poisoned => {
|
|
|
|
fmt.debug_struct("MdnsBusyWrapper::Poisoned")
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 13:30:52 +01:00
|
|
|
impl Mdns {
|
2018-12-10 16:00:16 +01:00
|
|
|
/// Builds a new `Mdns` behaviour.
|
2020-12-03 13:30:52 +01:00
|
|
|
pub async fn new() -> io::Result<Self> {
|
|
|
|
Ok(Self {
|
|
|
|
service: MdnsBusyWrapper::Free(MdnsService::new().await?),
|
2019-01-26 23:57:53 +01:00
|
|
|
discovered_nodes: SmallVec::new(),
|
|
|
|
closest_expiration: None,
|
2018-12-10 16:00:16 +01:00
|
|
|
})
|
|
|
|
}
|
2019-01-26 23:57:53 +01:00
|
|
|
|
|
|
|
/// Returns true if the given `PeerId` is in the list of nodes discovered through mDNS.
|
|
|
|
pub fn has_node(&self, peer_id: &PeerId) -> bool {
|
2020-03-02 17:11:28 +01:00
|
|
|
self.discovered_nodes().any(|p| p == peer_id)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the list of nodes that we have discovered through mDNS and that are not expired.
|
|
|
|
pub fn discovered_nodes(&self) -> impl ExactSizeIterator<Item = &PeerId> {
|
|
|
|
self.discovered_nodes.iter().map(|(p, _, _)| p)
|
2019-01-26 23:57:53 +01:00
|
|
|
}
|
2018-12-10 16:00:16 +01:00
|
|
|
}
|
|
|
|
|
2020-12-03 13:30:52 +01:00
|
|
|
impl NetworkBehaviour for Mdns {
|
2020-02-07 16:29:30 +01:00
|
|
|
type ProtocolsHandler = DummyProtocolsHandler;
|
2019-01-26 23:57:53 +01:00
|
|
|
type OutEvent = MdnsEvent;
|
2018-12-10 16:00:16 +01:00
|
|
|
|
|
|
|
fn new_handler(&mut self) -> Self::ProtocolsHandler {
|
|
|
|
DummyProtocolsHandler::default()
|
|
|
|
}
|
|
|
|
|
2019-01-30 14:55:39 +01:00
|
|
|
fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec<Multiaddr> {
|
2019-01-26 23:57:53 +01:00
|
|
|
let now = Instant::now();
|
|
|
|
self.discovered_nodes
|
|
|
|
.iter()
|
|
|
|
.filter(move |(p, _, expires)| p == peer_id && *expires > now)
|
|
|
|
.map(|(_, addr, _)| addr.clone())
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2020-03-31 15:41:13 +02:00
|
|
|
fn inject_connected(&mut self, _: &PeerId) {}
|
2018-12-10 16:00:16 +01:00
|
|
|
|
2020-03-31 15:41:13 +02:00
|
|
|
fn inject_disconnected(&mut self, _: &PeerId) {}
|
2018-12-10 16:00:16 +01:00
|
|
|
|
Multiple connections per peer (#1440)
* Allow multiple connections per peer in libp2p-core.
Instead of trying to enforce a single connection per peer,
which involves quite a bit of additional complexity e.g.
to prioritise simultaneously opened connections and can
have other undesirable consequences [1], we now
make multiple connections per peer a feature.
The gist of these changes is as follows:
The concept of a "node" with an implicit 1-1 correspondence
to a connection has been replaced with the "first-class"
concept of a "connection". The code from `src/nodes` has moved
(with varying degrees of modification) to `src/connection`.
A `HandledNode` has become a `Connection`, a `NodeHandler` a
`ConnectionHandler`, the `CollectionStream` was the basis for
the new `connection::Pool`, and so forth.
Conceptually, a `Network` contains a `connection::Pool` which
in turn internally employs the `connection::Manager` for
handling the background `connection::manager::Task`s, one
per connection, as before. These are all considered implementation
details. On the public API, `Peer`s are managed as before through
the `Network`, except now the API has changed with the shift of focus
to (potentially multiple) connections per peer. The `NetworkEvent`s have
accordingly also undergone changes.
The Swarm APIs remain largely unchanged, except for the fact that
`inject_replaced` is no longer called. It may now practically happen
that multiple `ProtocolsHandler`s are associated with a single
`NetworkBehaviour`, one per connection. If implementations of
`NetworkBehaviour` rely somehow on communicating with exactly
one `ProtocolsHandler`, this may cause issues, but it is unlikely.
[1]: https://github.com/paritytech/substrate/issues/4272
* Fix intra-rustdoc links.
* Update core/src/connection/pool.rs
Co-Authored-By: Max Inden <mail@max-inden.de>
* Address some review feedback and fix doc links.
* Allow responses to be sent on the same connection.
* Remove unnecessary remainders of inject_replaced.
* Update swarm/src/behaviour.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Update swarm/src/lib.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Update core/src/connection/manager.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Update core/src/connection/manager.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Update core/src/connection/pool.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Incorporate more review feedback.
* Move module declaration below imports.
* Update core/src/connection/manager.rs
Co-Authored-By: Toralf Wittner <tw@dtex.org>
* Update core/src/connection/manager.rs
Co-Authored-By: Toralf Wittner <tw@dtex.org>
* Simplify as per review.
* Fix rustoc link.
* Add try_notify_handler and simplify.
* Relocate DialingConnection and DialingAttempt.
For better visibility constraints.
* Small cleanup.
* Small cleanup. More robust EstablishedConnectionIter.
* Clarify semantics of `DialingPeer::connect`.
* Don't call inject_disconnected on InvalidPeerId.
To preserve the previous behavior and ensure calls to
`inject_disconnected` are always paired with calls to
`inject_connected`.
* Provide public ConnectionId constructor.
Mainly needed for testing purposes, e.g. in substrate.
* Move the established connection limit check to the right place.
* Clean up connection error handling.
Separate connection errors into those occuring during
connection setup or upon rejecting a newly established
connection (the `PendingConnectionError`) and those
errors occurring on previously established connections,
i.e. for which a `ConnectionEstablished` event has
been emitted by the connection pool earlier.
* Revert change in log level and clarify an invariant.
* Remove inject_replaced entirely.
* Allow notifying all connection handlers.
Thereby simplify by introducing a new enum `NotifyHandler`,
used with a single constructor `NetworkBehaviourAction::NotifyHandler`.
* Finishing touches.
Small API simplifications and code deduplication.
Some more useful debug logging.
Co-authored-by: Max Inden <mail@max-inden.de>
Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>
Co-authored-by: Toralf Wittner <tw@dtex.org>
2020-03-04 13:49:25 +01:00
|
|
|
fn inject_event(
|
2018-12-10 16:00:16 +01:00
|
|
|
&mut self,
|
|
|
|
_: PeerId,
|
Multiple connections per peer (#1440)
* Allow multiple connections per peer in libp2p-core.
Instead of trying to enforce a single connection per peer,
which involves quite a bit of additional complexity e.g.
to prioritise simultaneously opened connections and can
have other undesirable consequences [1], we now
make multiple connections per peer a feature.
The gist of these changes is as follows:
The concept of a "node" with an implicit 1-1 correspondence
to a connection has been replaced with the "first-class"
concept of a "connection". The code from `src/nodes` has moved
(with varying degrees of modification) to `src/connection`.
A `HandledNode` has become a `Connection`, a `NodeHandler` a
`ConnectionHandler`, the `CollectionStream` was the basis for
the new `connection::Pool`, and so forth.
Conceptually, a `Network` contains a `connection::Pool` which
in turn internally employs the `connection::Manager` for
handling the background `connection::manager::Task`s, one
per connection, as before. These are all considered implementation
details. On the public API, `Peer`s are managed as before through
the `Network`, except now the API has changed with the shift of focus
to (potentially multiple) connections per peer. The `NetworkEvent`s have
accordingly also undergone changes.
The Swarm APIs remain largely unchanged, except for the fact that
`inject_replaced` is no longer called. It may now practically happen
that multiple `ProtocolsHandler`s are associated with a single
`NetworkBehaviour`, one per connection. If implementations of
`NetworkBehaviour` rely somehow on communicating with exactly
one `ProtocolsHandler`, this may cause issues, but it is unlikely.
[1]: https://github.com/paritytech/substrate/issues/4272
* Fix intra-rustdoc links.
* Update core/src/connection/pool.rs
Co-Authored-By: Max Inden <mail@max-inden.de>
* Address some review feedback and fix doc links.
* Allow responses to be sent on the same connection.
* Remove unnecessary remainders of inject_replaced.
* Update swarm/src/behaviour.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Update swarm/src/lib.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Update core/src/connection/manager.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Update core/src/connection/manager.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Update core/src/connection/pool.rs
Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
* Incorporate more review feedback.
* Move module declaration below imports.
* Update core/src/connection/manager.rs
Co-Authored-By: Toralf Wittner <tw@dtex.org>
* Update core/src/connection/manager.rs
Co-Authored-By: Toralf Wittner <tw@dtex.org>
* Simplify as per review.
* Fix rustoc link.
* Add try_notify_handler and simplify.
* Relocate DialingConnection and DialingAttempt.
For better visibility constraints.
* Small cleanup.
* Small cleanup. More robust EstablishedConnectionIter.
* Clarify semantics of `DialingPeer::connect`.
* Don't call inject_disconnected on InvalidPeerId.
To preserve the previous behavior and ensure calls to
`inject_disconnected` are always paired with calls to
`inject_connected`.
* Provide public ConnectionId constructor.
Mainly needed for testing purposes, e.g. in substrate.
* Move the established connection limit check to the right place.
* Clean up connection error handling.
Separate connection errors into those occuring during
connection setup or upon rejecting a newly established
connection (the `PendingConnectionError`) and those
errors occurring on previously established connections,
i.e. for which a `ConnectionEstablished` event has
been emitted by the connection pool earlier.
* Revert change in log level and clarify an invariant.
* Remove inject_replaced entirely.
* Allow notifying all connection handlers.
Thereby simplify by introducing a new enum `NotifyHandler`,
used with a single constructor `NetworkBehaviourAction::NotifyHandler`.
* Finishing touches.
Small API simplifications and code deduplication.
Some more useful debug logging.
Co-authored-by: Max Inden <mail@max-inden.de>
Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>
Co-authored-by: Toralf Wittner <tw@dtex.org>
2020-03-04 13:49:25 +01:00
|
|
|
_: ConnectionId,
|
2020-12-03 13:30:52 +01:00
|
|
|
ev: <Self::ProtocolsHandler as ProtocolsHandler>::OutEvent,
|
2018-12-10 16:00:16 +01:00
|
|
|
) {
|
2020-12-03 13:30:52 +01:00
|
|
|
void::unreachable(ev)
|
2018-12-10 16:00:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn poll(
|
|
|
|
&mut self,
|
2020-07-27 20:27:33 +00:00
|
|
|
cx: &mut Context<'_>,
|
2019-06-18 10:23:26 +02:00
|
|
|
params: &mut impl PollParameters,
|
2019-09-16 11:08:44 +02:00
|
|
|
) -> Poll<
|
2018-12-10 16:00:16 +01:00
|
|
|
NetworkBehaviourAction<
|
|
|
|
<Self::ProtocolsHandler as ProtocolsHandler>::InEvent,
|
|
|
|
Self::OutEvent,
|
|
|
|
>,
|
|
|
|
> {
|
2019-01-26 23:57:53 +01:00
|
|
|
// Remove expired peers.
|
|
|
|
if let Some(ref mut closest_expiration) = self.closest_expiration {
|
2020-12-03 13:30:52 +01:00
|
|
|
match Pin::new(closest_expiration).poll(cx) {
|
|
|
|
Poll::Ready(now) => {
|
2019-01-26 23:57:53 +01:00
|
|
|
let mut expired = SmallVec::<[(PeerId, Multiaddr); 4]>::new();
|
|
|
|
while let Some(pos) = self.discovered_nodes.iter().position(|(_, _, exp)| *exp < now) {
|
|
|
|
let (peer_id, addr, _) = self.discovered_nodes.remove(pos);
|
|
|
|
expired.push((peer_id, addr));
|
|
|
|
}
|
|
|
|
|
|
|
|
if !expired.is_empty() {
|
|
|
|
let event = MdnsEvent::Expired(ExpiredAddrsIter {
|
|
|
|
inner: expired.into_iter(),
|
|
|
|
});
|
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event));
|
2019-01-26 23:57:53 +01:00
|
|
|
}
|
|
|
|
},
|
2019-09-16 11:08:44 +02:00
|
|
|
Poll::Pending => (),
|
2018-12-10 16:00:16 +01:00
|
|
|
}
|
2019-01-26 23:57:53 +01:00
|
|
|
}
|
2018-12-10 16:00:16 +01:00
|
|
|
|
2019-01-26 23:57:53 +01:00
|
|
|
// Polling the mDNS service, and obtain the list of nodes discovered this round.
|
|
|
|
let discovered = loop {
|
2020-12-03 13:30:52 +01:00
|
|
|
let service = mem::replace(&mut self.service, MdnsBusyWrapper::Poisoned);
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
|
|
|
|
let packet = match service {
|
2020-12-03 13:30:52 +01:00
|
|
|
MdnsBusyWrapper::Free(service) => {
|
|
|
|
self.service = MdnsBusyWrapper::Busy(Box::pin(service.next()));
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
continue;
|
|
|
|
},
|
2020-12-03 13:30:52 +01:00
|
|
|
MdnsBusyWrapper::Busy(mut fut) => {
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
match fut.as_mut().poll(cx) {
|
|
|
|
Poll::Ready((service, packet)) => {
|
2020-12-03 13:30:52 +01:00
|
|
|
self.service = MdnsBusyWrapper::Free(service);
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
packet
|
|
|
|
},
|
|
|
|
Poll::Pending => {
|
2020-12-03 13:30:52 +01:00
|
|
|
self.service = MdnsBusyWrapper::Busy(fut);
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
return Poll::Pending;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2020-12-03 13:30:52 +01:00
|
|
|
MdnsBusyWrapper::Poisoned => panic!("Mdns poisoned"),
|
2018-12-10 16:00:16 +01:00
|
|
|
};
|
|
|
|
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
match packet {
|
2018-12-10 16:00:16 +01:00
|
|
|
MdnsPacket::Query(query) => {
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
// MaybeBusyMdnsService should always be Free.
|
2020-12-03 13:30:52 +01:00
|
|
|
if let MdnsBusyWrapper::Free(ref mut service) = self.service {
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
let resp = build_query_response(
|
|
|
|
query.query_id(),
|
|
|
|
params.local_peer_id().clone(),
|
|
|
|
params.listened_addresses().into_iter(),
|
|
|
|
MDNS_RESPONSE_TTL,
|
|
|
|
);
|
|
|
|
service.enqueue_response(resp.unwrap());
|
|
|
|
} else { debug_assert!(false); }
|
2018-12-10 16:00:16 +01:00
|
|
|
},
|
|
|
|
MdnsPacket::Response(response) => {
|
2019-04-17 20:12:31 +02:00
|
|
|
// We replace the IP address with the address we observe the
|
2018-12-10 16:00:16 +01:00
|
|
|
// remote as and the address they listen on.
|
|
|
|
let obs_ip = Protocol::from(response.remote_addr().ip());
|
|
|
|
let obs_port = Protocol::Udp(response.remote_addr().port());
|
|
|
|
let observed: Multiaddr = iter::once(obs_ip)
|
|
|
|
.chain(iter::once(obs_port))
|
|
|
|
.collect();
|
|
|
|
|
2019-01-26 23:57:53 +01:00
|
|
|
let mut discovered: SmallVec<[_; 4]> = SmallVec::new();
|
2018-12-10 16:00:16 +01:00
|
|
|
for peer in response.discovered_peers() {
|
|
|
|
if peer.id() == params.local_peer_id() {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-01-26 23:57:53 +01:00
|
|
|
let new_expiration = Instant::now() + peer.ttl();
|
|
|
|
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
let mut addrs: Vec<Multiaddr> = Vec::new();
|
2018-12-10 16:00:16 +01:00
|
|
|
for addr in peer.addresses() {
|
2019-04-17 20:12:31 +02:00
|
|
|
if let Some(new_addr) = address_translation(&addr, &observed) {
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
addrs.push(new_addr.clone())
|
2019-01-02 13:23:58 +01:00
|
|
|
}
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
addrs.push(addr.clone())
|
2018-12-10 16:00:16 +01:00
|
|
|
}
|
|
|
|
|
2019-01-26 23:57:53 +01:00
|
|
|
for addr in addrs {
|
|
|
|
if let Some((_, _, cur_expires)) = self.discovered_nodes.iter_mut()
|
|
|
|
.find(|(p, a, _)| p == peer.id() && *a == addr)
|
|
|
|
{
|
|
|
|
*cur_expires = cmp::max(*cur_expires, new_expiration);
|
|
|
|
} else {
|
|
|
|
self.discovered_nodes.push((peer.id().clone(), addr.clone(), new_expiration));
|
|
|
|
}
|
|
|
|
|
|
|
|
discovered.push((peer.id().clone(), addr));
|
2018-12-10 16:00:16 +01:00
|
|
|
}
|
|
|
|
}
|
2019-01-26 23:57:53 +01:00
|
|
|
|
|
|
|
break discovered;
|
2018-12-10 16:00:16 +01:00
|
|
|
},
|
|
|
|
MdnsPacket::ServiceDiscovery(disc) => {
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
// MaybeBusyMdnsService should always be Free.
|
2020-12-03 13:30:52 +01:00
|
|
|
if let MdnsBusyWrapper::Free(ref mut service) = self.service {
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
let resp = build_service_discovery_response(
|
|
|
|
disc.query_id(),
|
|
|
|
MDNS_RESPONSE_TTL,
|
|
|
|
);
|
|
|
|
service.enqueue_response(resp);
|
|
|
|
} else { debug_assert!(false); }
|
2018-12-10 16:00:16 +01:00
|
|
|
},
|
|
|
|
}
|
2019-01-26 23:57:53 +01:00
|
|
|
};
|
|
|
|
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
// Getting this far implies that we discovered new nodes. As the final step, we need to
|
|
|
|
// refresh `closest_expiration`.
|
2019-01-26 23:57:53 +01:00
|
|
|
self.closest_expiration = self.discovered_nodes.iter()
|
|
|
|
.fold(None, |exp, &(_, _, elem_exp)| {
|
|
|
|
Some(exp.map(|exp| cmp::min(exp, elem_exp)).unwrap_or(elem_exp))
|
|
|
|
})
|
2020-12-03 13:30:52 +01:00
|
|
|
.map(Timer::at);
|
misc/mdns: Update to futures-preview (#1247)
* misc/mdns/service: Use async std with stack pinned futures
* misc/mdns: Define mdns broadcast address as lazy static
* misc/mdns: Drop future before borrowing their arguments again
* misc/mdns: Send queries on query socket, not socket
* misc/mdns: Use poll_next_unpin on query interval stream
* misc/mdns: Ensure underlying task is woken up on next interval tick
* misc/mdns: Wrap match expression in scope to drop future early
* misc/mdns: Adjust 'discovery_ourselves' test
* misc/mdns: Make query interval fire instantly on first tick
This is an optimization only important for short lived use cases, e.g.
unit tests. Instead of waiting for 20 seconds at first, the query
interval fires right away and thereby the service makes progress
instantly.
* misc/mdns: Adjust MdnsService documentation tests
* misc/mdns: Do not drop UDP socket send and reicv futures
Libp2p-mdns uses the async-std crate for network io. This crate only
offers async send and receive functions. In order to use this in non
async/await functions one needs to keep the future returned by the crate
functions around across `poll` invocations.
The future returned by the crate functions references the io resource.
Thus one has to keep both the io resource as well as the future
referencing it. This results in a self-referencing struct which is not
possible to create with safe Rust.
Instead, by having `MdnsService::next` (former `MdnsService::poll`) take
ownership of `self`, the Rust async magic takes care of the above (See
code comments for more details).
As a (negative) side effect, given that `MdnsService::next` takes
ownership of `self`, there is nothing to bind the lifetime of the
returned `MdnsPacket` to. With no better solution in mind, this patch
makes `MdnsPacket` static, not referencing the `MdnsService` receive
buffer.
* misc/mdns: Fix code comments and remove *if Free* TODO
* misc/mdns: Minor refactorings
* misc/mdns: Build responses in behaviour.rs directly
* misc/mdns: Move response ttl duration to constant
* misc/mdns: Remove optimization todo comment
* misc/mdns: Add query interval test
* misc/mdns: Move packet parsing into MdnPacket impl
* misc/mdns: Don't have receiving packets starve the query interval
When we 'await' on receiving a packet on the udp socket without
receiving a single packet we starve the remaining logic of the mdns
service, in this case the logic triggered on the receive interval.
* misc/mdns: Add debug_assert to MaybeBusyMdnsService check
* misc/mdns: Implement Debug for MaybeBusyMdnsService
* misc/mdns: Make ownership note a normal comment, not a doc comment
* misc/mdns: Have discovered_peers return an iterator
2019-11-20 13:25:12 +01:00
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
Poll::Ready(NetworkBehaviourAction::GenerateEvent(MdnsEvent::Discovered(DiscoveredAddrsIter {
|
2019-01-26 23:57:53 +01:00
|
|
|
inner: discovered.into_iter(),
|
|
|
|
})))
|
2018-12-10 16:00:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 13:30:52 +01:00
|
|
|
impl fmt::Debug for Mdns {
|
2019-02-11 14:58:15 +01:00
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2018-12-10 16:00:16 +01:00
|
|
|
fmt.debug_struct("Mdns")
|
|
|
|
.field("service", &self.service)
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
2020-08-18 14:51:03 +02:00
|
|
|
|
|
|
|
/// Event that can be produced by the `Mdns` behaviour.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum MdnsEvent {
|
|
|
|
/// Discovered nodes through mDNS.
|
|
|
|
Discovered(DiscoveredAddrsIter),
|
|
|
|
|
|
|
|
/// The given combinations of `PeerId` and `Multiaddr` have expired.
|
|
|
|
///
|
|
|
|
/// Each discovered record has a time-to-live. When this TTL expires and the address hasn't
|
|
|
|
/// been refreshed, we remove it from the list and emit it as an `Expired` event.
|
|
|
|
Expired(ExpiredAddrsIter),
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Iterator that produces the list of addresses that have been discovered.
|
|
|
|
pub struct DiscoveredAddrsIter {
|
|
|
|
inner: smallvec::IntoIter<[(PeerId, Multiaddr); 4]>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Iterator for DiscoveredAddrsIter {
|
|
|
|
type Item = (PeerId, Multiaddr);
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
self.inner.next()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
|
|
self.inner.size_hint()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ExactSizeIterator for DiscoveredAddrsIter {
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for DiscoveredAddrsIter {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
fmt.debug_struct("DiscoveredAddrsIter")
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Iterator that produces the list of addresses that have expired.
|
|
|
|
pub struct ExpiredAddrsIter {
|
|
|
|
inner: smallvec::IntoIter<[(PeerId, Multiaddr); 4]>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Iterator for ExpiredAddrsIter {
|
|
|
|
type Item = (PeerId, Multiaddr);
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
self.inner.next()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
|
|
self.inner.size_hint()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ExactSizeIterator for ExpiredAddrsIter {
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for ExpiredAddrsIter {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
fmt.debug_struct("ExpiredAddrsIter")
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|