mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-08-03 04:06:23 -04:00
add penalty for failed connections, increase duration for maintenance
This commit is contained in:
parent
167e07b094
commit
067bf07a83
6 changed files with 78 additions and 22 deletions
|
@ -39,13 +39,13 @@ public class Broadcaster {
|
||||||
receivers.stream()
|
receivers.stream()
|
||||||
.filter(connection -> !connection.getPeersNodeAddressOptional().get().equals(sender))
|
.filter(connection -> !connection.getPeersNodeAddressOptional().get().equals(sender))
|
||||||
.forEach(connection -> {
|
.forEach(connection -> {
|
||||||
log.trace("Broadcast message from " + networkNode.getNodeAddress() + " to " +
|
log.trace("Broadcast message to " +
|
||||||
connection.getPeersNodeAddressOptional().get() + ".");
|
connection.getPeersNodeAddressOptional().get() + ".");
|
||||||
SettableFuture<Connection> future = networkNode.sendMessage(connection, message);
|
SettableFuture<Connection> future = networkNode.sendMessage(connection, message);
|
||||||
Futures.addCallback(future, new FutureCallback<Connection>() {
|
Futures.addCallback(future, new FutureCallback<Connection>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Connection connection) {
|
public void onSuccess(Connection connection) {
|
||||||
log.trace("Broadcast from " + networkNode.getNodeAddress() + " to " + connection + " succeeded.");
|
log.trace("Broadcast to " + connection + " succeeded.");
|
||||||
listeners.stream().forEach(listener -> {
|
listeners.stream().forEach(listener -> {
|
||||||
listener.onBroadcasted(message);
|
listener.onBroadcasted(message);
|
||||||
listeners.remove(listener);
|
listeners.remove(listener);
|
||||||
|
|
|
@ -116,6 +116,7 @@ public class PeerExchangeManager implements MessageListener, ConnectionListener
|
||||||
public void onFault(String errorMessage) {
|
public void onFault(String errorMessage) {
|
||||||
log.trace("PeerExchangeHandshake of outbound connection failed. {} connection= {}",
|
log.trace("PeerExchangeHandshake of outbound connection failed. {} connection= {}",
|
||||||
errorMessage, connection);
|
errorMessage, connection);
|
||||||
|
peerManager.penalizeUnreachablePeer(connection);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
peerExchangeHandshake.onGetPeersRequest((GetPeersRequest) message, connection);
|
peerExchangeHandshake.onGetPeersRequest((GetPeersRequest) message, connection);
|
||||||
|
@ -147,6 +148,7 @@ public class PeerExchangeManager implements MessageListener, ConnectionListener
|
||||||
errorMessage, nodeAddress);
|
errorMessage, nodeAddress);
|
||||||
|
|
||||||
peerExchangeHandshakeMap.remove(nodeAddress);
|
peerExchangeHandshakeMap.remove(nodeAddress);
|
||||||
|
peerManager.penalizeUnreachablePeer(nodeAddress);
|
||||||
if (!remainingNodeAddresses.isEmpty()) {
|
if (!remainingNodeAddresses.isEmpty()) {
|
||||||
log.info("There are remaining nodes available for requesting peers. " +
|
log.info("There are remaining nodes available for requesting peers. " +
|
||||||
"We will try getReportedPeers again.");
|
"We will try getReportedPeers again.");
|
||||||
|
@ -197,16 +199,16 @@ public class PeerExchangeManager implements MessageListener, ConnectionListener
|
||||||
connectToMorePeers();
|
connectToMorePeers();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use all outbound connections older than 4 min. for updating reported peers and make sure we keep the connection alive
|
// Use all outbound connections older than 10 min. for updating reported peers and make sure we keep the connection alive
|
||||||
// Inbound connections should be maintained be the requesting peer
|
// Inbound connections should be maintained be the requesting peer
|
||||||
confirmedConnections.stream()
|
confirmedConnections.stream()
|
||||||
.filter(c -> c.getPeersNodeAddressOptional().isPresent() &&
|
.filter(c -> c.getPeersNodeAddressOptional().isPresent() &&
|
||||||
c instanceof OutboundConnection &&
|
c instanceof OutboundConnection &&
|
||||||
new Date().getTime() - c.getLastActivityDate().getTime() > 4 * 60 * 1000)
|
new Date().getTime() - c.getLastActivityDate().getTime() > 10 * 60 * 1000)
|
||||||
.forEach(c -> UserThread.runAfterRandomDelay(() -> {
|
.forEach(c -> {
|
||||||
log.trace("Call requestReportedPeers from maintainConnections");
|
log.trace("Call requestReportedPeers from maintainConnections");
|
||||||
requestReportedPeers(c.getPeersNodeAddressOptional().get(), new ArrayList<>());
|
requestReportedPeers(c.getPeersNodeAddressOptional().get(), new ArrayList<>());
|
||||||
}, 3, 5));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connectToMorePeers() {
|
private void connectToMorePeers() {
|
||||||
|
@ -228,6 +230,7 @@ public class PeerExchangeManager implements MessageListener, ConnectionListener
|
||||||
!peerManager.isSelf(e) &&
|
!peerManager.isSelf(e) &&
|
||||||
!peerManager.isConfirmed(e))
|
!peerManager.isConfirmed(e))
|
||||||
.collect(Collectors.toSet()));
|
.collect(Collectors.toSet()));
|
||||||
|
log.info("Sorted and filtered list: list.size()=" + list.size());
|
||||||
log.trace("Sorted and filtered list: list=" + list);
|
log.trace("Sorted and filtered list: list=" + list);
|
||||||
if (!list.isEmpty()) {
|
if (!list.isEmpty()) {
|
||||||
NodeAddress nextCandidate = list.get(0);
|
NodeAddress nextCandidate = list.get(0);
|
||||||
|
|
|
@ -44,6 +44,7 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
|
|
||||||
private static final int MAX_REPORTED_PEERS = 1000;
|
private static final int MAX_REPORTED_PEERS = 1000;
|
||||||
private static final int MAX_PERSISTED_PEERS = 500;
|
private static final int MAX_PERSISTED_PEERS = 500;
|
||||||
|
private static final long MAX_AGE = 14 * 24 * 60 * 60 * 1000; // max age for reported peers is 14 days
|
||||||
|
|
||||||
|
|
||||||
private final NetworkNode networkNode;
|
private final NetworkNode networkNode;
|
||||||
|
@ -68,9 +69,13 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
createDbStorage(storageDir);
|
createDbStorage(storageDir);
|
||||||
|
|
||||||
connectionNodeAddressListener = (observable, oldValue, newValue) -> {
|
connectionNodeAddressListener = (observable, oldValue, newValue) -> {
|
||||||
|
// Every time we get a new peer connected with a known address we check if we need to remove peers
|
||||||
printConnectedPeers();
|
printConnectedPeers();
|
||||||
if (checkMaxConnectionsTimer == null && newValue != null)
|
if (checkMaxConnectionsTimer == null && newValue != null)
|
||||||
checkMaxConnectionsTimer = UserThread.runAfter(() -> checkMaxConnections(MAX_CONNECTIONS), 3);
|
checkMaxConnectionsTimer = UserThread.runAfter(() -> {
|
||||||
|
removeTooOldReportedPeers();
|
||||||
|
checkMaxConnections(MAX_CONNECTIONS);
|
||||||
|
}, 3);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +123,12 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
@Override
|
@Override
|
||||||
public void onDisconnect(Reason reason, Connection connection) {
|
public void onDisconnect(Reason reason, Connection connection) {
|
||||||
connection.getNodeAddressProperty().removeListener(connectionNodeAddressListener);
|
connection.getNodeAddressProperty().removeListener(connectionNodeAddressListener);
|
||||||
//connection.getPeersNodeAddressOptional().ifPresent(this::removePeer);
|
connection.getPeersNodeAddressOptional().ifPresent(nodeAddress -> {
|
||||||
|
ReportedPeer reportedPeer = new ReportedPeer(nodeAddress);
|
||||||
|
reportedPeers.remove(reportedPeer);
|
||||||
|
persistedPeers.add(reportedPeer);
|
||||||
|
dbStorage.queueUpForSave(persistedPeers, 5000);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -203,6 +213,18 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeTooOldReportedPeers() {
|
||||||
|
Set<ReportedPeer> reportedPeersToRemove = reportedPeers.stream()
|
||||||
|
.filter(reportedPeer -> new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
reportedPeersToRemove.forEach(this::removeReportedPeer);
|
||||||
|
|
||||||
|
Set<ReportedPeer> persistedPeersToRemove = persistedPeers.stream()
|
||||||
|
.filter(reportedPeer -> new Date().getTime() - reportedPeer.lastActivityDate.getTime() > MAX_AGE)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
persistedPeersToRemove.forEach(this::removeFromPersistedPeers);
|
||||||
|
}
|
||||||
|
|
||||||
private void removeSuperfluousSeedNodes() {
|
private void removeSuperfluousSeedNodes() {
|
||||||
Set<Connection> allConnections = networkNode.getAllConnections();
|
Set<Connection> allConnections = networkNode.getAllConnections();
|
||||||
if (allConnections.size() > MAX_CONNECTIONS_EXTENDED_1) {
|
if (allConnections.size() > MAX_CONNECTIONS_EXTENDED_1) {
|
||||||
|
@ -299,7 +321,7 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dbStorage != null)
|
if (dbStorage != null)
|
||||||
dbStorage.queueUpForSave(persistedPeers);
|
dbStorage.queueUpForSave(persistedPeers, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
printReportedPeers();
|
printReportedPeers();
|
||||||
|
@ -342,6 +364,31 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
return networkNode.getNodeAddressesOfConfirmedConnections().size() >= MIN_CONNECTIONS;
|
return networkNode.getNodeAddressesOfConfirmedConnections().size() >= MIN_CONNECTIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void penalizeUnreachablePeer(Connection connection) {
|
||||||
|
connection.getPeersNodeAddressOptional().ifPresent(this::penalizeUnreachablePeer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void penalizeUnreachablePeer(NodeAddress nodeAddress) {
|
||||||
|
reportedPeers.stream()
|
||||||
|
.filter(reportedPeer -> reportedPeer.nodeAddress.equals(nodeAddress))
|
||||||
|
.findAny()
|
||||||
|
.ifPresent(this::adjustLastActivityDate);
|
||||||
|
persistedPeers.stream()
|
||||||
|
.filter(reportedPeer -> reportedPeer.nodeAddress.equals(nodeAddress))
|
||||||
|
.findAny()
|
||||||
|
.ifPresent(reportedPeer -> {
|
||||||
|
adjustLastActivityDate(reportedPeer);
|
||||||
|
dbStorage.queueUpForSave(persistedPeers, 5000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void adjustLastActivityDate(ReportedPeer reportedPeer) {
|
||||||
|
long now = new Date().getTime();
|
||||||
|
long diff = now - reportedPeer.lastActivityDate.getTime();
|
||||||
|
long reduced = now - diff * 2;
|
||||||
|
reportedPeer.setLastActivityDate(new Date(reduced));
|
||||||
|
}
|
||||||
|
|
||||||
public Set<ReportedPeer> getConnectedAndReportedPeers() {
|
public Set<ReportedPeer> getConnectedAndReportedPeers() {
|
||||||
Set<ReportedPeer> result = new HashSet<>(reportedPeers);
|
Set<ReportedPeer> result = new HashSet<>(reportedPeers);
|
||||||
result.addAll(getConnectedPeers());
|
result.addAll(getConnectedPeers());
|
||||||
|
@ -443,5 +490,4 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
log.info(result.toString());
|
log.info(result.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ public class ReportedPeer implements Serializable {
|
||||||
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
|
||||||
|
|
||||||
public final NodeAddress nodeAddress;
|
public final NodeAddress nodeAddress;
|
||||||
public final Date lastActivityDate;
|
public Date lastActivityDate;
|
||||||
|
|
||||||
public ReportedPeer(NodeAddress nodeAddress, Date lastActivityDate) {
|
public ReportedPeer(NodeAddress nodeAddress, Date lastActivityDate) {
|
||||||
this.nodeAddress = nodeAddress;
|
this.nodeAddress = nodeAddress;
|
||||||
|
@ -22,6 +22,10 @@ public class ReportedPeer implements Serializable {
|
||||||
this(nodeAddress, null);
|
this(nodeAddress, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLastActivityDate(Date lastActivityDate) {
|
||||||
|
this.lastActivityDate = lastActivityDate;
|
||||||
|
}
|
||||||
|
|
||||||
// We don't use the lastActivityDate for identity
|
// We don't use the lastActivityDate for identity
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
|
|
|
@ -126,6 +126,7 @@ public class RequestDataManager implements MessageListener {
|
||||||
public void onFault(String errorMessage) {
|
public void onFault(String errorMessage) {
|
||||||
log.trace("RequestDataHandshake of inbound connection failed. {} Connection= {}",
|
log.trace("RequestDataHandshake of inbound connection failed. {} Connection= {}",
|
||||||
errorMessage, connection);
|
errorMessage, connection);
|
||||||
|
peerManager.penalizeUnreachablePeer(connection);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
requestDataHandshake.onDataRequest(message, connection);
|
requestDataHandshake.onDataRequest(message, connection);
|
||||||
|
@ -170,6 +171,9 @@ public class RequestDataManager implements MessageListener {
|
||||||
public void onFault(String errorMessage) {
|
public void onFault(String errorMessage) {
|
||||||
log.trace("RequestDataHandshake of outbound connection failed. {} nodeAddress= {}",
|
log.trace("RequestDataHandshake of outbound connection failed. {} nodeAddress= {}",
|
||||||
errorMessage, nodeAddress);
|
errorMessage, nodeAddress);
|
||||||
|
|
||||||
|
peerManager.penalizeUnreachablePeer(nodeAddress);
|
||||||
|
|
||||||
if (!remainingNodeAddresses.isEmpty()) {
|
if (!remainingNodeAddresses.isEmpty()) {
|
||||||
log.info("There are remaining nodes available for requesting data. " +
|
log.info("There are remaining nodes available for requesting data. " +
|
||||||
"We will try requestDataFromPeers again.");
|
"We will try requestDataFromPeers again.");
|
||||||
|
|
|
@ -160,14 +160,11 @@ public class P2PDataStorage implements MessageListener {
|
||||||
storage.queueUpForSave(sequenceNumberMap, 5000);
|
storage.queueUpForSave(sequenceNumberMap, 5000);
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n");
|
StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n");
|
||||||
sb.append("Data set after addProtectedExpirableData:");
|
sb.append("Data set after addProtectedExpirableData (truncated)");
|
||||||
if (map.values().size() < 10)
|
map.values().stream().forEach(e -> sb.append("\n").append(e.toString().substring(0, 40)).append("...\n"));
|
||||||
map.values().stream().forEach(e -> sb.append("\n").append(e.toString()).append("\n"));
|
|
||||||
else
|
|
||||||
map.values().stream().forEach(e -> sb.append("\n").append("Truncated logs:").append(map.values().size())
|
|
||||||
.append(" entries\n").append(e.toString().substring(0, 40)).append("...\n"));
|
|
||||||
sb.append("\n------------------------------------------------------------\n");
|
sb.append("\n------------------------------------------------------------\n");
|
||||||
log.info(sb.toString());
|
log.trace(sb.toString());
|
||||||
|
log.info("Data set after addProtectedExpirableData: size=" + map.values().size());
|
||||||
|
|
||||||
if (rePublish || !containsKey)
|
if (rePublish || !containsKey)
|
||||||
broadcast(new AddDataMessage(protectedData), sender);
|
broadcast(new AddDataMessage(protectedData), sender);
|
||||||
|
@ -282,10 +279,12 @@ public class P2PDataStorage implements MessageListener {
|
||||||
hashMapChangedListeners.stream().forEach(e -> e.onRemoved(protectedData));
|
hashMapChangedListeners.stream().forEach(e -> e.onRemoved(protectedData));
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n" +
|
StringBuilder sb = new StringBuilder("\n\n------------------------------------------------------------\n" +
|
||||||
"Data set after removeProtectedExpirableData:");
|
"Data set after removeProtectedExpirableData: (truncated)");
|
||||||
map.values().stream().forEach(e -> sb.append("\n").append(e.toString()));
|
map.values().stream().forEach(e -> sb.append("\n").append(e.toString().substring(0, 40)).append("...\n"));
|
||||||
sb.append("\n------------------------------------------------------------\n");
|
sb.append("\n------------------------------------------------------------\n");
|
||||||
log.info(sb.toString());
|
log.trace(sb.toString());
|
||||||
|
log.info("Data set after addProtectedExpirableData: size=" + map.values().size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSequenceNrValid(ProtectedData data, ByteArray hashOfData) {
|
private boolean isSequenceNrValid(ProtectedData data, ByteArray hashOfData) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue