Skip to content

Commit

Permalink
[swarm] Configurable and "infinite" scores for external addresses. (#…
Browse files Browse the repository at this point in the history
…1842)

* Add "infinite" scores for external addresses.

Extend address scores with an infinite cardinal, permitting
addresses to be retained "forever" or until explicitly removed.

Expose (external) address scores on the API.

* Update swarm/src/registry.rs

Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>

* Fix compilation.

* Update CHANGELOG

Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>
  • Loading branch information
romanb and tomaka committed Nov 18, 2020
1 parent edb99ed commit 1bd013c
Show file tree
Hide file tree
Showing 9 changed files with 346 additions and 120 deletions.
4 changes: 2 additions & 2 deletions misc/core-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,8 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
event: #wrapped_event,
});
}
std::task::Poll::Ready(#network_behaviour_action::ReportObservedAddr { address }) => {
return std::task::Poll::Ready(#network_behaviour_action::ReportObservedAddr { address });
std::task::Poll::Ready(#network_behaviour_action::ReportObservedAddr { address, score }) => {
return std::task::Poll::Ready(#network_behaviour_action::ReportObservedAddr { address, score });
}
std::task::Poll::Pending => break,
}
Expand Down
4 changes: 2 additions & 2 deletions protocols/gossipsub/src/behaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1412,8 +1412,8 @@ impl NetworkBehaviour for Gossipsub {
NetworkBehaviourAction::DialPeer { peer_id, condition } => {
NetworkBehaviourAction::DialPeer { peer_id, condition }
}
NetworkBehaviourAction::ReportObservedAddr { address } => {
NetworkBehaviourAction::ReportObservedAddr { address }
NetworkBehaviourAction::ReportObservedAddr { address, score } => {
NetworkBehaviourAction::ReportObservedAddr { address, score }
}
});
}
Expand Down
8 changes: 7 additions & 1 deletion protocols/identify/src/identify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use libp2p_core::{
upgrade::{ReadOneError, UpgradeError}
};
use libp2p_swarm::{
AddressScore,
NegotiatedSubstream,
NetworkBehaviour,
NetworkBehaviourAction,
Expand All @@ -47,6 +48,10 @@ use std::{

/// Network behaviour that automatically identifies nodes periodically, returns information
/// about them, and answers identify queries from other nodes.
///
/// All external addresses of the local node supposedly observed by remotes
/// are reported via [`NetworkBehaviourAction::ReportObservedAddr`] with a
/// [score](AddressScore) of `1`.
pub struct Identify {
/// Protocol version to send back to remotes.
protocol_version: String,
Expand Down Expand Up @@ -143,6 +148,7 @@ impl NetworkBehaviour for Identify {
self.events.push_back(
NetworkBehaviourAction::ReportObservedAddr {
address: remote.observed_addr,
score: AddressScore::Finite(1),
});
}
IdentifyHandlerEvent::Identify(sender) => {
Expand Down Expand Up @@ -187,7 +193,7 @@ impl NetworkBehaviour for Identify {
.map(|p| String::from_utf8_lossy(&p).to_string())
.collect();

let mut listen_addrs: Vec<_> = params.external_addresses().collect();
let mut listen_addrs: Vec<_> = params.external_addresses().map(|r| r.addr).collect();
listen_addrs.extend(params.listened_addresses());

let mut sending = 0;
Expand Down
2 changes: 1 addition & 1 deletion protocols/kad/src/behaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,7 +1046,7 @@ where
phase: AddProviderPhase::GetClosestPeers
} => {
let provider_id = params.local_peer_id().clone();
let external_addresses = params.external_addresses().collect();
let external_addresses = params.external_addresses().map(|r| r.addr).collect();
let inner = QueryInner::new(QueryInfo::AddProvider {
context,
key,
Expand Down
4 changes: 2 additions & 2 deletions protocols/request-response/src/throttled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,8 @@ where
NetworkBehaviourAction::DialPeer { peer_id, condition },
| NetworkBehaviourAction::NotifyHandler { peer_id, handler, event } =>
NetworkBehaviourAction::NotifyHandler { peer_id, handler, event },
| NetworkBehaviourAction::ReportObservedAddr { address } =>
NetworkBehaviourAction::ReportObservedAddr { address }
| NetworkBehaviourAction::ReportObservedAddr { address, score } =>
NetworkBehaviourAction::ReportObservedAddr { address, score }
};

return Poll::Ready(event)
Expand Down
5 changes: 5 additions & 0 deletions swarm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

- Update `libp2p-core`.

- Expose configurable scores for external addresses, as well as
the ability to remove them and to add addresses that are
retained "forever" (or until explicitly removed).
[PR 1842](https://github.com/libp2p/rust-libp2p/pull/1842).

# 0.24.0 [2020-11-09]

- Update dependencies.
Expand Down
20 changes: 13 additions & 7 deletions swarm/src/behaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use crate::{AddressScore, AddressRecord};
use crate::protocols_handler::{IntoProtocolsHandler, ProtocolsHandler};
use libp2p_core::{ConnectedPoint, Multiaddr, PeerId, connection::{ConnectionId, ListenerId}};
use std::{error, task::Context, task::Poll};
Expand Down Expand Up @@ -182,7 +183,7 @@ pub trait PollParameters {
/// Iterator returned by [`listened_addresses`](PollParameters::listened_addresses).
type ListenedAddressesIter: ExactSizeIterator<Item = Multiaddr>;
/// Iterator returned by [`external_addresses`](PollParameters::external_addresses).
type ExternalAddressesIter: ExactSizeIterator<Item = Multiaddr>;
type ExternalAddressesIter: ExactSizeIterator<Item = AddressRecord>;

/// Returns the list of protocol the behaviour supports when a remote negotiates a protocol on
/// an inbound substream.
Expand Down Expand Up @@ -269,15 +270,20 @@ pub enum NetworkBehaviourAction<TInEvent, TOutEvent> {
event: TInEvent,
},

/// Informs the `Swarm` about a multi-address observed by a remote for
/// the local node.
/// Informs the `Swarm` about an address observed by a remote for
/// the local node by which the local node is supposedly publicly
/// reachable.
///
/// It is advisable to issue `ReportObservedAddr` actions at a fixed frequency
/// per node. This way address information will be more accurate over time
/// and individual outliers carry less weight.
ReportObservedAddr {
/// The observed address of the local node.
address: Multiaddr,
/// The score to associate with this observation, i.e.
/// an indicator for the trusworthiness of this address
/// relative to other observed addresses.
score: AddressScore,
},
}

Expand All @@ -297,8 +303,8 @@ impl<TInEvent, TOutEvent> NetworkBehaviourAction<TInEvent, TOutEvent> {
handler,
event: f(event)
},
NetworkBehaviourAction::ReportObservedAddr { address } =>
NetworkBehaviourAction::ReportObservedAddr { address }
NetworkBehaviourAction::ReportObservedAddr { address, score } =>
NetworkBehaviourAction::ReportObservedAddr { address, score }
}
}

Expand All @@ -313,8 +319,8 @@ impl<TInEvent, TOutEvent> NetworkBehaviourAction<TInEvent, TOutEvent> {
NetworkBehaviourAction::DialPeer { peer_id, condition },
NetworkBehaviourAction::NotifyHandler { peer_id, handler, event } =>
NetworkBehaviourAction::NotifyHandler { peer_id, handler, event },
NetworkBehaviourAction::ReportObservedAddr { address } =>
NetworkBehaviourAction::ReportObservedAddr { address }
NetworkBehaviourAction::ReportObservedAddr { address, score } =>
NetworkBehaviourAction::ReportObservedAddr { address, score }
}
}
}
Expand Down
57 changes: 34 additions & 23 deletions swarm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub use protocols_handler::{
OneShotHandlerConfig,
SubstreamProtocol
};
pub use registry::{AddressScore, AddressRecord, AddAddressResult};

use protocols_handler::{
NodeHandlerWrapperBuilder,
Expand Down Expand Up @@ -397,34 +398,44 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
me.network.listen_addrs()
}

/// Returns an iterator that produces the list of addresses that other nodes can use to reach
/// us.
pub fn external_addresses(me: &Self) -> impl Iterator<Item = &Multiaddr> {
me.external_addrs.iter()
}

/// Returns the peer ID of the swarm passed as parameter.
pub fn local_peer_id(me: &Self) -> &PeerId {
&me.network.local_peer_id()
}

/// Adds an external address.
/// Returns an iterator for [`AddressRecord`]s of external addresses
/// of the local node, in decreasing order of their current
/// [score](AddressScore).
pub fn external_addresses(me: &Self) -> impl Iterator<Item = &AddressRecord> {
me.external_addrs.iter()
}

/// Adds an external address record for the local node.
///
/// An external address is an address we are listening on but that accounts for things such as
/// NAT traversal.
pub fn add_external_address(me: &mut Self, addr: Multiaddr) {
me.external_addrs.add(addr)
/// An external address is an address of the local node known to
/// be (likely) reachable for other nodes, possibly taking into
/// account NAT. The external addresses of the local node may be
/// shared with other nodes by the `NetworkBehaviour`.
///
/// The associated score determines both the position of the address
/// in the list of external addresses (which can determine the
/// order in which addresses are used to connect to) as well as
/// how long the address is retained in the list, depending on
/// how frequently it is reported by the `NetworkBehaviour` via
/// [`NetworkBehaviourAction::ReportObservedAddr`] or explicitly
/// through this method.
pub fn add_external_address(me: &mut Self, a: Multiaddr, s: AddressScore) -> AddAddressResult {
me.external_addrs.add(a, s)
}

/// Returns the connection info for an arbitrary connection with the peer, or `None`
/// if there is no connection to that peer.
// TODO: should take &self instead of &mut self, but the API in network requires &mut
pub fn connection_info(me: &mut Self, peer_id: &PeerId) -> Option<PeerId> {
if let Some(mut n) = me.network.peer(peer_id.clone()).into_connected() {
Some(n.some_connection().info().clone())
} else {
None
}
/// Removes an external address of the local node, regardless of
/// its current score. See [`ExpandedSwarm::add_external_address`]
/// for details.
///
/// Returns `true` if the address existed and was removed, `false`
/// otherwise.
pub fn remove_external_address(me: &mut Self, addr: &Multiaddr) -> bool {
me.external_addrs.remove(addr)
}

/// Bans a peer by its peer ID.
Expand Down Expand Up @@ -732,12 +743,12 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
}
}
},
Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) => {
Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address, score }) => {
for addr in this.network.address_translation(&address) {
if this.external_addrs.iter().all(|a| *a != addr) {
if this.external_addrs.iter().all(|a| &a.addr != &addr) {
this.behaviour.inject_new_external_addr(&addr);
}
this.external_addrs.add(addr);
this.external_addrs.add(addr, score);
}
},
}
Expand Down
Loading

0 comments on commit 1bd013c

Please sign in to comment.