Merge branch 'master' into pibd_peers_fix

This commit is contained in:
ardocrat
2026-04-22 11:08:02 +03:00
6 changed files with 188 additions and 137 deletions
+26 -14
View File
@@ -61,6 +61,7 @@ impl Peers {
/// Adds the peer to our internal peer mapping. Note that the peer is still
/// returned so the server can run it.
pub fn add_connected(&self, peer: Arc<Peer>) -> Result<(), Error> {
let enough_outbound = self.enough_outbound_peers();
let peer_data: PeerData;
{
// Scope for peers vector lock - dont hold the peers lock while adding to lmdb
@@ -76,9 +77,12 @@ impl Peers {
last_banned: 0,
ban_reason: ReasonForBan::None,
last_connected: Utc::now().timestamp(),
last_attempt: Utc::now().timestamp(),
};
debug!("Adding newly connected peer {}.", peer_data.addr);
peers.insert(peer_data.addr, peer);
if !enough_outbound || !peer.info.is_outbound() {
debug!("Adding newly connected peer {}.", peer_data.addr);
peers.insert(peer_data.addr, peer);
}
}
debug!("Saving newly connected peer {}.", peer_data.addr);
if let Err(e) = self.save_peer(&peer_data) {
@@ -98,6 +102,7 @@ impl Peers {
last_banned: Utc::now().timestamp(),
ban_reason,
last_connected: Utc::now().timestamp(),
last_attempt: Utc::now().timestamp(),
};
debug!("Banning peer {}.", addr);
self.save_peer(&peer_data)
@@ -142,6 +147,7 @@ impl Peers {
}
false
}
/// Ban a peer, disconnecting it if we're currently connected
pub fn ban_peer(&self, peer_addr: PeerAddr, ban_reason: ReasonForBan) -> Result<(), Error> {
// Update the peer in peers db
@@ -261,6 +267,8 @@ impl Peers {
break;
}
};
// Mark peer as defunct after ping failure.
let _ = self.update_state(p.info.addr, State::Defunct);
p.stop();
peers.remove(&p.info.addr);
}
@@ -747,21 +755,25 @@ impl NetAdapter for Peers {
trace!("Received {} peer addrs, saving.", peer_addrs.len());
let mut to_save: Vec<PeerData> = Vec::new();
for pa in peer_addrs {
if let Ok(e) = self.exists_peer(pa) {
if e {
if let Ok(mut p) = self.get_peer(pa) {
if p.flags != State::Defunct {
continue;
}
p.flags = State::Unknown;
to_save.push(p);
} else {
let peer = PeerData {
addr: pa,
capabilities: Capabilities::UNKNOWN,
user_agent: "".to_string(),
flags: State::Unknown,
last_banned: 0,
ban_reason: ReasonForBan::None,
last_connected: 0,
last_attempt: 0,
};
to_save.push(peer);
}
let peer = PeerData {
addr: pa,
capabilities: Capabilities::UNKNOWN,
user_agent: "".to_string(),
flags: State::Healthy,
last_banned: 0,
ban_reason: ReasonForBan::None,
last_connected: Utc::now().timestamp(),
};
to_save.push(peer);
}
if let Err(e) = self.save_peers(to_save) {
error!("Could not save received peer addresses: {:?}", e);
+3
View File
@@ -187,6 +187,9 @@ impl Server {
&self.handshake,
self.peers.clone(),
)?;
if self.peers.enough_outbound_peers() {
peer.stop();
}
let peer = Arc::new(peer);
self.peers.add_connected(peer.clone())?;
Ok(peer)
+15 -9
View File
@@ -27,13 +27,14 @@ const STORE_SUBPATH: &str = "peers";
const PEER_PREFIX: u8 = b'P';
// Types of messages
// Types of peers
enum_from_primitive! {
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum State {
Healthy = 0,
Banned = 1,
Defunct = 2,
Unknown = 3,
}
}
@@ -55,6 +56,8 @@ pub struct PeerData {
pub ban_reason: ReasonForBan,
/// Time when we last connected to this peer.
pub last_connected: i64,
/// Time when last connection attempt happened to this peer.
pub last_attempt: i64,
}
impl Writeable for PeerData {
@@ -67,7 +70,8 @@ impl Writeable for PeerData {
[write_u8, self.flags as u8],
[write_i64, self.last_banned],
[write_i32, self.ban_reason as i32],
[write_i64, self.last_connected]
[write_i64, self.last_connected],
[write_i64, self.last_attempt]
);
Ok(())
}
@@ -81,12 +85,10 @@ impl Readable for PeerData {
let (fl, lb, br) = ser_multiread!(reader, read_u8, read_i64, read_i32);
let lc = reader.read_i64();
// this only works because each PeerData is read in its own vector and this
// is the last data element
let last_connected = match lc {
Err(_) => Utc::now().timestamp(),
Ok(lc) => lc,
};
let last_connected = lc.unwrap_or_else(|_| Utc::now().timestamp());
let la = reader.read_i64();
let last_attempt = la.unwrap_or_else(|_| 0);
let user_agent = String::from_utf8(ua).map_err(|_| ser::Error::CorruptedData)?;
let capabilities = Capabilities::from_bits_truncate(capab);
@@ -97,10 +99,11 @@ impl Readable for PeerData {
addr,
capabilities,
user_agent,
flags: flags,
flags,
last_banned: lb,
ban_reason,
last_connected,
last_attempt,
}),
None => Err(ser::Error::CorruptedData),
}
@@ -187,6 +190,7 @@ impl PeerStore {
/// Convenience method to load a peer data, update its status and save it
/// back. If new state is Banned its last banned time will be updated too.
/// If new state is Defunct last connection attempt will be updated too.
pub fn update_state(&self, peer_addr: PeerAddr, new_state: State) -> Result<(), Error> {
let batch = self.db.batch()?;
@@ -197,6 +201,8 @@ impl PeerStore {
peer.flags = new_state;
if new_state == State::Banned {
peer.last_banned = Utc::now().timestamp();
} else {
peer.last_attempt = Utc::now().timestamp();
}
batch.put_ser(&peer_key(peer_addr)[..], &peer)?;
+7 -4
View File
@@ -183,10 +183,13 @@ impl<'de> Visitor<'de> for PeerAddrs {
Ok(ip) => peers.push(PeerAddr(ip)),
// If that fails it's probably a DNS record
Err(_) => {
let socket_addrs = entry.to_socket_addrs().map_err(|_| {
serde::de::Error::custom(format!("Unable to resolve DNS: {}", entry))
})?;
peers.append(&mut socket_addrs.map(PeerAddr).collect());
let socket_addrs: Result<std::vec::IntoIter<SocketAddr>, M::Error> =
entry.to_socket_addrs().map_err(|_| {
serde::de::Error::custom(format!("Unable to resolve DNS: {}", entry))
});
if let Ok(socket_addrs) = socket_addrs {
peers.append(&mut socket_addrs.map(PeerAddr).collect());
}
}
}
}