Search in sources :

Example 1 with BlockingSslHandler

use of org.apache.ignite.internal.util.nio.ssl.BlockingSslHandler in project ignite by apache.

the class TcpCommunicationSpi method safeHandshake.

/**
     * Performs handshake in timeout-safe way.
     *
     * @param client Client.
     * @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 <T> long safeHandshake(T client, @Nullable GridNioRecoveryDescriptor recovery, UUID rmtNodeId, long timeout, GridSslMeta sslMeta, @Nullable Integer handshakeConnIdx) throws IgniteCheckedException {
    HandshakeTimeoutObject<T> obj = new HandshakeTimeoutObject<>(client, U.currentTimeMillis() + timeout);
    addTimeoutObject(obj);
    long rcvCnt = 0;
    try {
        if (client instanceof GridCommunicationClient)
            ((GridCommunicationClient) client).doHandshake(new HandshakeClosure(rmtNodeId));
        else {
            SocketChannel ch = (SocketChannel) client;
            boolean success = false;
            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 IgniteCheckedException("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 IgniteCheckedException("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 IgniteCheckedException("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 IgniteCheckedException("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)));
                    } else
                        ch.write(ByteBuffer.wrap(nodeIdMessage().nodeIdBytesWithType));
                }
                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 IgniteCheckedException("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 IgniteCheckedException("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 + ']');
                    } else
                        success = true;
                } else
                    success = true;
            } catch (IOException e) {
                if (log.isDebugEnabled())
                    log.debug("Failed to read from channel: " + e);
                throw new IgniteCheckedException("Failed to read from channel.", e);
            } finally {
                if (!success)
                    U.closeQuiet(ch);
            }
        }
    } finally {
        boolean cancelled = obj.cancel();
        if (cancelled)
            removeTimeoutObject(obj);
        // Ignoring whatever happened after timeout - reporting only timeout event.
        if (!cancelled)
            throw new HandshakeTimeoutException("Failed to perform handshake due to timeout (consider increasing " + "'connectionTimeout' configuration property).");
    }
    return rcvCnt;
}
Also used : ClusterNode(org.apache.ignite.cluster.ClusterNode) SocketChannel(java.nio.channels.SocketChannel) BlockingSslHandler(org.apache.ignite.internal.util.nio.ssl.BlockingSslHandler) IOException(java.io.IOException) GridCommunicationClient(org.apache.ignite.internal.util.nio.GridCommunicationClient) 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) EVT_NODE_LEFT(org.apache.ignite.events.EventType.EVT_NODE_LEFT) LT(org.apache.ignite.internal.util.typedef.internal.LT) UUID(java.util.UUID)

Aggregations

IOException (java.io.IOException)1 ByteBuffer (java.nio.ByteBuffer)1 SocketChannel (java.nio.channels.SocketChannel)1 UUID (java.util.UUID)1 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)1 ClusterNode (org.apache.ignite.cluster.ClusterNode)1 EVT_NODE_LEFT (org.apache.ignite.events.EventType.EVT_NODE_LEFT)1 IpcEndpoint (org.apache.ignite.internal.util.ipc.IpcEndpoint)1 IpcSharedMemoryServerEndpoint (org.apache.ignite.internal.util.ipc.shmem.IpcSharedMemoryServerEndpoint)1 GridCommunicationClient (org.apache.ignite.internal.util.nio.GridCommunicationClient)1 BlockingSslHandler (org.apache.ignite.internal.util.nio.ssl.BlockingSslHandler)1 LT (org.apache.ignite.internal.util.typedef.internal.LT)1