Search in sources :

Example 1 with PeerDisconnectedException

use of org.hyperledger.besu.ethereum.p2p.network.exceptions.PeerDisconnectedException in project besu by hyperledger.

the class DeFramer method decode.

@Override
protected void decode(final ChannelHandlerContext ctx, final ByteBuf in, final List<Object> out) {
    MessageData message;
    while ((message = framer.deframe(in)) != null) {
        if (hellosExchanged) {
            out.add(message);
        } else if (message.getCode() == WireMessageCodes.HELLO) {
            hellosExchanged = true;
            // Decode first hello and use the payload to modify pipeline
            final PeerInfo peerInfo;
            try {
                peerInfo = HelloMessage.readFrom(message).getPeerInfo();
            } catch (final RLPException e) {
                LOG.debug("Received invalid HELLO message, set log level to TRACE for message body", e);
                connectFuture.completeExceptionally(e);
                ctx.close();
                return;
            }
            LOG.trace("Received HELLO message: {}", peerInfo);
            if (peerInfo.getVersion() >= 5) {
                LOG.trace("Enable compression for p2pVersion: {}", peerInfo.getVersion());
                framer.enableCompression();
            }
            final CapabilityMultiplexer capabilityMultiplexer = new CapabilityMultiplexer(subProtocols, localNode.getPeerInfo().getCapabilities(), peerInfo.getCapabilities());
            final Optional<Peer> peer = expectedPeer.or(() -> createPeer(peerInfo, ctx));
            if (peer.isEmpty()) {
                LOG.debug("Failed to create connection for peer {}", peerInfo);
                connectFuture.completeExceptionally(new PeerChannelClosedException(peerInfo));
                ctx.close();
                return;
            }
            final PeerConnection connection = new NettyPeerConnection(ctx, peer.get(), peerInfo, capabilityMultiplexer, connectionEventDispatcher, outboundMessagesCounter);
            // Check peer is who we expected
            if (expectedPeer.isPresent() && !Objects.equals(expectedPeer.get().getId(), peerInfo.getNodeId())) {
                final String unexpectedMsg = String.format("Expected id %s, but got %s", expectedPeer.get().getId(), peerInfo.getNodeId());
                connectFuture.completeExceptionally(new UnexpectedPeerConnectionException(unexpectedMsg));
                LOG.debug("{}. Disconnecting.", unexpectedMsg);
                connection.disconnect(DisconnectMessage.DisconnectReason.UNEXPECTED_ID);
            }
            // Check that we have shared caps
            if (capabilityMultiplexer.getAgreedCapabilities().size() == 0) {
                LOG.debug("Disconnecting because no capabilities are shared: {}", peerInfo);
                connectFuture.completeExceptionally(new IncompatiblePeerException("No shared capabilities"));
                connection.disconnect(DisconnectMessage.DisconnectReason.USELESS_PEER);
            }
            // Setup next stage
            final AtomicBoolean waitingForPong = new AtomicBoolean(false);
            ctx.channel().pipeline().addLast(new IdleStateHandler(15, 0, 0), new WireKeepAlive(connection, waitingForPong), new ApiHandler(capabilityMultiplexer, connection, connectionEventDispatcher, waitingForPong), new MessageFramer(capabilityMultiplexer, framer));
            connectFuture.complete(connection);
        } else if (message.getCode() == WireMessageCodes.DISCONNECT) {
            final DisconnectMessage disconnectMessage = DisconnectMessage.readFrom(message);
            LOG.debug("Peer {} disconnected before sending HELLO.  Reason: {}", expectedPeer.map(Peer::getEnodeURLString).orElse("unknown"), disconnectMessage.getReason());
            ctx.close();
            connectFuture.completeExceptionally(new PeerDisconnectedException(disconnectMessage.getReason()));
        } else {
            // Unexpected message - disconnect
            LOG.debug("Message received before HELLO's exchanged, disconnecting.  Peer: {}, Code: {}, Data: {}", expectedPeer.map(Peer::getEnodeURLString).orElse("unknown"), message.getCode(), message.getData().toString());
            ctx.writeAndFlush(new OutboundMessage(null, DisconnectMessage.create(DisconnectMessage.DisconnectReason.BREACH_OF_PROTOCOL))).addListener((f) -> ctx.close());
            connectFuture.completeExceptionally(new BreachOfProtocolException("Message received before HELLO's exchanged"));
        }
    }
}
Also used : Optional(java.util.Optional) PeerConnection(org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection) DisconnectMessage(org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage) MessageData(org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData) PeerInfo(org.hyperledger.besu.ethereum.p2p.rlpx.wire.PeerInfo) Peer(org.hyperledger.besu.ethereum.p2p.peers.Peer) DefaultPeer(org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer) CapabilityMultiplexer(org.hyperledger.besu.ethereum.p2p.rlpx.wire.CapabilityMultiplexer) PeerDisconnectedException(org.hyperledger.besu.ethereum.p2p.network.exceptions.PeerDisconnectedException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) IncompatiblePeerException(org.hyperledger.besu.ethereum.p2p.network.exceptions.IncompatiblePeerException) UnexpectedPeerConnectionException(org.hyperledger.besu.ethereum.p2p.network.exceptions.UnexpectedPeerConnectionException) IdleStateHandler(io.netty.handler.timeout.IdleStateHandler) RLPException(org.hyperledger.besu.ethereum.rlp.RLPException) BreachOfProtocolException(org.hyperledger.besu.ethereum.p2p.network.exceptions.BreachOfProtocolException) PeerChannelClosedException(org.hyperledger.besu.ethereum.p2p.network.exceptions.PeerChannelClosedException)

Aggregations

IdleStateHandler (io.netty.handler.timeout.IdleStateHandler)1 Optional (java.util.Optional)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 BreachOfProtocolException (org.hyperledger.besu.ethereum.p2p.network.exceptions.BreachOfProtocolException)1 IncompatiblePeerException (org.hyperledger.besu.ethereum.p2p.network.exceptions.IncompatiblePeerException)1 PeerChannelClosedException (org.hyperledger.besu.ethereum.p2p.network.exceptions.PeerChannelClosedException)1 PeerDisconnectedException (org.hyperledger.besu.ethereum.p2p.network.exceptions.PeerDisconnectedException)1 UnexpectedPeerConnectionException (org.hyperledger.besu.ethereum.p2p.network.exceptions.UnexpectedPeerConnectionException)1 DefaultPeer (org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer)1 Peer (org.hyperledger.besu.ethereum.p2p.peers.Peer)1 PeerConnection (org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection)1 CapabilityMultiplexer (org.hyperledger.besu.ethereum.p2p.rlpx.wire.CapabilityMultiplexer)1 MessageData (org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData)1 PeerInfo (org.hyperledger.besu.ethereum.p2p.rlpx.wire.PeerInfo)1 DisconnectMessage (org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage)1 RLPException (org.hyperledger.besu.ethereum.rlp.RLPException)1