|
|
@@ -89,17 +89,17 @@ impl Hosts {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- /// Loops through whitelist addresses to find an outbound address that we can
|
|
|
+ /// Loops through greylist addresses to find an outbound address that we can
|
|
|
/// connect to. Check whether the address is valid by making sure it isn't
|
|
|
/// our own inbound address, then checks whether it is already connected
|
|
|
/// (exists) or connecting (pending).
|
|
|
/// Lastly adds matching address to the pending list.
|
|
|
- pub async fn whitelist_fetch_address_with_lock(
|
|
|
+ pub async fn greylist_fetch_address_with_lock(
|
|
|
&self,
|
|
|
p2p: P2pPtr,
|
|
|
transports: &[String],
|
|
|
) -> Option<(Url, u64)> {
|
|
|
- debug!(target: "store", "whitelist_fetch_address_with_lock() [START]");
|
|
|
+ debug!(target: "store", "greylist_fetch_address_with_lock() [START]");
|
|
|
// Collect hosts
|
|
|
let mut hosts = vec![];
|
|
|
|
|
|
@@ -111,7 +111,7 @@ impl Hosts {
|
|
|
($a:expr, $b:expr) => {
|
|
|
if transports.contains(&$a.to_string()) && transport_mixing {
|
|
|
let mut a_to_b =
|
|
|
- self.whitelist_fetch_with_schemes(&[$b.to_string()], None).await;
|
|
|
+ self.greylist_fetch_with_schemes(&[$b.to_string()], None).await;
|
|
|
for (addr, last_seen) in a_to_b.iter_mut() {
|
|
|
addr.set_scheme($a).unwrap();
|
|
|
hosts.push((addr.clone(), last_seen.clone()));
|
|
|
@@ -125,7 +125,7 @@ impl Hosts {
|
|
|
mix_transport!("nym+tls", "tcp+tls");
|
|
|
|
|
|
// And now the actual requested transports
|
|
|
- for (addr, last_seen) in self.whitelist_fetch_with_schemes(transports, None).await {
|
|
|
+ for (addr, last_seen) in self.greylist_fetch_with_schemes(transports, None).await {
|
|
|
hosts.push((addr, last_seen));
|
|
|
}
|
|
|
|
|
|
@@ -138,7 +138,7 @@ impl Hosts {
|
|
|
// Check if we already have this connection established
|
|
|
if p2p.exists(host).await {
|
|
|
trace!(
|
|
|
- target: "net::hosts::whitelist_fetch_address_with_lock()",
|
|
|
+ target: "net::hosts::greylist_fetch_address_with_lock()",
|
|
|
"Host '{}' exists so skipping",
|
|
|
host
|
|
|
);
|
|
|
@@ -148,7 +148,7 @@ impl Hosts {
|
|
|
// Check if we already have this configured as a manual peer
|
|
|
if self.settings.peers.contains(host) {
|
|
|
trace!(
|
|
|
- target: "net::hosts::whitelist_fetch_address_with_lock()",
|
|
|
+ target: "net::hosts::greylist_fetch_address_with_lock()",
|
|
|
"Host '{}' configured as manual peer so skipping",
|
|
|
host
|
|
|
);
|
|
|
@@ -158,7 +158,7 @@ impl Hosts {
|
|
|
// Obtain a lock on this address to prevent duplicate connection
|
|
|
if !p2p.add_pending(host).await {
|
|
|
trace!(
|
|
|
- target: "net::hosts::whitelist_fetch_address_with_lock()",
|
|
|
+ target: "net::hosts::greylist_fetch_address_with_lock()",
|
|
|
"Host '{}' pending so skipping",
|
|
|
host
|
|
|
);
|
|
|
@@ -166,7 +166,7 @@ impl Hosts {
|
|
|
}
|
|
|
|
|
|
trace!(
|
|
|
- target: "net::hosts::whitelist_fetch_address_with_lock()",
|
|
|
+ target: "net::hosts::greylist_fetch_address_with_lock()",
|
|
|
"Found valid host '{}",
|
|
|
host
|
|
|
);
|
|
|
@@ -176,12 +176,17 @@ impl Hosts {
|
|
|
None
|
|
|
}
|
|
|
|
|
|
- pub async fn greylist_fetch_address_with_lock(
|
|
|
+ /// Loops through whitelist addresses to find an outbound address that we can
|
|
|
+ /// connect to. Check whether the address is valid by making sure it isn't
|
|
|
+ /// our own inbound address, then checks whether it is already connected
|
|
|
+ /// (exists) or connecting (pending).
|
|
|
+ /// Lastly adds matching address to the pending list.
|
|
|
+ pub async fn whitelist_fetch_address_with_lock(
|
|
|
&self,
|
|
|
p2p: P2pPtr,
|
|
|
transports: &[String],
|
|
|
) -> Option<(Url, u64)> {
|
|
|
- debug!(target: "store", "greylist_fetch_address_with_lock() [START]");
|
|
|
+ debug!(target: "store", "whitelist_fetch_address_with_lock() [START]");
|
|
|
// Collect hosts
|
|
|
let mut hosts = vec![];
|
|
|
|
|
|
@@ -193,7 +198,7 @@ impl Hosts {
|
|
|
($a:expr, $b:expr) => {
|
|
|
if transports.contains(&$a.to_string()) && transport_mixing {
|
|
|
let mut a_to_b =
|
|
|
- self.greylist_fetch_with_schemes(&[$b.to_string()], None).await;
|
|
|
+ self.whitelist_fetch_with_schemes(&[$b.to_string()], None).await;
|
|
|
for (addr, last_seen) in a_to_b.iter_mut() {
|
|
|
addr.set_scheme($a).unwrap();
|
|
|
hosts.push((addr.clone(), last_seen.clone()));
|
|
|
@@ -207,7 +212,7 @@ impl Hosts {
|
|
|
mix_transport!("nym+tls", "tcp+tls");
|
|
|
|
|
|
// And now the actual requested transports
|
|
|
- for (addr, last_seen) in self.greylist_fetch_with_schemes(transports, None).await {
|
|
|
+ for (addr, last_seen) in self.whitelist_fetch_with_schemes(transports, None).await {
|
|
|
hosts.push((addr, last_seen));
|
|
|
}
|
|
|
|
|
|
@@ -220,7 +225,7 @@ impl Hosts {
|
|
|
// Check if we already have this connection established
|
|
|
if p2p.exists(host).await {
|
|
|
trace!(
|
|
|
- target: "net::hosts::greylist_fetch_address_with_lock()",
|
|
|
+ target: "net::hosts::whitelist_fetch_address_with_lock()",
|
|
|
"Host '{}' exists so skipping",
|
|
|
host
|
|
|
);
|
|
|
@@ -230,7 +235,7 @@ impl Hosts {
|
|
|
// Check if we already have this configured as a manual peer
|
|
|
if self.settings.peers.contains(host) {
|
|
|
trace!(
|
|
|
- target: "net::hosts::greylist_fetch_address_with_lock()",
|
|
|
+ target: "net::hosts::whitelist_fetch_address_with_lock()",
|
|
|
"Host '{}' configured as manual peer so skipping",
|
|
|
host
|
|
|
);
|
|
|
@@ -240,7 +245,7 @@ impl Hosts {
|
|
|
// Obtain a lock on this address to prevent duplicate connection
|
|
|
if !p2p.add_pending(host).await {
|
|
|
trace!(
|
|
|
- target: "net::hosts::greylist_fetch_address_with_lock()",
|
|
|
+ target: "net::hosts::whitelist_fetch_address_with_lock()",
|
|
|
"Host '{}' pending so skipping",
|
|
|
host
|
|
|
);
|
|
|
@@ -248,7 +253,7 @@ impl Hosts {
|
|
|
}
|
|
|
|
|
|
trace!(
|
|
|
- target: "net::hosts::greylist_fetch_address_with_lock()",
|
|
|
+ target: "net::hosts::whitelist_fetch_address_with_lock()",
|
|
|
"Found valid host '{}",
|
|
|
host
|
|
|
);
|
|
|
@@ -258,6 +263,11 @@ impl Hosts {
|
|
|
None
|
|
|
}
|
|
|
|
|
|
+ /// Loops through anchorlist addresses to find an outbound address that we can
|
|
|
+ /// connect to. Check whether the address is valid by making sure it isn't
|
|
|
+ /// our own inbound address, then checks whether it is already connected
|
|
|
+ /// (exists) or connecting (pending).
|
|
|
+ /// Lastly adds matching address to the pending list.
|
|
|
pub async fn anchorlist_fetch_address_with_lock(
|
|
|
&self,
|
|
|
p2p: P2pPtr,
|
|
|
@@ -340,29 +350,8 @@ impl Hosts {
|
|
|
None
|
|
|
}
|
|
|
|
|
|
- // Store the address in the whitelist if we don't have it.
|
|
|
- // Otherwise, update the last_seen field.
|
|
|
- pub async fn whitelist_store_or_update(&self, addrs: &[(Url, u64)]) -> Result<()> {
|
|
|
- debug!(target: "net::hosts::whitelist_store_or_update()", "[START]");
|
|
|
-
|
|
|
- // No address filtering for whitelist (whitelist is created from greylist)
|
|
|
- for (addr, last_seen) in addrs {
|
|
|
- if !self.whitelist_contains(addr).await {
|
|
|
- debug!(target: "net::hosts::whitelist_store_or_update()",
|
|
|
- "We do not have this entry in the whitelist. Adding to store...");
|
|
|
-
|
|
|
- self.whitelist_store(addr.clone(), last_seen.clone()).await;
|
|
|
- } else {
|
|
|
- debug!(target: "net::hosts::whitelist_store_or_update()",
|
|
|
- "We have this entry in the whitelist. Updating last seen...");
|
|
|
-
|
|
|
- let index = self.get_whitelist_index_at_addr(addr).await?;
|
|
|
- self.whitelist_update_last_seen(addr, last_seen.clone(), index).await;
|
|
|
- }
|
|
|
- }
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
+ /// Stores an address on the greylist or updates its last_seen field if we already
|
|
|
+ /// have the address.
|
|
|
pub async fn greylist_store_or_update(&self, addrs: &[(Url, u64)]) -> Result<()> {
|
|
|
debug!(target: "store::greylist_store_or_update()", "[START]");
|
|
|
|
|
|
@@ -386,6 +375,31 @@ impl Hosts {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
+ /// Stores an address on the whitelist or updates its last_seen field if we already
|
|
|
+ /// have the address.
|
|
|
+ pub async fn whitelist_store_or_update(&self, addrs: &[(Url, u64)]) -> Result<()> {
|
|
|
+ debug!(target: "net::hosts::whitelist_store_or_update()", "[START]");
|
|
|
+
|
|
|
+ // No address filtering for whitelist (whitelist is created from greylist)
|
|
|
+ for (addr, last_seen) in addrs {
|
|
|
+ if !self.whitelist_contains(addr).await {
|
|
|
+ debug!(target: "net::hosts::whitelist_store_or_update()",
|
|
|
+ "We do not have this entry in the whitelist. Adding to store...");
|
|
|
+
|
|
|
+ self.whitelist_store(addr.clone(), last_seen.clone()).await;
|
|
|
+ } else {
|
|
|
+ debug!(target: "net::hosts::whitelist_store_or_update()",
|
|
|
+ "We have this entry in the whitelist. Updating last seen...");
|
|
|
+
|
|
|
+ let index = self.get_whitelist_index_at_addr(addr).await?;
|
|
|
+ self.whitelist_update_last_seen(addr, last_seen.clone(), index).await;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Ok(())
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Stores an address on the anchorlist or updates its last_seen field if we already
|
|
|
+ /// have the address.
|
|
|
pub async fn anchorlist_store_or_update(&self, addrs: &[(Url, u64)]) -> Result<()> {
|
|
|
debug!(target: "store::anchor_store_or_update()", "[START]");
|
|
|
|
|
|
@@ -407,7 +421,7 @@ impl Hosts {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
- // Append host to the greylist. Called on learning of a new peer.
|
|
|
+ /// Append host to the greylist. Called on learning of a new peer.
|
|
|
pub async fn greylist_store(&self, addr: Url, last_seen: u64) {
|
|
|
debug!(target: "net::hosts::greylist_store()", "hosts::greylist_store() [START]");
|
|
|
|
|
|
@@ -427,7 +441,7 @@ impl Hosts {
|
|
|
debug!(target: "net::hosts::greylist_store()", "[END]");
|
|
|
}
|
|
|
|
|
|
- // Append host to the whitelist. Called after a successful interaction with an online peer.
|
|
|
+ /// Append host to the whitelist. Called after a successful interaction with an online peer.
|
|
|
pub async fn whitelist_store(&self, addr: Url, last_seen: u64) {
|
|
|
debug!(target: "net::hosts::whitelist_store()", "[START]");
|
|
|
|
|
|
@@ -447,6 +461,24 @@ impl Hosts {
|
|
|
debug!(target: "store::whitelist_store()", "[END]");
|
|
|
}
|
|
|
|
|
|
+ /// Append host to the anchorlist. Called after we have successfully established a connection
|
|
|
+ /// to a peer.
|
|
|
+ pub async fn anchorlist_store(&self, addr: Url, last_seen: u64) {
|
|
|
+ debug!(target: "net::hosts::anchorlist_store()", "[START]");
|
|
|
+
|
|
|
+ let mut anchorlist = self.anchorlist.write().await;
|
|
|
+
|
|
|
+ debug!(target: "net::hosts::anchorlist_store()", "Inserting {}", addr);
|
|
|
+ anchorlist.push((addr, last_seen));
|
|
|
+
|
|
|
+ // Sort the list by last_seen.
|
|
|
+ anchorlist.sort_by_key(|entry| entry.1);
|
|
|
+ debug!(target: "net::hosts::anchorlist_store()", "[END]");
|
|
|
+ }
|
|
|
+
|
|
|
+ // Downgrade a non-responsive host.
|
|
|
+ // TODO: it is perhaps more efficient simply to select another connection and allow
|
|
|
+ // the greylist refinery process to filter address.
|
|
|
pub async fn downgrade_host(&self, addr: &Url) -> Result<()> {
|
|
|
if self.anchorlist_contains(addr).await {
|
|
|
debug!(target: "net::store::downgrade_host()",
|
|
|
@@ -466,7 +498,7 @@ impl Hosts {
|
|
|
Ok(())
|
|
|
} else {
|
|
|
debug!(target: "net::store::downgrade_host()",
|
|
|
- "Greylist entry detected! Do nothing for now...");
|
|
|
+ "Removing non responsive peer from greylist");
|
|
|
let index = self.get_greylist_index_at_addr(addr).await?;
|
|
|
self.greylist_remove(addr, index).await;
|
|
|
|
|
|
@@ -474,22 +506,21 @@ impl Hosts {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Append host to the anchorlist. Called after we have established a successful connection to a
|
|
|
- // peer.
|
|
|
- pub async fn anchorlist_store(&self, addr: Url, last_seen: u64) {
|
|
|
- debug!(target: "net::hosts::anchorlist_store()", "[START]");
|
|
|
+ /// Update the last_seen field of a peer on the greylist.
|
|
|
+ pub async fn greylist_update_last_seen(&self, addr: &Url, last_seen: u64, index: usize) {
|
|
|
+ debug!(target: "net::hosts::greylist_update_last_seen()", "[START]");
|
|
|
|
|
|
- let mut anchorlist = self.anchorlist.write().await;
|
|
|
+ let mut greylist = self.greylist.write().await;
|
|
|
|
|
|
- debug!(target: "net::hosts::anchorlist_store()", "Inserting {}", addr);
|
|
|
- anchorlist.push((addr, last_seen));
|
|
|
+ greylist[index] = (addr.clone(), last_seen);
|
|
|
|
|
|
// Sort the list by last_seen.
|
|
|
- anchorlist.sort_by_key(|entry| entry.1);
|
|
|
- debug!(target: "net::hosts::anchorlist_store()", "[END]");
|
|
|
+ greylist.sort_by_key(|entry| entry.1);
|
|
|
+
|
|
|
+ debug!(target: "store::greylist_update_last_seen()", "[END]");
|
|
|
}
|
|
|
|
|
|
- // Update the last_seen field of a peer on the whitelist.
|
|
|
+ /// Update the last_seen field of a peer on the whitelist.
|
|
|
pub async fn whitelist_update_last_seen(&self, addr: &Url, last_seen: u64, index: usize) {
|
|
|
debug!(target: "store::whitelist_update_last_seen()", "[START]");
|
|
|
|
|
|
@@ -503,21 +534,7 @@ impl Hosts {
|
|
|
debug!(target: "store::whitelist_update_last_seen()", "[END]");
|
|
|
}
|
|
|
|
|
|
- // Update the last_seen field of a peer on the greylist.
|
|
|
- pub async fn greylist_update_last_seen(&self, addr: &Url, last_seen: u64, index: usize) {
|
|
|
- debug!(target: "net::hosts::greylist_update_last_seen()", "[START]");
|
|
|
-
|
|
|
- let mut greylist = self.greylist.write().await;
|
|
|
-
|
|
|
- greylist[index] = (addr.clone(), last_seen);
|
|
|
-
|
|
|
- // Sort the list by last_seen.
|
|
|
- greylist.sort_by_key(|entry| entry.1);
|
|
|
-
|
|
|
- debug!(target: "store::greylist_update_last_seen()", "[END]");
|
|
|
- }
|
|
|
-
|
|
|
- // Update the last_seen field of a peer on the anchorlist.
|
|
|
+ /// Update the last_seen field of a peer on the anchorlist.
|
|
|
pub async fn anchorlist_update_last_seen(&self, addr: &Url, last_seen: u64, index: usize) {
|
|
|
debug!(target: "store::anchorlist_update_last_seen()", "[START]");
|
|
|
|
|
|
@@ -531,6 +548,7 @@ impl Hosts {
|
|
|
debug!(target: "store::anchorlist_update_last_seen()", "[END]");
|
|
|
}
|
|
|
|
|
|
+ /// Remove an entry from the greylist.
|
|
|
pub async fn greylist_remove(&self, addr: &Url, position: usize) {
|
|
|
debug!(target: "net::refinery::run()", "Removing whitelisted peer {} from greylist", addr);
|
|
|
let mut greylist = self.greylist.write().await;
|
|
|
@@ -541,16 +559,7 @@ impl Hosts {
|
|
|
greylist.sort_by_key(|entry| entry.1);
|
|
|
}
|
|
|
|
|
|
- pub async fn anchorlist_remove(&self, addr: &Url, position: usize) {
|
|
|
- debug!(target: "net::refinery::run()", "Removing disconnected peer {} from anchorlist", addr);
|
|
|
- let mut anchorlist = self.anchorlist.write().await;
|
|
|
-
|
|
|
- anchorlist.remove(position);
|
|
|
-
|
|
|
- // Sort the list by last_seen.
|
|
|
- anchorlist.sort_by_key(|entry| entry.1);
|
|
|
- }
|
|
|
-
|
|
|
+ /// Remove an entry from the whitelist.
|
|
|
pub async fn whitelist_remove(&self, addr: &Url, position: usize) {
|
|
|
debug!(target: "net::refinery::run()", "Removing disconnected peer {} from whitelist", addr);
|
|
|
let mut whitelist = self.whitelist.write().await;
|
|
|
@@ -561,6 +570,17 @@ impl Hosts {
|
|
|
whitelist.sort_by_key(|entry| entry.1);
|
|
|
}
|
|
|
|
|
|
+ /// Remove an entry from the anchorlist.
|
|
|
+ pub async fn anchorlist_remove(&self, addr: &Url, position: usize) {
|
|
|
+ debug!(target: "net::refinery::run()", "Removing disconnected peer {} from anchorlist", addr);
|
|
|
+ let mut anchorlist = self.anchorlist.write().await;
|
|
|
+
|
|
|
+ anchorlist.remove(position);
|
|
|
+
|
|
|
+ // Sort the list by last_seen.
|
|
|
+ anchorlist.sort_by_key(|entry| entry.1);
|
|
|
+ }
|
|
|
+
|
|
|
pub async fn subscribe_store(&self) -> Result<Subscription<usize>> {
|
|
|
let sub = self.store_subscriber.clone().subscribe().await;
|
|
|
Ok(sub)
|
|
|
@@ -571,6 +591,7 @@ impl Hosts {
|
|
|
// `Hosts`. For this reason, it might make more sense
|
|
|
// to move this function to a more appropriate location
|
|
|
// in the codebase.
|
|
|
+ /// Check whether a URL is local host
|
|
|
pub async fn is_local_host(&self, url: Url) -> bool {
|
|
|
// Reject Urls without host strings.
|
|
|
if url.host_str().is_none() {
|
|
|
@@ -781,10 +802,10 @@ impl Hosts {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
- /// Get the index for a given addr on the anchorlist.
|
|
|
- pub async fn get_anchorlist_index_at_addr(&self, addr: &Url) -> Result<usize> {
|
|
|
- let anchorlist = self.anchorlist.read().await;
|
|
|
- for (i, (url, time)) in anchorlist.iter().enumerate() {
|
|
|
+ /// Get the index for a given addr on the greylist.
|
|
|
+ pub async fn get_greylist_index_at_addr(&self, addr: &Url) -> Result<usize> {
|
|
|
+ let greylist = self.greylist.read().await;
|
|
|
+ for (i, (url, _time)) in greylist.iter().enumerate() {
|
|
|
if url == addr {
|
|
|
return Ok(i)
|
|
|
}
|
|
|
@@ -803,10 +824,10 @@ impl Hosts {
|
|
|
return Err(Error::HostDoesNotExist)
|
|
|
}
|
|
|
|
|
|
- /// Get the index for a given addr on the greylist.
|
|
|
- pub async fn get_greylist_index_at_addr(&self, addr: &Url) -> Result<usize> {
|
|
|
- let greylist = self.greylist.read().await;
|
|
|
- for (i, (url, _time)) in greylist.iter().enumerate() {
|
|
|
+ /// Get the index for a given addr on the anchorlist.
|
|
|
+ pub async fn get_anchorlist_index_at_addr(&self, addr: &Url) -> Result<usize> {
|
|
|
+ let anchorlist = self.anchorlist.read().await;
|
|
|
+ for (i, (url, time)) in anchorlist.iter().enumerate() {
|
|
|
if url == addr {
|
|
|
return Ok(i)
|
|
|
}
|
|
|
@@ -865,6 +886,7 @@ impl Hosts {
|
|
|
urls.iter().map(|&url| url.clone()).collect()
|
|
|
}
|
|
|
|
|
|
+ /// Get up to a random peer from the greylist.
|
|
|
pub async fn greylist_fetch_random(&self) -> ((Url, u64), usize) {
|
|
|
let greylist = self.greylist.read().await;
|
|
|
let position = rand::thread_rng().gen_range(0..greylist.len());
|
|
|
@@ -896,8 +918,53 @@ impl Hosts {
|
|
|
let urls = hosts.iter().choose_multiple(&mut OsRng, n.min(hosts.len()));
|
|
|
urls.iter().map(|&url| url.clone()).collect()
|
|
|
}
|
|
|
+
|
|
|
+ /// Get up to limit peers that don't match the given transport schemes from the whitelist.
|
|
|
+ /// If limit was not provided, return all matching peers.
|
|
|
+ pub async fn whitelist_fetch_excluding_schemes(
|
|
|
+ &self,
|
|
|
+ schemes: &[String],
|
|
|
+ limit: Option<usize>,
|
|
|
+ ) -> Vec<(Url, u64)> {
|
|
|
+ let addrs = self.whitelist.read().await;
|
|
|
+ let mut limit = match limit {
|
|
|
+ Some(l) => l.min(addrs.len()),
|
|
|
+ None => addrs.len(),
|
|
|
+ };
|
|
|
+ let mut ret = vec![];
|
|
|
+
|
|
|
+ if limit == 0 {
|
|
|
+ return ret
|
|
|
+ }
|
|
|
+
|
|
|
+ for (addr, last_seen) in addrs.iter() {
|
|
|
+ if !schemes.contains(&addr.scheme().to_string()) {
|
|
|
+ ret.push((addr.clone(), *last_seen));
|
|
|
+ limit -= 1;
|
|
|
+ if limit == 0 {
|
|
|
+ return ret
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // If we didn't find any, pick some from the greylist
|
|
|
+ if ret.is_empty() {
|
|
|
+ for (addr, last_seen) in self.greylist.read().await.iter() {
|
|
|
+ if !schemes.contains(&addr.scheme().to_string()) {
|
|
|
+ ret.push((addr.clone(), *last_seen));
|
|
|
+ limit -= 1;
|
|
|
+ if limit == 0 {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- /// Get up to n random whitelisted peers that don't match the given transport schemes from the hosts set.
|
|
|
+ ret
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Get up to n random whitelisted peers that don't match the given transport schemes from the
|
|
|
+ /// hosts set.
|
|
|
pub async fn whitelist_fetch_n_random_excluding_schemes(
|
|
|
&self,
|
|
|
schemes: &[String],
|
|
|
@@ -911,6 +978,7 @@ impl Hosts {
|
|
|
|
|
|
// Retrieve all peers not corresponding to that transport schemes
|
|
|
let hosts = self.whitelist_fetch_excluding_schemes(schemes, None).await;
|
|
|
+
|
|
|
if hosts.is_empty() {
|
|
|
debug!(target: "store::whitelist_fetch_n_random_excluding_schemes",
|
|
|
"Whitelist is empty! Exiting...");
|
|
|
@@ -922,6 +990,42 @@ impl Hosts {
|
|
|
urls.iter().map(|&url| url.clone()).collect()
|
|
|
}
|
|
|
|
|
|
+ /// Get up to limit peers that match the given transport schemes from the greylist.
|
|
|
+ /// If limit was not provided, return all matching peers.
|
|
|
+ async fn greylist_fetch_with_schemes(
|
|
|
+ &self,
|
|
|
+ schemes: &[String],
|
|
|
+ limit: Option<usize>,
|
|
|
+ ) -> Vec<(Url, u64)> {
|
|
|
+ debug!(target: "store::greylist_fetch_with_schemes", "[START]");
|
|
|
+ let greylist = self.greylist.read().await;
|
|
|
+
|
|
|
+ let mut limit = match limit {
|
|
|
+ Some(l) => l.min(greylist.len()),
|
|
|
+ None => greylist.len(),
|
|
|
+ };
|
|
|
+ let mut ret = vec![];
|
|
|
+
|
|
|
+ if limit == 0 {
|
|
|
+ return ret
|
|
|
+ }
|
|
|
+
|
|
|
+ for (addr, last_seen) in greylist.iter() {
|
|
|
+ if schemes.contains(&addr.scheme().to_string()) {
|
|
|
+ ret.push((addr.clone(), *last_seen));
|
|
|
+ limit -= 1;
|
|
|
+ if limit == 0 {
|
|
|
+ debug!(target: "store::greylist_fetch_with_schemes", "Found matching scheme, returning");
|
|
|
+ return ret
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ debug!(target: "store::greylist_fetch_with_schemes", "END");
|
|
|
+
|
|
|
+ ret
|
|
|
+ }
|
|
|
+
|
|
|
/// Get up to limit peers that match the given transport schemes from the whitelist.
|
|
|
/// If limit was not provided, return all matching peers.
|
|
|
async fn whitelist_fetch_with_schemes(
|
|
|
@@ -935,7 +1039,7 @@ impl Hosts {
|
|
|
if !self.is_empty_whitelist().await {
|
|
|
let whitelist = self.whitelist.read().await;
|
|
|
|
|
|
- let mut limit = match limit {
|
|
|
+ let mut parsed_limit = match limit {
|
|
|
Some(l) => l.min(whitelist.len()),
|
|
|
None => whitelist.len(),
|
|
|
};
|
|
|
@@ -943,43 +1047,23 @@ impl Hosts {
|
|
|
for (addr, last_seen) in whitelist.iter() {
|
|
|
if schemes.contains(&addr.scheme().to_string()) {
|
|
|
ret.push((addr.clone(), *last_seen));
|
|
|
- limit -= 1;
|
|
|
- if limit == 0 {
|
|
|
+ parsed_limit -= 1;
|
|
|
+ if parsed_limit == 0 {
|
|
|
debug!(target: "store::whitelist_fetch_with_schemes",
|
|
|
"Found matching white scheme, returning");
|
|
|
return ret
|
|
|
}
|
|
|
} else {
|
|
|
- // TODO: select from greylist?
|
|
|
debug!(target: "store::whitelist_fetch_with_schemes",
|
|
|
- "No matching schemes");
|
|
|
+ "No matching schemes! Trying greylist...");
|
|
|
+ return self.greylist_fetch_with_schemes(schemes, limit).await
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
// Whitelist is empty!
|
|
|
if !self.is_empty_greylist().await {
|
|
|
- // Select from the anchorlist providing it's not empty.
|
|
|
- let greylist = self.greylist.read().await;
|
|
|
-
|
|
|
- let mut limit = match limit {
|
|
|
- Some(l) => l.min(greylist.len()),
|
|
|
- None => greylist.len(),
|
|
|
- };
|
|
|
-
|
|
|
- for (addr, last_seen) in greylist.iter() {
|
|
|
- if schemes.contains(&addr.scheme().to_string()) {
|
|
|
- ret.push((addr.clone(), *last_seen));
|
|
|
- limit -= 1;
|
|
|
- if limit == 0 {
|
|
|
- debug!(target: "store::whitelist_fetch_with_schemes",
|
|
|
- "Found matching greylist scheme, returning");
|
|
|
- return ret
|
|
|
- }
|
|
|
- } else {
|
|
|
- debug!(target: "store::whitelist_fetch_with_schemes",
|
|
|
- "No matching schemes");
|
|
|
- }
|
|
|
- }
|
|
|
+ // Select from the greylist providing it's not empty.
|
|
|
+ return self.greylist_fetch_with_schemes(schemes, limit).await
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -988,40 +1072,8 @@ impl Hosts {
|
|
|
ret
|
|
|
}
|
|
|
|
|
|
- async fn greylist_fetch_with_schemes(
|
|
|
- &self,
|
|
|
- schemes: &[String],
|
|
|
- limit: Option<usize>,
|
|
|
- ) -> Vec<(Url, u64)> {
|
|
|
- debug!(target: "store::greylist_fetch_with_schemes", "[START]");
|
|
|
- let greylist = self.greylist.read().await;
|
|
|
-
|
|
|
- let mut limit = match limit {
|
|
|
- Some(l) => l.min(greylist.len()),
|
|
|
- None => greylist.len(),
|
|
|
- };
|
|
|
- let mut ret = vec![];
|
|
|
-
|
|
|
- if limit == 0 {
|
|
|
- return ret
|
|
|
- }
|
|
|
-
|
|
|
- for (addr, last_seen) in greylist.iter() {
|
|
|
- if schemes.contains(&addr.scheme().to_string()) {
|
|
|
- ret.push((addr.clone(), *last_seen));
|
|
|
- limit -= 1;
|
|
|
- if limit == 0 {
|
|
|
- debug!(target: "store::greylist_fetch_with_schemes", "Found matching scheme, returning");
|
|
|
- return ret
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- debug!(target: "store::greylist_fetch_with_schemes", "END");
|
|
|
-
|
|
|
- ret
|
|
|
- }
|
|
|
-
|
|
|
+ /// Get up to limit peers that match the given transport schemes from the anchorlist.
|
|
|
+ /// If limit was not provided, return all matching peers.
|
|
|
async fn anchorlist_fetch_with_schemes(
|
|
|
&self,
|
|
|
schemes: &[String],
|
|
|
@@ -1034,7 +1086,7 @@ impl Hosts {
|
|
|
// Select from the anchorlist providing it's not empty.
|
|
|
let anchorlist = self.anchorlist.read().await;
|
|
|
|
|
|
- let mut limit = match limit {
|
|
|
+ let mut parsed_limit = match limit {
|
|
|
Some(l) => l.min(anchorlist.len()),
|
|
|
None => anchorlist.len(),
|
|
|
};
|
|
|
@@ -1042,71 +1094,27 @@ impl Hosts {
|
|
|
for (addr, last_seen) in anchorlist.iter() {
|
|
|
if schemes.contains(&addr.scheme().to_string()) {
|
|
|
ret.push((addr.clone(), *last_seen));
|
|
|
- limit -= 1;
|
|
|
- if limit == 0 {
|
|
|
+ parsed_limit -= 1;
|
|
|
+ if parsed_limit == 0 {
|
|
|
debug!(target: "store::anchorlist_fetch_with_schemes",
|
|
|
"Found matching anchor scheme, returning {:?}", ret);
|
|
|
return ret
|
|
|
}
|
|
|
} else {
|
|
|
debug!(target: "store::anchorlist_fetch_with_schemes",
|
|
|
- "No matching schemes!!");
|
|
|
+ "No matching schemes! Trying greylist...");
|
|
|
+ return self.whitelist_fetch_with_schemes(schemes, limit).await
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
// Anchorlist is empty!
|
|
|
if !self.is_empty_whitelist().await {
|
|
|
- // Select from the whitelist providing it's not empty.
|
|
|
- let whitelist = self.whitelist.read().await;
|
|
|
-
|
|
|
- let mut limit = match limit {
|
|
|
- Some(l) => l.min(whitelist.len()),
|
|
|
- None => whitelist.len(),
|
|
|
- };
|
|
|
-
|
|
|
- if limit == 0 {
|
|
|
- return ret
|
|
|
- }
|
|
|
-
|
|
|
- for (addr, last_seen) in whitelist.iter() {
|
|
|
- if schemes.contains(&addr.scheme().to_string()) {
|
|
|
- ret.push((addr.clone(), *last_seen));
|
|
|
- limit -= 1;
|
|
|
- if limit == 0 {
|
|
|
- debug!(target: "store::anchorlist_fetch_with_schemes",
|
|
|
- "Found matching white scheme, returning {:?}", ret);
|
|
|
- return ret
|
|
|
- }
|
|
|
- } else {
|
|
|
- debug!(target: "store::anchorlist_fetch_with_schemes",
|
|
|
- "No matching schemes!!");
|
|
|
- }
|
|
|
- }
|
|
|
+ return self.whitelist_fetch_with_schemes(schemes, limit).await
|
|
|
} else {
|
|
|
// Whitelist is empty!
|
|
|
if !self.is_empty_greylist().await {
|
|
|
- // Select from the anchorlist providing it's not empty.
|
|
|
- let greylist = self.greylist.read().await;
|
|
|
-
|
|
|
- let mut limit = match limit {
|
|
|
- Some(l) => l.min(greylist.len()),
|
|
|
- None => greylist.len(),
|
|
|
- };
|
|
|
-
|
|
|
- for (addr, last_seen) in greylist.iter() {
|
|
|
- if schemes.contains(&addr.scheme().to_string()) {
|
|
|
- ret.push((addr.clone(), *last_seen));
|
|
|
- limit -= 1;
|
|
|
- if limit == 0 {
|
|
|
- debug!(target: "store::anchorlist_fetch_with_schemes",
|
|
|
- "Found matching grey scheme, returning {:?}", ret);
|
|
|
- return ret
|
|
|
- }
|
|
|
- } else {
|
|
|
- debug!(target: "store::anchorlist_fetch_with_schemes",
|
|
|
- "No matching schemes!!");
|
|
|
- }
|
|
|
- }
|
|
|
+ // Select from the greyist providing it's not empty.
|
|
|
+ return self.greylist_fetch_with_schemes(schemes, limit).await
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -1116,50 +1124,7 @@ impl Hosts {
|
|
|
ret
|
|
|
}
|
|
|
|
|
|
- /// Get up to limit peers that don't match the given transport schemes from the whitelist.
|
|
|
- /// If limit was not provided, return all matching peers.
|
|
|
- pub async fn whitelist_fetch_excluding_schemes(
|
|
|
- &self,
|
|
|
- schemes: &[String],
|
|
|
- limit: Option<usize>,
|
|
|
- ) -> Vec<(Url, u64)> {
|
|
|
- let addrs = self.whitelist.read().await;
|
|
|
- let mut limit = match limit {
|
|
|
- Some(l) => l.min(addrs.len()),
|
|
|
- None => addrs.len(),
|
|
|
- };
|
|
|
- let mut ret = vec![];
|
|
|
-
|
|
|
- if limit == 0 {
|
|
|
- return ret
|
|
|
- }
|
|
|
-
|
|
|
- for (addr, last_seen) in addrs.iter() {
|
|
|
- if !schemes.contains(&addr.scheme().to_string()) {
|
|
|
- ret.push((addr.clone(), *last_seen));
|
|
|
- limit -= 1;
|
|
|
- if limit == 0 {
|
|
|
- return ret
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // If we didn't find any, pick some from the greylist
|
|
|
- if ret.is_empty() {
|
|
|
- for (addr, last_seen) in self.greylist.read().await.iter() {
|
|
|
- if !schemes.contains(&addr.scheme().to_string()) {
|
|
|
- ret.push((addr.clone(), *last_seen));
|
|
|
- limit -= 1;
|
|
|
- if limit == 0 {
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- ret
|
|
|
- }
|
|
|
-
|
|
|
+ /// Load the hostlist from a file.
|
|
|
pub async fn load_hosts(&self) -> Result<()> {
|
|
|
let path = expand_path(&self.settings.hostlist)?;
|
|
|
|
|
|
@@ -1215,7 +1180,7 @@ impl Hosts {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
- // Save the hostlist to a file.
|
|
|
+ /// Save the hostlist to a file.
|
|
|
pub async fn save_hosts(&self) -> Result<()> {
|
|
|
let path = expand_path(&self.settings.hostlist)?;
|
|
|
|