Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[swarm] Configurable and "infinite" scores for external addresses. #1842

Merged
merged 7 commits into from
Nov 18, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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