mirror of https://github.com/hyperledger/besu
Move connect decision into protocol layer (#4759)
Move the decision making for connecting or not connecting to peers into the eth layer. Future changes will take advantage if this to improve peering. Signed-off-by: Stefan <stefan.pingel@consensys.net> --------- Signed-off-by: Stefan <stefan.pingel@consensys.net> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>pull/5344/head
parent
067a263374
commit
534a369574
@ -0,0 +1,32 @@ |
|||||||
|
/* |
||||||
|
* Copyright contributors to Hyperledger Besu |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||||
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||||
|
* specific language governing permissions and limitations under the License. |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
package org.hyperledger.besu.ethereum.eth; |
||||||
|
|
||||||
|
import org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer; |
||||||
|
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; |
||||||
|
import org.hyperledger.besu.ethereum.p2p.peers.Peer; |
||||||
|
|
||||||
|
import org.apache.tuweni.bytes.Bytes; |
||||||
|
|
||||||
|
public class EthPeerTestUtil { |
||||||
|
|
||||||
|
public static EnodeURLImpl.Builder enodeBuilder() { |
||||||
|
return EnodeURLImpl.builder().ipAddress("127.0.0.1").useDefaultPorts().nodeId(Peer.randomId()); |
||||||
|
} |
||||||
|
|
||||||
|
public static Peer createPeer(final Bytes nodeId) { |
||||||
|
return DefaultPeer.fromEnodeURL(enodeBuilder().nodeId(nodeId).build()); |
||||||
|
} |
||||||
|
} |
@ -1,254 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright ConsenSys AG. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
|
||||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||||
* specific language governing permissions and limitations under the License. |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
package org.hyperledger.besu.ethereum.p2p.rlpx.connections; |
|
||||||
|
|
||||||
import org.hyperledger.besu.ethereum.p2p.peers.Peer; |
|
||||||
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason; |
|
||||||
|
|
||||||
import java.util.Objects; |
|
||||||
import java.util.concurrent.CompletableFuture; |
|
||||||
|
|
||||||
import org.apache.tuweni.bytes.Bytes; |
|
||||||
|
|
||||||
public abstract class RlpxConnection { |
|
||||||
|
|
||||||
private final long initiatedAt; |
|
||||||
protected final CompletableFuture<PeerConnection> future; |
|
||||||
|
|
||||||
private RlpxConnection(final CompletableFuture<PeerConnection> future) { |
|
||||||
this.future = future; |
|
||||||
this.initiatedAt = System.currentTimeMillis(); |
|
||||||
} |
|
||||||
|
|
||||||
public static RlpxConnection inboundConnection(final PeerConnection peerConnection) { |
|
||||||
return new RemotelyInitiatedRlpxConnection(peerConnection); |
|
||||||
} |
|
||||||
|
|
||||||
public static RlpxConnection outboundConnection( |
|
||||||
final Peer peer, final CompletableFuture<PeerConnection> future) { |
|
||||||
return new LocallyInitiatedRlpxConnection(peer, future); |
|
||||||
} |
|
||||||
|
|
||||||
public abstract Peer getPeer(); |
|
||||||
|
|
||||||
public abstract void disconnect(DisconnectReason reason); |
|
||||||
|
|
||||||
public Bytes getId() { |
|
||||||
return getPeer().getId(); |
|
||||||
} |
|
||||||
|
|
||||||
public abstract PeerConnection getPeerConnection() throws ConnectionNotEstablishedException; |
|
||||||
|
|
||||||
public CompletableFuture<PeerConnection> getFuture() { |
|
||||||
return future; |
|
||||||
} |
|
||||||
|
|
||||||
public abstract boolean isActive(); |
|
||||||
|
|
||||||
public abstract boolean isPending(); |
|
||||||
|
|
||||||
public abstract boolean isFailedOrDisconnected(); |
|
||||||
|
|
||||||
public abstract boolean initiatedRemotely(); |
|
||||||
|
|
||||||
public void subscribeConnectionEstablished( |
|
||||||
final RlpxConnectCallback successCallback, final RlpxConnectFailedCallback failedCallback) { |
|
||||||
future.whenComplete( |
|
||||||
(conn, err) -> { |
|
||||||
if (err != null) { |
|
||||||
failedCallback.onFailure(this); |
|
||||||
} else { |
|
||||||
successCallback.onConnect(this); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean initiatedLocally() { |
|
||||||
return !initiatedRemotely(); |
|
||||||
} |
|
||||||
|
|
||||||
public long getInitiatedAt() { |
|
||||||
return initiatedAt; |
|
||||||
} |
|
||||||
|
|
||||||
private static class RemotelyInitiatedRlpxConnection extends RlpxConnection { |
|
||||||
|
|
||||||
private final PeerConnection peerConnection; |
|
||||||
|
|
||||||
private RemotelyInitiatedRlpxConnection(final PeerConnection peerConnection) { |
|
||||||
super(CompletableFuture.completedFuture(peerConnection)); |
|
||||||
this.peerConnection = peerConnection; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public Peer getPeer() { |
|
||||||
return peerConnection.getPeer(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void disconnect(final DisconnectReason reason) { |
|
||||||
peerConnection.disconnect(reason); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public PeerConnection getPeerConnection() { |
|
||||||
return peerConnection; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isActive() { |
|
||||||
return !peerConnection.isDisconnected(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isPending() { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isFailedOrDisconnected() { |
|
||||||
return peerConnection.isDisconnected(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean initiatedRemotely() { |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean equals(final Object o) { |
|
||||||
if (o == this) { |
|
||||||
return true; |
|
||||||
} |
|
||||||
if (!(o instanceof RemotelyInitiatedRlpxConnection)) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
final RemotelyInitiatedRlpxConnection that = (RemotelyInitiatedRlpxConnection) o; |
|
||||||
return Objects.equals(peerConnection, that.peerConnection); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public int hashCode() { |
|
||||||
return Objects.hash(peerConnection); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String toString() { |
|
||||||
return "RemotelyInitiatedRlpxConnection initiatedAt:" |
|
||||||
+ getInitiatedAt() |
|
||||||
+ " to " |
|
||||||
+ peerConnection.getPeer().getId() |
|
||||||
+ " disconnected? " |
|
||||||
+ isFailedOrDisconnected(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private static class LocallyInitiatedRlpxConnection extends RlpxConnection { |
|
||||||
|
|
||||||
private final Peer peer; |
|
||||||
|
|
||||||
private LocallyInitiatedRlpxConnection( |
|
||||||
final Peer peer, final CompletableFuture<PeerConnection> future) { |
|
||||||
super(future); |
|
||||||
this.peer = peer; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public Peer getPeer() { |
|
||||||
return peer; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void disconnect(final DisconnectReason reason) { |
|
||||||
future.thenAccept((conn) -> conn.disconnect(reason)); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public PeerConnection getPeerConnection() throws ConnectionNotEstablishedException { |
|
||||||
if (!future.isDone() || future.isCompletedExceptionally()) { |
|
||||||
throw new ConnectionNotEstablishedException( |
|
||||||
"Cannot access PeerConnection before connection is fully established."); |
|
||||||
} |
|
||||||
return future.getNow(null); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isActive() { |
|
||||||
return future.isDone() |
|
||||||
&& !future.isCompletedExceptionally() |
|
||||||
&& !getPeerConnection().isDisconnected(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isPending() { |
|
||||||
return !future.isDone(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isFailedOrDisconnected() { |
|
||||||
return future.isCompletedExceptionally() |
|
||||||
|| (future.isDone() && getPeerConnection().isDisconnected()); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean initiatedRemotely() { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean equals(final Object o) { |
|
||||||
if (o == this) { |
|
||||||
return true; |
|
||||||
} |
|
||||||
if (!(o instanceof LocallyInitiatedRlpxConnection)) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
final LocallyInitiatedRlpxConnection that = (LocallyInitiatedRlpxConnection) o; |
|
||||||
return Objects.equals(peer, that.peer) && Objects.equals(future, that.future); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public int hashCode() { |
|
||||||
return Objects.hash(peer, future); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String toString() { |
|
||||||
return "LocallyInitiatedRlpxConnection initiatedAt:" |
|
||||||
+ getInitiatedAt() |
|
||||||
+ " to " |
|
||||||
+ getPeer().getId() |
|
||||||
+ " disconnected? " |
|
||||||
+ isFailedOrDisconnected(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static class ConnectionNotEstablishedException extends IllegalStateException { |
|
||||||
|
|
||||||
public ConnectionNotEstablishedException(final String message) { |
|
||||||
super(message); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@FunctionalInterface |
|
||||||
public interface RlpxConnectCallback { |
|
||||||
void onConnect(RlpxConnection connection); |
|
||||||
} |
|
||||||
|
|
||||||
@FunctionalInterface |
|
||||||
public interface RlpxConnectFailedCallback { |
|
||||||
void onFailure(RlpxConnection connection); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,23 @@ |
|||||||
|
/* |
||||||
|
* Copyright contributors to Hyperledger Besu |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||||
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||||
|
* specific language governing permissions and limitations under the License. |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
package org.hyperledger.besu.ethereum.p2p.rlpx.wire; |
||||||
|
|
||||||
|
import org.hyperledger.besu.ethereum.p2p.peers.Peer; |
||||||
|
|
||||||
|
@FunctionalInterface |
||||||
|
public interface ShouldConnectCallback { |
||||||
|
|
||||||
|
boolean shouldConnect(final Peer peer, final boolean incoming); |
||||||
|
} |
@ -1,66 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright ConsenSys AG. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
|
||||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||||
* specific language governing permissions and limitations under the License. |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
package org.hyperledger.besu.ethereum.p2p.config; |
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat; |
|
||||||
|
|
||||||
import org.junit.Test; |
|
||||||
|
|
||||||
public class RlpxConfigurationTest { |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getMaxRemotelyInitiatedConnections_remoteLimitsDisabled() { |
|
||||||
final RlpxConfiguration config = |
|
||||||
RlpxConfiguration.create() |
|
||||||
.setFractionRemoteWireConnectionsAllowed(.5f) |
|
||||||
.setLimitRemoteWireConnectionsEnabled(false) |
|
||||||
.setPeerUpperBound(20); |
|
||||||
|
|
||||||
assertThat(config.getMaxRemotelyInitiatedConnections()).isEqualTo(20); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getMaxRemotelyInitiatedConnections_remoteLimitsEnabled() { |
|
||||||
final RlpxConfiguration config = |
|
||||||
RlpxConfiguration.create() |
|
||||||
.setFractionRemoteWireConnectionsAllowed(.5f) |
|
||||||
.setLimitRemoteWireConnectionsEnabled(true) |
|
||||||
.setPeerUpperBound(20); |
|
||||||
|
|
||||||
assertThat(config.getMaxRemotelyInitiatedConnections()).isEqualTo(10); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getMaxRemotelyInitiatedConnections_remoteLimitsEnabledWithNonIntegerRatio() { |
|
||||||
final RlpxConfiguration config = |
|
||||||
RlpxConfiguration.create() |
|
||||||
.setFractionRemoteWireConnectionsAllowed(.5f) |
|
||||||
.setLimitRemoteWireConnectionsEnabled(true) |
|
||||||
.setPeerUpperBound(25); |
|
||||||
|
|
||||||
assertThat(config.getMaxRemotelyInitiatedConnections()).isEqualTo(12); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getMaxRemotelyInitiatedConnections_remoteLimitsEnabledRoundsToZero() { |
|
||||||
final RlpxConfiguration config = |
|
||||||
RlpxConfiguration.create() |
|
||||||
.setFractionRemoteWireConnectionsAllowed(.5f) |
|
||||||
.setLimitRemoteWireConnectionsEnabled(true) |
|
||||||
.setPeerUpperBound(1); |
|
||||||
|
|
||||||
assertThat(config.getMaxRemotelyInitiatedConnections()).isEqualTo(0); |
|
||||||
} |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,269 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright ConsenSys AG. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
|
||||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
||||||
* specific language governing permissions and limitations under the License. |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
package org.hyperledger.besu.ethereum.p2p.rlpx.connections; |
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat; |
|
||||||
import static org.assertj.core.api.Assertions.assertThatThrownBy; |
|
||||||
import static org.hyperledger.besu.ethereum.p2p.peers.PeerTestHelper.createPeer; |
|
||||||
import static org.mockito.Mockito.spy; |
|
||||||
import static org.mockito.Mockito.verify; |
|
||||||
|
|
||||||
import org.hyperledger.besu.ethereum.p2p.peers.Peer; |
|
||||||
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.RlpxConnection.ConnectionNotEstablishedException; |
|
||||||
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason; |
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture; |
|
||||||
|
|
||||||
import org.junit.Test; |
|
||||||
|
|
||||||
public class RlpxConnectionTest { |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getPeer_pendingOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
|
|
||||||
assertThat(conn.getPeer()).isEqualTo(peer); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getPeer_establishedOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
future.complete(peerConnection(peer)); |
|
||||||
|
|
||||||
assertThat(conn.getPeer()).isEqualTo(peer); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getPeer_inboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final PeerConnection peerConnection = peerConnection(peer); |
|
||||||
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection); |
|
||||||
|
|
||||||
assertThat(conn.getPeer()).isEqualTo(peer); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void disconnect_pendingOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
|
|
||||||
final DisconnectReason reason = DisconnectReason.REQUESTED; |
|
||||||
conn.disconnect(reason); |
|
||||||
assertThat(conn.isFailedOrDisconnected()).isFalse(); |
|
||||||
|
|
||||||
// Resolve future
|
|
||||||
final PeerConnection peerConnection = peerConnection(peer); |
|
||||||
future.complete(peerConnection); |
|
||||||
|
|
||||||
// Check disconnect was issued
|
|
||||||
verify(peerConnection).disconnect(reason); |
|
||||||
assertThat(conn.isFailedOrDisconnected()).isTrue(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void disconnect_activeOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
final PeerConnection peerConnection = peerConnection(peer); |
|
||||||
future.complete(peerConnection); |
|
||||||
|
|
||||||
final DisconnectReason reason = DisconnectReason.REQUESTED; |
|
||||||
conn.disconnect(reason); |
|
||||||
|
|
||||||
// Check disconnect was issued
|
|
||||||
assertThat(conn.isFailedOrDisconnected()).isTrue(); |
|
||||||
verify(peerConnection).disconnect(reason); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void disconnect_failedOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
future.completeExceptionally(new IllegalStateException("whoops")); |
|
||||||
|
|
||||||
assertThat(conn.isFailedOrDisconnected()).isTrue(); |
|
||||||
final DisconnectReason reason = DisconnectReason.REQUESTED; |
|
||||||
conn.disconnect(reason); |
|
||||||
assertThat(conn.isFailedOrDisconnected()).isTrue(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void disconnect_inboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final PeerConnection peerConnection = peerConnection(peer); |
|
||||||
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection); |
|
||||||
|
|
||||||
assertThat(conn.isFailedOrDisconnected()).isFalse(); |
|
||||||
final DisconnectReason reason = DisconnectReason.REQUESTED; |
|
||||||
conn.disconnect(reason); |
|
||||||
|
|
||||||
// Check disconnect was issued
|
|
||||||
assertThat(conn.isFailedOrDisconnected()).isTrue(); |
|
||||||
verify(peerConnection).disconnect(reason); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getPeerConnection_pendingOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
|
|
||||||
assertThatThrownBy(conn::getPeerConnection) |
|
||||||
.isInstanceOf(ConnectionNotEstablishedException.class); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getPeerConnection_activeOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
final PeerConnection peerConnection = peerConnection(peer); |
|
||||||
future.complete(peerConnection); |
|
||||||
|
|
||||||
assertThat(conn.getPeerConnection()).isEqualTo(peerConnection); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getPeerConnection_failedOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
future.completeExceptionally(new IllegalStateException("whoops")); |
|
||||||
|
|
||||||
assertThatThrownBy(conn::getPeerConnection) |
|
||||||
.isInstanceOf(ConnectionNotEstablishedException.class); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getPeerConnection_disconnectedOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
final PeerConnection peerConnection = peerConnection(peer); |
|
||||||
future.complete(peerConnection); |
|
||||||
conn.disconnect(DisconnectReason.REQUESTED); |
|
||||||
|
|
||||||
assertThat(conn.getPeerConnection()).isEqualTo(peerConnection); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getPeerConnection_activeInboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final PeerConnection peerConnection = peerConnection(peer); |
|
||||||
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection); |
|
||||||
|
|
||||||
assertThat(conn.getPeerConnection()).isEqualTo(peerConnection); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void getPeerConnection_disconnectedInboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final PeerConnection peerConnection = peerConnection(peer); |
|
||||||
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection); |
|
||||||
conn.disconnect(DisconnectReason.REQUESTED); |
|
||||||
|
|
||||||
assertThat(conn.getPeerConnection()).isEqualTo(peerConnection); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void checkState_pendingOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
|
|
||||||
assertThat(conn.initiatedRemotely()).isFalse(); |
|
||||||
assertThat(conn.isActive()).isFalse(); |
|
||||||
assertThat(conn.isPending()).isTrue(); |
|
||||||
assertThat(conn.isFailedOrDisconnected()).isFalse(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void checkState_activeOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
final PeerConnection peerConnection = peerConnection(peer); |
|
||||||
future.complete(peerConnection); |
|
||||||
|
|
||||||
assertThat(conn.initiatedRemotely()).isFalse(); |
|
||||||
assertThat(conn.isActive()).isTrue(); |
|
||||||
assertThat(conn.isPending()).isFalse(); |
|
||||||
assertThat(conn.isFailedOrDisconnected()).isFalse(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void checkState_failedOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
future.completeExceptionally(new IllegalStateException("whoops")); |
|
||||||
|
|
||||||
assertThat(conn.initiatedRemotely()).isFalse(); |
|
||||||
assertThat(conn.isActive()).isFalse(); |
|
||||||
assertThat(conn.isPending()).isFalse(); |
|
||||||
assertThat(conn.isFailedOrDisconnected()).isTrue(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void checkState_disconnectedOutboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); |
|
||||||
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); |
|
||||||
final PeerConnection peerConnection = peerConnection(peer); |
|
||||||
future.complete(peerConnection); |
|
||||||
conn.disconnect(DisconnectReason.UNKNOWN); |
|
||||||
|
|
||||||
assertThat(conn.initiatedRemotely()).isFalse(); |
|
||||||
assertThat(conn.isActive()).isFalse(); |
|
||||||
assertThat(conn.isPending()).isFalse(); |
|
||||||
assertThat(conn.isFailedOrDisconnected()).isTrue(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void checkState_activeInboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final PeerConnection peerConnection = peerConnection(peer); |
|
||||||
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection); |
|
||||||
|
|
||||||
assertThat(conn.initiatedRemotely()).isTrue(); |
|
||||||
assertThat(conn.isActive()).isTrue(); |
|
||||||
assertThat(conn.isPending()).isFalse(); |
|
||||||
assertThat(conn.isFailedOrDisconnected()).isFalse(); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void checkState_disconnectedInboundConnection() { |
|
||||||
final Peer peer = createPeer(); |
|
||||||
final PeerConnection peerConnection = peerConnection(peer); |
|
||||||
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection); |
|
||||||
conn.disconnect(DisconnectReason.UNKNOWN); |
|
||||||
|
|
||||||
assertThat(conn.initiatedRemotely()).isTrue(); |
|
||||||
assertThat(conn.isActive()).isFalse(); |
|
||||||
assertThat(conn.isPending()).isFalse(); |
|
||||||
assertThat(conn.isFailedOrDisconnected()).isTrue(); |
|
||||||
} |
|
||||||
|
|
||||||
private PeerConnection peerConnection(final Peer peer) { |
|
||||||
return spy(MockPeerConnection.create(peer)); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue