Search in sources :

Example 1 with HandshakeMessage

use of org.apache.ignite.spi.communication.tcp.messages.HandshakeMessage in project ignite by apache.

the class TcpCommunicationSpi method safeTcpHandshake.

/**
 * Performs handshake in timeout-safe way.
 *
 * @param ch Socket channel.
 * @param recovery Recovery descriptor if use recovery handshake, otherwise {@code null}.
 * @param rmtNodeId Remote node.
 * @param timeout Timeout for handshake.
 * @param sslMeta Session meta.
 * @param handshakeConnIdx Non null connection index if need send it in handshake.
 * @throws IgniteCheckedException If handshake failed or wasn't completed withing timeout.
 * @return Handshake response.
 */
@SuppressWarnings("ThrowFromFinallyBlock")
private long safeTcpHandshake(SocketChannel ch, @Nullable GridNioRecoveryDescriptor recovery, UUID rmtNodeId, long timeout, GridSslMeta sslMeta, @Nullable Integer handshakeConnIdx) throws IgniteCheckedException {
    HandshakeTimeoutObject obj = new HandshakeTimeoutObject<>(ch, U.currentTimeMillis() + timeout);
    addTimeoutObject(obj);
    long rcvCnt = 0;
    try {
        BlockingSslHandler sslHnd = null;
        ByteBuffer buf;
        if (isSslEnabled()) {
            assert sslMeta != null;
            sslHnd = new BlockingSslHandler(sslMeta.sslEngine(), ch, directBuf, ByteOrder.nativeOrder(), log);
            if (!sslHnd.handshake())
                throw new HandshakeException("SSL handshake is not completed.");
            ByteBuffer handBuff = sslHnd.applicationBuffer();
            if (handBuff.remaining() < NodeIdMessage.MESSAGE_FULL_SIZE) {
                buf = ByteBuffer.allocate(1000);
                int read = ch.read(buf);
                if (read == -1)
                    throw new HandshakeException("Failed to read remote node ID (connection closed).");
                buf.flip();
                buf = sslHnd.decode(buf);
            } else
                buf = handBuff;
        } else {
            buf = ByteBuffer.allocate(NodeIdMessage.MESSAGE_FULL_SIZE);
            for (int i = 0; i < NodeIdMessage.MESSAGE_FULL_SIZE; ) {
                int read = ch.read(buf);
                if (read == -1)
                    throw new HandshakeException("Failed to read remote node ID (connection closed).");
                i += read;
            }
        }
        UUID rmtNodeId0 = U.bytesToUuid(buf.array(), Message.DIRECT_TYPE_SIZE);
        if (!rmtNodeId.equals(rmtNodeId0))
            throw new HandshakeException("Remote node ID is not as expected [expected=" + rmtNodeId + ", rcvd=" + rmtNodeId0 + ']');
        else if (log.isDebugEnabled())
            log.debug("Received remote node ID: " + rmtNodeId0);
        if (isSslEnabled()) {
            assert sslHnd != null;
            ch.write(sslHnd.encrypt(ByteBuffer.wrap(U.IGNITE_HEADER)));
        } else
            ch.write(ByteBuffer.wrap(U.IGNITE_HEADER));
        ClusterNode locNode = getLocalNode();
        if (locNode == null)
            throw new IgniteCheckedException("Local node has not been started or " + "fully initialized [isStopping=" + getSpiContext().isStopping() + ']');
        if (recovery != null) {
            HandshakeMessage msg;
            int msgSize = HandshakeMessage.MESSAGE_FULL_SIZE;
            if (handshakeConnIdx != null) {
                msg = new HandshakeMessage2(locNode.id(), recovery.incrementConnectCount(), recovery.received(), handshakeConnIdx);
                msgSize += 4;
            } else {
                msg = new HandshakeMessage(locNode.id(), recovery.incrementConnectCount(), recovery.received());
            }
            if (log.isDebugEnabled())
                log.debug("Writing handshake message [locNodeId=" + locNode.id() + ", rmtNode=" + rmtNodeId + ", msg=" + msg + ']');
            buf = ByteBuffer.allocate(msgSize);
            buf.order(ByteOrder.nativeOrder());
            boolean written = msg.writeTo(buf, null);
            assert written;
            buf.flip();
            if (isSslEnabled()) {
                assert sslHnd != null;
                ch.write(sslHnd.encrypt(buf));
            } else
                ch.write(buf);
        } else {
            if (isSslEnabled()) {
                assert sslHnd != null;
                ch.write(sslHnd.encrypt(ByteBuffer.wrap(NodeIdMessage.nodeIdBytesWithType(safeLocalNodeId()))));
            } else
                ch.write(ByteBuffer.wrap(NodeIdMessage.nodeIdBytesWithType(safeLocalNodeId())));
        }
        if (recovery != null) {
            if (log.isDebugEnabled())
                log.debug("Waiting for handshake [rmtNode=" + rmtNodeId + ']');
            if (isSslEnabled()) {
                assert sslHnd != null;
                buf = ByteBuffer.allocate(1000);
                buf.order(ByteOrder.nativeOrder());
                ByteBuffer decode = ByteBuffer.allocate(2 * buf.capacity());
                decode.order(ByteOrder.nativeOrder());
                for (int i = 0; i < RecoveryLastReceivedMessage.MESSAGE_FULL_SIZE; ) {
                    int read = ch.read(buf);
                    if (read == -1)
                        throw new HandshakeException("Failed to read remote node recovery handshake " + "(connection closed).");
                    buf.flip();
                    ByteBuffer decode0 = sslHnd.decode(buf);
                    i += decode0.remaining();
                    decode = appendAndResizeIfNeeded(decode, decode0);
                    buf.clear();
                }
                decode.flip();
                rcvCnt = decode.getLong(Message.DIRECT_TYPE_SIZE);
                if (decode.limit() > RecoveryLastReceivedMessage.MESSAGE_FULL_SIZE) {
                    decode.position(RecoveryLastReceivedMessage.MESSAGE_FULL_SIZE);
                    sslMeta.decodedBuffer(decode);
                }
                ByteBuffer inBuf = sslHnd.inputBuffer();
                if (inBuf.position() > 0)
                    sslMeta.encodedBuffer(inBuf);
            } else {
                buf = ByteBuffer.allocate(RecoveryLastReceivedMessage.MESSAGE_FULL_SIZE);
                buf.order(ByteOrder.nativeOrder());
                for (int i = 0; i < RecoveryLastReceivedMessage.MESSAGE_FULL_SIZE; ) {
                    int read = ch.read(buf);
                    if (read == -1)
                        throw new HandshakeException("Failed to read remote node recovery handshake " + "(connection closed).");
                    i += read;
                }
                rcvCnt = buf.getLong(Message.DIRECT_TYPE_SIZE);
            }
            if (log.isDebugEnabled())
                log.debug("Received handshake message [rmtNode=" + rmtNodeId + ", rcvCnt=" + rcvCnt + ']');
            if (rcvCnt == -1) {
                if (log.isDebugEnabled())
                    log.debug("Connection rejected, will retry client creation [rmtNode=" + rmtNodeId + ']');
            }
        }
    } catch (IOException e) {
        if (log.isDebugEnabled())
            log.debug("Failed to read from channel: " + e);
        throw new IgniteCheckedException("Failed to read from channel.", e);
    } finally {
        boolean cancelled = obj.cancel();
        if (cancelled)
            removeTimeoutObject(obj);
        // Ignoring whatever happened after timeout - reporting only timeout event.
        if (!cancelled)
            throw new HandshakeTimeoutException(new IgniteSpiOperationTimeoutException("Failed to perform handshake due to timeout " + "(consider increasing 'connectionTimeout' configuration property)."));
    }
    return rcvCnt;
}
Also used : ClusterNode(org.apache.ignite.cluster.ClusterNode) HandshakeMessage2(org.apache.ignite.spi.communication.tcp.messages.HandshakeMessage2) BlockingSslHandler(org.apache.ignite.internal.util.nio.ssl.BlockingSslHandler) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) IpcEndpoint(org.apache.ignite.internal.util.ipc.IpcEndpoint) IpcSharedMemoryServerEndpoint(org.apache.ignite.internal.util.ipc.shmem.IpcSharedMemoryServerEndpoint) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) HandshakeMessage(org.apache.ignite.spi.communication.tcp.messages.HandshakeMessage) IgniteSpiOperationTimeoutException(org.apache.ignite.spi.IgniteSpiOperationTimeoutException) UUID(java.util.UUID)

Example 2 with HandshakeMessage

use of org.apache.ignite.spi.communication.tcp.messages.HandshakeMessage in project ignite by apache.

the class InboundConnectionHandler method onFirstMessage.

/**
 * @param ses Session.
 * @param msg Message.
 */
private void onFirstMessage(final GridNioSession ses, Message msg) {
    UUID sndId;
    ConnectionKey connKey;
    if (msg instanceof NodeIdMessage) {
        sndId = U.bytesToUuid(((NodeIdMessage) msg).nodeIdBytes(), 0);
        connKey = new ConnectionKey(sndId, 0, -1);
    } else {
        assert msg instanceof HandshakeMessage : msg;
        HandshakeMessage msg0 = (HandshakeMessage) msg;
        sndId = ((HandshakeMessage) msg).nodeId();
        connKey = new ConnectionKey(sndId, msg0.connectionIndex(), msg0.connectCount());
    }
    if (log.isDebugEnabled())
        log.debug("Remote node ID received: " + sndId);
    final ClusterNode rmtNode = nodeGetter.apply(sndId);
    if (rmtNode == null) {
        DiscoverySpi discoverySpi = igniteExSupplier.get().configuration().getDiscoverySpi();
        boolean unknownNode = true;
        if (discoverySpi instanceof TcpDiscoverySpi) {
            TcpDiscoverySpi tcpDiscoverySpi = (TcpDiscoverySpi) discoverySpi;
            ClusterNode node0 = tcpDiscoverySpi.getNode0(sndId);
            if (node0 != null) {
                assert node0.isClient() : node0;
                if (node0.version().compareTo(VERSION_SINCE_CLIENT_COULD_WAIT_TO_CONNECT) >= 0)
                    unknownNode = false;
            }
        } else if (discoverySpi instanceof IgniteDiscoverySpi)
            unknownNode = !((IgniteDiscoverySpi) discoverySpi).knownNode(sndId);
        if (unknownNode) {
            U.warn(log, "Close incoming connection, unknown node [nodeId=" + sndId + ", ses=" + ses + ']');
            ses.send(new RecoveryLastReceivedMessage(UNKNOWN_NODE)).listen(fut -> ses.close());
        } else
            ses.send(new RecoveryLastReceivedMessage(NEED_WAIT)).listen(fut -> ses.close());
        return;
    }
    ses.addMeta(CONSISTENT_ID_META, rmtNode.consistentId());
    final ConnectionKey old = ses.addMeta(CONN_IDX_META, connKey);
    assert old == null;
    ClusterNode locNode = locNodeSupplier.get();
    if (ses.remoteAddress() == null)
        return;
    assert msg instanceof HandshakeMessage : msg;
    HandshakeMessage msg0 = (HandshakeMessage) msg;
    if (log.isDebugEnabled()) {
        log.debug("Received handshake message [locNodeId=" + locNode.id() + ", rmtNodeId=" + sndId + ", msg=" + msg0 + ']');
    }
    if (isChannelConnIdx(msg0.connectionIndex()))
        ses.send(new RecoveryLastReceivedMessage(0));
    else if (cfg.usePairedConnections() && usePairedConnections(rmtNode, attributeNames.pairedConnection())) {
        final GridNioRecoveryDescriptor recoveryDesc = nioSrvWrapper.inRecoveryDescriptor(rmtNode, connKey);
        ConnectClosureNew c = new ConnectClosureNew(ses, recoveryDesc, rmtNode);
        boolean reserve = recoveryDesc.tryReserve(msg0.connectCount(), c);
        if (reserve)
            connectedNew(recoveryDesc, ses, true);
        else {
            if (c.failed) {
                ses.send(new RecoveryLastReceivedMessage(ALREADY_CONNECTED));
                closeStaleConnections(connKey);
            }
        }
    } else {
        assert connKey.connectionIndex() >= 0 : connKey;
        GridCommunicationClient[] curClients = clientPool.clientFor(sndId);
        GridCommunicationClient oldClient = curClients != null && connKey.connectionIndex() < curClients.length ? curClients[connKey.connectionIndex()] : null;
        if (oldClient instanceof GridTcpNioCommunicationClient) {
            if (log.isInfoEnabled())
                log.info("Received incoming connection when already connected " + "to this node, rejecting [locNode=" + locNode.id() + ", rmtNode=" + sndId + ']');
            ses.send(new RecoveryLastReceivedMessage(ALREADY_CONNECTED));
            closeStaleConnections(connKey);
            return;
        }
        GridFutureAdapter<GridCommunicationClient> fut = new GridFutureAdapter<>();
        GridFutureAdapter<GridCommunicationClient> oldFut = clientPool.putIfAbsentFut(connKey, fut);
        final GridNioRecoveryDescriptor recoveryDesc = nioSrvWrapper.inRecoveryDescriptor(rmtNode, connKey);
        if (oldFut == null) {
            curClients = clientPool.clientFor(sndId);
            oldClient = curClients != null && connKey.connectionIndex() < curClients.length ? curClients[connKey.connectionIndex()] : null;
            if (oldClient instanceof GridTcpNioCommunicationClient) {
                assert oldClient.connectionIndex() == connKey.connectionIndex() : oldClient;
                if (log.isInfoEnabled())
                    log.info("Received incoming connection when already connected " + "to this node, rejecting [locNode=" + locNode.id() + ", rmtNode=" + sndId + ']');
                ses.send(new RecoveryLastReceivedMessage(ALREADY_CONNECTED));
                closeStaleConnections(connKey);
                fut.onDone(oldClient);
                return;
            }
            boolean reserved = recoveryDesc.tryReserve(msg0.connectCount(), new ConnectClosure(ses, recoveryDesc, rmtNode, connKey, msg0, true, fut));
            if (log.isDebugEnabled()) {
                log.debug("Received incoming connection from remote node " + "[rmtNode=" + rmtNode.id() + ", reserved=" + reserved + ", recovery=" + recoveryDesc + ']');
            }
            if (reserved) {
                try {
                    GridTcpNioCommunicationClient client = connected(recoveryDesc, ses, rmtNode, msg0.received(), true, true);
                    fut.onDone(client);
                } finally {
                    clientPool.removeFut(connKey, fut);
                }
            }
        } else {
            if (oldFut instanceof ConnectFuture && locNode.order() < rmtNode.order()) {
                if (log.isInfoEnabled()) {
                    log.info("Received incoming connection from remote node while " + "connecting to this node, rejecting [locNode=" + locNode.id() + ", locNodeOrder=" + locNode.order() + ", rmtNode=" + rmtNode.id() + ", rmtNodeOrder=" + rmtNode.order() + ']');
                }
                ses.send(new RecoveryLastReceivedMessage(ALREADY_CONNECTED));
            } else {
                boolean reserved = recoveryDesc.tryReserve(msg0.connectCount(), new ConnectClosure(ses, recoveryDesc, rmtNode, connKey, msg0, true, fut));
                GridTcpNioCommunicationClient client = null;
                if (reserved)
                    client = connected(recoveryDesc, ses, rmtNode, msg0.received(), true, true);
                if (oldFut instanceof ConnectionRequestFuture && !oldFut.isDone())
                    oldFut.onDone(client);
            }
        }
    }
}
Also used : ClusterNode(org.apache.ignite.cluster.ClusterNode) IgniteInternalFuture(org.apache.ignite.internal.IgniteInternalFuture) CommunicationTcpUtils.usePairedConnections(org.apache.ignite.spi.communication.tcp.internal.CommunicationTcpUtils.usePairedConnections) GridNioSession(org.apache.ignite.internal.util.nio.GridNioSession) GridFutureAdapter(org.apache.ignite.internal.util.future.GridFutureAdapter) NEED_WAIT(org.apache.ignite.spi.communication.tcp.messages.RecoveryLastReceivedMessage.NEED_WAIT) GridNioSessionMetaKey(org.apache.ignite.internal.util.nio.GridNioSessionMetaKey) DiscoverySpi(org.apache.ignite.spi.discovery.DiscoverySpi) CONSISTENT_ID_META(org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi.CONSISTENT_ID_META) FailureProcessor(org.apache.ignite.internal.processors.failure.FailureProcessor) GridTcpNioCommunicationClient(org.apache.ignite.internal.util.nio.GridTcpNioCommunicationClient) Channel(java.nio.channels.Channel) GridNioMessageTracker(org.apache.ignite.internal.util.nio.GridNioMessageTracker) NOOP(org.apache.ignite.spi.communication.tcp.internal.CommunicationTcpUtils.NOOP) FailureType(org.apache.ignite.failure.FailureType) IgniteInClosure(org.apache.ignite.lang.IgniteInClosure) NodeIdMessage(org.apache.ignite.spi.communication.tcp.messages.NodeIdMessage) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) SpanTags(org.apache.ignite.internal.processors.tracing.SpanTags) IgniteRunnable(org.apache.ignite.lang.IgniteRunnable) UUID(java.util.UUID) RecoveryLastReceivedMessage(org.apache.ignite.spi.communication.tcp.messages.RecoveryLastReceivedMessage) AttributeNames(org.apache.ignite.spi.communication.tcp.AttributeNames) CountDownLatch(java.util.concurrent.CountDownLatch) Nullable(org.jetbrains.annotations.Nullable) MTC(org.apache.ignite.internal.processors.tracing.MTC) TraceableMessagesTable.traceName(org.apache.ignite.internal.processors.tracing.messages.TraceableMessagesTable.traceName) CHANNEL_FUT_META(org.apache.ignite.spi.communication.tcp.internal.GridNioServerWrapper.CHANNEL_FUT_META) Message(org.apache.ignite.plugin.extensions.communication.Message) GridCommunicationClient(org.apache.ignite.internal.util.nio.GridCommunicationClient) IgniteProductVersion(org.apache.ignite.lang.IgniteProductVersion) NODE_STOPPING(org.apache.ignite.spi.communication.tcp.messages.RecoveryLastReceivedMessage.NODE_STOPPING) ALREADY_CONNECTED(org.apache.ignite.spi.communication.tcp.messages.RecoveryLastReceivedMessage.ALREADY_CONNECTED) CommunicationListener(org.apache.ignite.spi.communication.CommunicationListener) TcpCommunicationMetricsListener(org.apache.ignite.spi.communication.tcp.TcpCommunicationMetricsListener) Span(org.apache.ignite.internal.processors.tracing.Span) GridSelectorNioSessionImpl(org.apache.ignite.internal.util.nio.GridSelectorNioSessionImpl) U(org.apache.ignite.internal.util.typedef.internal.U) IgniteLogger(org.apache.ignite.IgniteLogger) Function(java.util.function.Function) Supplier(java.util.function.Supplier) IgniteDiscoverySpi(org.apache.ignite.internal.managers.discovery.IgniteDiscoverySpi) LT(org.apache.ignite.internal.util.typedef.internal.LT) ClusterNode(org.apache.ignite.cluster.ClusterNode) FailureContext(org.apache.ignite.failure.FailureContext) CONN_IDX_META(org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi.CONN_IDX_META) Ignite(org.apache.ignite.Ignite) MAX_CONN_PER_NODE(org.apache.ignite.spi.communication.tcp.internal.GridNioServerWrapper.MAX_CONN_PER_NODE) SES_FUT_META(org.apache.ignite.spi.communication.tcp.internal.TcpCommunicationConnectionCheckFuture.SES_FUT_META) HandshakeMessage(org.apache.ignite.spi.communication.tcp.messages.HandshakeMessage) GridNioServerListenerAdapter(org.apache.ignite.internal.util.nio.GridNioServerListenerAdapter) TcpDiscoverySpi(org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi) UNKNOWN_NODE(org.apache.ignite.spi.communication.tcp.messages.RecoveryLastReceivedMessage.UNKNOWN_NODE) GridNioRecoveryDescriptor(org.apache.ignite.internal.util.nio.GridNioRecoveryDescriptor) HandshakeWaitMessage(org.apache.ignite.spi.communication.tcp.messages.HandshakeWaitMessage) RecoveryLastReceivedMessage(org.apache.ignite.spi.communication.tcp.messages.RecoveryLastReceivedMessage) GridCommunicationClient(org.apache.ignite.internal.util.nio.GridCommunicationClient) GridTcpNioCommunicationClient(org.apache.ignite.internal.util.nio.GridTcpNioCommunicationClient) HandshakeMessage(org.apache.ignite.spi.communication.tcp.messages.HandshakeMessage) NodeIdMessage(org.apache.ignite.spi.communication.tcp.messages.NodeIdMessage) DiscoverySpi(org.apache.ignite.spi.discovery.DiscoverySpi) IgniteDiscoverySpi(org.apache.ignite.internal.managers.discovery.IgniteDiscoverySpi) TcpDiscoverySpi(org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi) GridNioRecoveryDescriptor(org.apache.ignite.internal.util.nio.GridNioRecoveryDescriptor) GridFutureAdapter(org.apache.ignite.internal.util.future.GridFutureAdapter) UUID(java.util.UUID) IgniteDiscoverySpi(org.apache.ignite.internal.managers.discovery.IgniteDiscoverySpi) TcpDiscoverySpi(org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi)

Aggregations

UUID (java.util.UUID)2 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)2 ClusterNode (org.apache.ignite.cluster.ClusterNode)2 HandshakeMessage (org.apache.ignite.spi.communication.tcp.messages.HandshakeMessage)2 IOException (java.io.IOException)1 ByteBuffer (java.nio.ByteBuffer)1 Channel (java.nio.channels.Channel)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 Function (java.util.function.Function)1 Supplier (java.util.function.Supplier)1 Ignite (org.apache.ignite.Ignite)1 IgniteLogger (org.apache.ignite.IgniteLogger)1 FailureContext (org.apache.ignite.failure.FailureContext)1 FailureType (org.apache.ignite.failure.FailureType)1 IgniteInternalFuture (org.apache.ignite.internal.IgniteInternalFuture)1 IgniteDiscoverySpi (org.apache.ignite.internal.managers.discovery.IgniteDiscoverySpi)1 FailureProcessor (org.apache.ignite.internal.processors.failure.FailureProcessor)1 MTC (org.apache.ignite.internal.processors.tracing.MTC)1 Span (org.apache.ignite.internal.processors.tracing.Span)1 SpanTags (org.apache.ignite.internal.processors.tracing.SpanTags)1