use of org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message in project besu by hyperledger.
the class EthProtocolManager method processMessage.
@Override
public void processMessage(final Capability cap, final Message message) {
checkArgument(getSupportedCapabilities().contains(cap), "Unsupported capability passed to processMessage(): " + cap);
final MessageData messageData = message.getData();
final int code = messageData.getCode();
LOG.trace("Process message {}, {}", cap, code);
final EthPeer ethPeer = ethPeers.peer(message.getConnection());
if (ethPeer == null) {
LOG.debug("Ignoring message received from unknown peer connection: {}", message.getConnection());
return;
}
if (messageData.getSize() > 10 * 1_000_000) /*10MB*/
{
LOG.debug("Received message over 10MB. Disconnecting from {}", ethPeer);
ethPeer.disconnect(DisconnectReason.BREACH_OF_PROTOCOL);
return;
}
// Handle STATUS processing
if (code == EthPV62.STATUS) {
handleStatusMessage(ethPeer, messageData);
return;
} else if (!ethPeer.statusHasBeenReceived()) {
// Peers are required to send status messages before any other message type
LOG.debug("{} requires a Status ({}) message to be sent first. Instead, received message {}. Disconnecting from {}.", this.getClass().getSimpleName(), EthPV62.STATUS, code, ethPeer);
ethPeer.disconnect(DisconnectReason.BREACH_OF_PROTOCOL);
return;
}
final EthMessage ethMessage = new EthMessage(ethPeer, messageData);
if (!ethPeer.validateReceivedMessage(ethMessage, getSupportedProtocol())) {
LOG.debug("Unsolicited message received from, disconnecting: {}", ethPeer);
ethPeer.disconnect(DisconnectReason.BREACH_OF_PROTOCOL);
return;
}
if (isFinalized() && (code == EthPV62.NEW_BLOCK || code == EthPV62.NEW_BLOCK_HASHES)) {
LOG.debug("disconnecting peer for sending new blocks after transition to PoS");
ethPeer.disconnect(DisconnectReason.SUBPROTOCOL_TRIGGERED);
}
// This will handle responses
ethPeers.dispatchMessage(ethPeer, ethMessage, getSupportedProtocol());
// This will handle requests
Optional<MessageData> maybeResponseData = Optional.empty();
try {
if (EthProtocol.isEth66Compatible(cap) && EthProtocol.requestIdCompatible(code)) {
final Map.Entry<BigInteger, MessageData> requestIdAndEthMessage = ethMessage.getData().unwrapMessageData();
maybeResponseData = ethMessages.dispatch(new EthMessage(ethPeer, requestIdAndEthMessage.getValue())).map(responseData -> responseData.wrapMessageData(requestIdAndEthMessage.getKey()));
} else {
maybeResponseData = ethMessages.dispatch(ethMessage);
}
} catch (final RLPException e) {
LOG.debug("Received malformed message {} , disconnecting: {}", messageData.getData(), ethPeer, e);
ethPeer.disconnect(DisconnectMessage.DisconnectReason.BREACH_OF_PROTOCOL);
}
maybeResponseData.ifPresent(responseData -> {
try {
ethPeer.send(responseData, getSupportedProtocol());
} catch (final PeerNotConnected missingPeerException) {
// Peer disconnected before we could respond - nothing to do
}
});
}
use of org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message in project besu by hyperledger.
the class P2PPlainNetworkTest method p2pOverTlsCanHandleRecordFragmentation.
@Test
public void p2pOverTlsCanHandleRecordFragmentation() throws Exception {
// Given
final int tlsRecordSize = 16 * 1024;
final int threeTlsRecords = 2 * tlsRecordSize + 1;
final LargeMessageData largeMessageData = new LargeMessageData(Bytes.of(buildPaddedMessage(threeTlsRecords)));
final NodeKey nodeKey = NodeKeyUtils.generate();
try (final P2PNetwork listener = builder("partner1client1").nodeKey(nodeKey).build();
final P2PNetwork connector = builder("partner2client1").build()) {
final CompletableFuture<DisconnectReason> disconnectReasonFuture = new CompletableFuture<>();
listener.subscribeDisconnect((peerConnection, reason, initiatedByPeer) -> {
if (!DisconnectReason.CLIENT_QUITTING.equals(reason)) {
// client quitting is the valid end state
disconnectReasonFuture.complete(reason);
}
});
final CompletableFuture<Message> successfulMessageFuture = new CompletableFuture<>();
listener.subscribe(Capability.create("eth", 63), (capability, message) -> {
if (message.getData().getCode() == LargeMessageData.VALID_ETH_MESSAGE_CODE) {
successfulMessageFuture.complete(message);
}
});
listener.start();
connector.start();
final EnodeURL listenerEnode = listener.getLocalEnode().get();
final Bytes listenId = listenerEnode.getNodeId();
final int listenPort = listenerEnode.getListeningPort().get();
final PeerConnection peerConnection = connector.connect(createPeer(listenId, listenPort)).get(30000L, TimeUnit.SECONDS);
// When
peerConnection.sendForProtocol("eth", largeMessageData);
// Then
CompletableFuture.anyOf(disconnectReasonFuture, successfulMessageFuture).thenAccept(successOrFailure -> {
if (successOrFailure instanceof DisconnectReason) {
fail("listener disconnected due to " + ((DisconnectReason) successOrFailure).name());
} else {
final Message receivedMessage = (Message) successOrFailure;
assertThat(receivedMessage.getData().getData()).isEqualTo(largeMessageData.getData());
}
}).get(30L, TimeUnit.SECONDS);
}
}
use of org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message in project besu by hyperledger.
the class IbftControllerTest method startsNewBlockHeightManagerAndReplaysFutureMessages.
@Test
public void startsNewBlockHeightManagerAndReplaysFutureMessages() {
final ConsensusRoundIdentifier roundIdentifierHeight6 = new ConsensusRoundIdentifier(6, 0);
setupPrepare(futureRoundIdentifier, validator);
setupProposal(roundIdentifierHeight6, validator);
setupCommit(futureRoundIdentifier, validator);
setupRoundChange(futureRoundIdentifier, validator);
final List<Message> height2Msgs = newArrayList(prepareMessage, commitMessage, roundChangeMessage);
when(blockHeightManager.getChainHeight()).thenReturn(5L);
when(futureMessageBuffer.retrieveMessagesForHeight(5L)).thenReturn(height2Msgs);
constructIbftController();
ibftController.start();
verify(futureMessageBuffer).retrieveMessagesForHeight(5L);
verify(futureMessageBuffer, never()).retrieveMessagesForHeight(6L);
verify(blockHeightManagerFactory).create(chainHeadBlockHeader);
verify(blockHeightManager, atLeastOnce()).getChainHeight();
verify(blockHeightManager, never()).handleProposalPayload(proposal);
verify(blockHeightManager).handlePreparePayload(prepare);
verify(ibftGossip).send(prepareMessage);
verify(blockHeightManager).handleCommitPayload(commit);
verify(ibftGossip).send(commitMessage);
verify(blockHeightManager).handleRoundChangePayload(roundChange);
verify(ibftGossip).send(roundChangeMessage);
}
use of org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message in project besu by hyperledger.
the class MockNetworkTest method exchangeMessages.
@Test
public void exchangeMessages() throws Exception {
final Capability cap = Capability.create("eth", 63);
final MockNetwork network = new MockNetwork(Arrays.asList(cap));
final Peer one = DefaultPeer.fromEnodeURL(EnodeURLImpl.builder().nodeId(randomId()).ipAddress("192.168.1.2").discoveryPort(1234).listeningPort(4321).build());
final Peer two = DefaultPeer.fromEnodeURL(EnodeURLImpl.builder().nodeId(randomId()).ipAddress("192.168.1.3").discoveryPort(1234).listeningPort(4321).build());
try (final P2PNetwork network1 = network.setup(one);
final P2PNetwork network2 = network.setup(two)) {
final CompletableFuture<Message> messageFuture = new CompletableFuture<>();
network1.subscribe(cap, (capability, msg) -> messageFuture.complete(msg));
final Predicate<PeerConnection> isPeerOne = peerConnection -> peerConnection.getPeerInfo().getNodeId().equals(one.getId());
final Predicate<PeerConnection> isPeerTwo = peerConnection -> peerConnection.getPeerInfo().getNodeId().equals(two.getId());
Assertions.assertThat(network1.getPeers().stream().filter(isPeerTwo).findFirst()).isNotPresent();
Assertions.assertThat(network2.getPeers().stream().filter(isPeerOne).findFirst()).isNotPresent();
// Validate Connect Behaviour
final CompletableFuture<PeerConnection> peer2Future = new CompletableFuture<>();
network1.subscribeConnect(peer2Future::complete);
final CompletableFuture<PeerConnection> peer1Future = new CompletableFuture<>();
network2.subscribeConnect(peer1Future::complete);
network1.connect(two).get();
Assertions.assertThat(peer1Future.get().getPeerInfo().getNodeId()).isEqualTo(one.getId());
Assertions.assertThat(peer2Future.get().getPeerInfo().getNodeId()).isEqualTo(two.getId());
Assertions.assertThat(network1.getPeers().stream().filter(isPeerTwo).findFirst()).isPresent();
final Optional<PeerConnection> optionalConnection = network2.getPeers().stream().filter(isPeerOne).findFirst();
Assertions.assertThat(optionalConnection).isPresent();
// Validate Message Exchange
final int size = 128;
final byte[] data = new byte[size];
ThreadLocalRandom.current().nextBytes(data);
final int code = 0x74;
final PeerConnection connection = optionalConnection.get();
connection.send(cap, new RawMessage(code, Bytes.wrap(data)));
final Message receivedMessage = messageFuture.get();
final MessageData receivedMessageData = receivedMessage.getData();
Assertions.assertThat(receivedMessageData.getData()).isEqualTo(Bytes.wrap(data));
Assertions.assertThat(receivedMessage.getConnection().getPeerInfo().getNodeId()).isEqualTo(two.getId());
Assertions.assertThat(receivedMessageData.getSize()).isEqualTo(size);
Assertions.assertThat(receivedMessageData.getCode()).isEqualTo(code);
// Validate Disconnect Behaviour
final CompletableFuture<DisconnectReason> peer1DisconnectFuture = new CompletableFuture<>();
final CompletableFuture<DisconnectReason> peer2DisconnectFuture = new CompletableFuture<>();
network2.subscribeDisconnect((peer, reason, initiatedByPeer) -> peer1DisconnectFuture.complete(reason));
network1.subscribeDisconnect((peer, reason, initiatedByPeer) -> peer2DisconnectFuture.complete(reason));
connection.disconnect(DisconnectReason.CLIENT_QUITTING);
Assertions.assertThat(peer1DisconnectFuture.get()).isEqualTo(DisconnectReason.REQUESTED);
Assertions.assertThat(peer2DisconnectFuture.get()).isEqualTo(DisconnectReason.CLIENT_QUITTING);
Assertions.assertThat(network1.getPeers().stream().filter(isPeerTwo).findFirst()).isNotPresent();
Assertions.assertThat(network2.getPeers().stream().filter(isPeerOne).findFirst()).isNotPresent();
}
}
use of org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message in project besu by hyperledger.
the class PeerConnectionEvents method dispatchMessage.
@Override
public void dispatchMessage(final Capability capability, final PeerConnection connection, final MessageData message) {
final Message msg = new DefaultMessage(connection, message);
messageSubscribers.getOrDefault(capability, Subscribers.none()).forEach(s -> s.onMessage(capability, msg));
}
Aggregations