Skip to content

Commit

Permalink
Merge pull request #5057 from chimp1984/fix-premature-disconnections-…
Browse files Browse the repository at this point in the history
…from-seeds

Fix premature disconnections from seeds
  • Loading branch information
sqrrm authored Jan 12, 2021
2 parents e565a18 + 3f8972b commit fea52f0
Show file tree
Hide file tree
Showing 37 changed files with 722 additions and 218 deletions.
40 changes: 40 additions & 0 deletions common/src/main/java/bisq/common/util/Utilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DurationFormatUtils;

import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
Expand Down Expand Up @@ -505,4 +506,43 @@ public static String readableFileSize(long size) {
return new DecimalFormat("#,##0.###").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
}

// Substitute for FormattingUtils if there is no dependency to core
public static String formatDurationAsWords(long durationMillis) {
String format = "";
String second = "second";
String minute = "minute";
String hour = "hour";
String day = "day";
String days = "days";
String hours = "hours";
String minutes = "minutes";
String seconds = "seconds";

if (durationMillis >= TimeUnit.DAYS.toMillis(1)) {
format = "d\' " + days + ", \'";
}

format += "H\' " + hours + ", \'m\' " + minutes + ", \'s\'.\'S\' " + seconds + "\'";

String duration = durationMillis > 0 ? DurationFormatUtils.formatDuration(durationMillis, format) : "";

duration = StringUtils.replacePattern(duration, "^1 " + seconds + "|\\b1 " + seconds, "1 " + second);
duration = StringUtils.replacePattern(duration, "^1 " + minutes + "|\\b1 " + minutes, "1 " + minute);
duration = StringUtils.replacePattern(duration, "^1 " + hours + "|\\b1 " + hours, "1 " + hour);
duration = StringUtils.replacePattern(duration, "^1 " + days + "|\\b1 " + days, "1 " + day);

duration = duration.replace(", 0 seconds", "");
duration = duration.replace(", 0 minutes", "");
duration = duration.replace(", 0 hours", "");
duration = StringUtils.replacePattern(duration, "^0 days, ", "");
duration = StringUtils.replacePattern(duration, "^0 hours, ", "");
duration = StringUtils.replacePattern(duration, "^0 minutes, ", "");
duration = StringUtils.replacePattern(duration, "^0 seconds, ", "");

String result = duration.trim();
if (result.isEmpty()) {
result = "0.000 seconds";
}
return result;
}
}
2 changes: 1 addition & 1 deletion core/src/main/java/bisq/core/app/P2PNetworkSetup.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public void onConnection(Connection connection) {
public void onDisconnect(CloseConnectionReason closeConnectionReason, Connection connection) {
// We only check at seed nodes as they are running the latest version
// Other disconnects might be caused by peers running an older version
if (connection.getPeerType() == Connection.PeerType.SEED_NODE &&
if (connection.getConnectionState().isSeedNode() &&
closeConnectionReason == CloseConnectionReason.RULE_VIOLATION) {
log.warn("RULE_VIOLATION onDisconnect closeConnectionReason={}, connection={}",
closeConnectionReason, connection);
Expand Down
6 changes: 3 additions & 3 deletions core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ public void onConnection(Connection connection) {
public void onDisconnect(CloseConnectionReason closeConnectionReason, Connection connection) {
// We only check at seed nodes as they are running the latest version
// Other disconnects might be caused by peers running an older version
if (connection.getPeerType() == Connection.PeerType.SEED_NODE &&
if (connection.getConnectionState().isSeedNode() &&
closeConnectionReason == CloseConnectionReason.RULE_VIOLATION) {
log.warn("RULE_VIOLATION onDisconnect closeConnectionReason=" + closeConnectionReason);
log.warn("RULE_VIOLATION onDisconnect connection={}", connection);
log.warn("RULE_VIOLATION onDisconnect closeConnectionReason={}. connection={}",
closeConnectionReason, connection);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import bisq.core.dao.monitoring.model.BlindVoteStateHash;

import bisq.network.p2p.InitialDataRequest;

import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;

Expand Down Expand Up @@ -67,4 +69,9 @@ public static NetworkEnvelope fromProto(protobuf.GetBlindVoteStateHashesResponse
proto.getRequestNonce(),
messageVersion);
}

@Override
public Class<? extends InitialDataRequest> associatedRequest() {
return GetBlindVoteStateHashesRequest.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import bisq.core.dao.monitoring.model.DaoStateHash;

import bisq.network.p2p.InitialDataRequest;

import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;

Expand Down Expand Up @@ -67,4 +69,9 @@ public static NetworkEnvelope fromProto(protobuf.GetDaoStateHashesResponse proto
proto.getRequestNonce(),
messageVersion);
}

@Override
public Class<? extends InitialDataRequest> associatedRequest() {
return GetDaoStateHashesRequest.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import bisq.core.dao.monitoring.model.ProposalStateHash;

import bisq.network.p2p.InitialDataRequest;

import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;

Expand Down Expand Up @@ -67,4 +69,9 @@ public static NetworkEnvelope fromProto(protobuf.GetProposalStateHashesResponse
proto.getRequestNonce(),
messageVersion);
}

@Override
public Class<? extends InitialDataRequest> associatedRequest() {
return GetProposalStateHashesRequest.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package bisq.core.dao.monitoring.network.messages;

import bisq.network.p2p.DirectMessage;
import bisq.network.p2p.InitialDataRequest;
import bisq.network.p2p.storage.payload.CapabilityRequiringPayload;

import bisq.common.app.Capabilities;
Expand All @@ -29,7 +30,8 @@

@EqualsAndHashCode(callSuper = true)
@Getter
public abstract class GetStateHashesRequest extends NetworkEnvelope implements DirectMessage, CapabilityRequiringPayload {
public abstract class GetStateHashesRequest extends NetworkEnvelope implements DirectMessage,
CapabilityRequiringPayload, InitialDataRequest {
protected final int height;
protected final int nonce;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import bisq.network.p2p.DirectMessage;
import bisq.network.p2p.ExtendedDataSizePermission;
import bisq.network.p2p.InitialDataResponse;

import bisq.common.proto.network.NetworkEnvelope;

Expand All @@ -31,7 +32,8 @@

@EqualsAndHashCode(callSuper = true)
@Getter
public abstract class GetStateHashesResponse<T extends StateHash> extends NetworkEnvelope implements DirectMessage, ExtendedDataSizePermission {
public abstract class GetStateHashesResponse<T extends StateHash> extends NetworkEnvelope implements DirectMessage,
ExtendedDataSizePermission, InitialDataResponse {
protected final List<T> stateHashes;
protected final int requestNonce;

Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/bisq/core/dao/node/full/FullNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import bisq.core.dao.state.model.blockchain.Block;

import bisq.network.p2p.P2PService;
import bisq.network.p2p.network.ConnectionState;

import bisq.common.UserThread;
import bisq.common.handlers.ResultHandler;
Expand Down Expand Up @@ -76,6 +77,7 @@ public FullNode(BlockParser blockParser,
this.rpcService = rpcService;

this.fullNodeNetworkService = fullNodeNetworkService;
ConnectionState.setExpectedRequests(5);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ public FullNodeNetworkService(NetworkNode networkNode,
public void start() {
networkNode.addMessageListener(this);
peerManager.addListener(this);
peerManager.setAllowDisconnectSeedNodes(true);
}

@SuppressWarnings("Duplicates")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,6 @@ private void requestBlocks(NodeAddress peersNodeAddress, int startBlockHeight) {
return;
}

// In case we would have had an earlier request and had set allowDisconnectSeedNodes to true we un-do that
// if we get a repeated request.
peerManager.setAllowDisconnectSeedNodes(false);
RequestBlocksHandler requestBlocksHandler = new RequestBlocksHandler(networkNode,
peerManager,
peersNodeAddress,
Expand All @@ -304,9 +301,6 @@ public void onComplete(GetBlocksResponse getBlocksResponse) {

listeners.forEach(listener -> listener.onRequestedBlocksReceived(getBlocksResponse,
() -> {
// After we received the blocks we allow to disconnect seed nodes.
// We delay 20 seconds to allow multiple requests to finish.
UserThread.runAfter(() -> peerManager.setAllowDisconnectSeedNodes(true), 20);
}));
} else {
log.warn("We got a response which is already obsolete because we received a " +
Expand All @@ -325,9 +319,6 @@ public void onFault(String errorMessage, @Nullable Connection connection) {

listeners.forEach(listener -> listener.onFault(errorMessage, connection));

// We allow now to disconnect from that seed.
peerManager.setAllowDisconnectSeedNodes(true);

tryWithNewSeedNode(startBlockHeight);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package bisq.core.dao.node.messages;

import bisq.network.p2p.DirectMessage;
import bisq.network.p2p.InitialDataRequest;
import bisq.network.p2p.NodeAddress;
import bisq.network.p2p.SendersNodeAddressMessage;
import bisq.network.p2p.SupportedCapabilitiesMessage;
Expand All @@ -44,7 +45,7 @@
@Getter
@Slf4j
public final class GetBlocksRequest extends NetworkEnvelope implements DirectMessage, SendersNodeAddressMessage,
/*CapabilityRequiringPayload, */SupportedCapabilitiesMessage {
SupportedCapabilitiesMessage, InitialDataRequest {
private final int fromBlockHeight;
private final int nonce;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

import bisq.network.p2p.DirectMessage;
import bisq.network.p2p.ExtendedDataSizePermission;
import bisq.network.p2p.InitialDataRequest;
import bisq.network.p2p.InitialDataResponse;

import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
Expand All @@ -36,7 +38,8 @@
@EqualsAndHashCode(callSuper = true)
@Getter
@Slf4j
public final class GetBlocksResponse extends NetworkEnvelope implements DirectMessage, ExtendedDataSizePermission {
public final class GetBlocksResponse extends NetworkEnvelope implements DirectMessage,
ExtendedDataSizePermission, InitialDataResponse {
private final List<RawBlock> blocks;
private final int requestNonce;

Expand Down Expand Up @@ -88,4 +91,9 @@ public String toString() {
",\n requestNonce=" + requestNonce +
"\n} " + super.toString();
}

@Override
public Class<? extends InitialDataRequest> associatedRequest() {
return GetBlocksRequest.class;
}
}
7 changes: 6 additions & 1 deletion core/src/main/java/bisq/core/user/Cookie.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ public Optional<Boolean> getAsOptionalBoolean(CookieKey key) {

public Map<String, String> toProtoMessage() {
Map<String, String> protoMap = new HashMap<>();
this.forEach((key, value) -> protoMap.put(key.name(), value));
this.forEach((key, value) -> {
if (key != null) {
String name = key.name();
protoMap.put(name, value);
}
});
return protoMap;
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/bisq/core/util/FormattingUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import org.bitcoinj.utils.MonetaryFormat;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.DurationFormatUtils;

import java.text.DateFormat;
Expand All @@ -24,6 +23,7 @@
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

import lombok.extern.slf4j.Slf4j;

Expand Down Expand Up @@ -246,7 +246,7 @@ public static String formatDurationAsWords(long durationMillis, boolean showSeco
String minutes = Res.get("time.minutes");
String seconds = Res.get("time.seconds");

if (durationMillis >= DateUtils.MILLIS_PER_DAY) {
if (durationMillis >= TimeUnit.DAYS.toMillis(1)) {
format = "d\' " + days + ", \'";
}

Expand Down
1 change: 1 addition & 0 deletions core/src/main/resources/i18n/displayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1303,6 +1303,7 @@ settings.net.chainHeight=Bisq: {0} | Peers: {1}
settings.net.ips=[IP address:port | host name:port | onion address:port] (comma separated). Port can be omitted if default is used (8333).
settings.net.seedNode=Seed node
settings.net.directPeer=Peer (direct)
settings.net.initialDataExchange={0} [Bootstrapping]
settings.net.peer=Peer
settings.net.inbound=inbound
settings.net.outbound=outbound
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
<PropertyValueFactory property="receivedBytes"/>
</cellValueFactory>
</TableColumn>
<TableColumn fx:id="peerTypeColumn" minWidth="100" maxWidth="100">
<TableColumn fx:id="peerTypeColumn" minWidth="170" maxWidth="170">
<cellValueFactory>
<PropertyValueFactory property="peerType"/>
</cellValueFactory>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
import bisq.core.util.FormattingUtils;

import bisq.network.p2p.network.Connection;
import bisq.network.p2p.network.ConnectionState;
import bisq.network.p2p.network.OutboundConnection;
import bisq.network.p2p.network.PeerType;
import bisq.network.p2p.network.Statistic;

import bisq.common.ClockWatcher;
Expand Down Expand Up @@ -109,12 +111,17 @@ public void updateConnectionType() {
}

public void updatePeerType() {
if (connection.getPeerType() == Connection.PeerType.SEED_NODE)
peerType.set(Res.get("settings.net.seedNode"));
else if (connection.getPeerType() == Connection.PeerType.DIRECT_MSG_PEER)
ConnectionState connectionState = connection.getConnectionState();
if (connectionState.getPeerType() == PeerType.DIRECT_MSG_PEER) {
peerType.set(Res.get("settings.net.directPeer"));
else
peerType.set(Res.get("settings.net.peer"));
} else {
String peerOrSeed = connectionState.isSeedNode() ? Res.get("settings.net.seedNode") : Res.get("settings.net.peer");
if (connectionState.getPeerType() == PeerType.INITIAL_DATA_EXCHANGE) {
peerType.set(Res.get("settings.net.initialDataExchange", peerOrSeed));
} else {
peerType.set(peerOrSeed);
}
}
}

public String getCreationDate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@

package bisq.network.p2p;

// Market interface for messages with higher allowed data size
// Marker interface for messages with higher allowed data size
public interface ExtendedDataSizePermission {
}
22 changes: 22 additions & 0 deletions p2p/src/main/java/bisq/network/p2p/InitialDataRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.network.p2p;

// Marker interface for initial data request
public interface InitialDataRequest {
}
Loading

0 comments on commit fea52f0

Please sign in to comment.