Search in sources :

Example 1 with SSLSocketChannel

use of org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel in project nifi by apache.

the class SocketChannelDispatcher method run.

@Override
public void run() {
    while (!stopped) {
        try {
            int selected = selector.select();
            // if stopped the selector could already be closed which would result in a ClosedSelectorException
            if (selected > 0 && !stopped) {
                Iterator<SelectionKey> selectorKeys = selector.selectedKeys().iterator();
                // if stopped we don't want to modify the keys because close() may still be in progress
                while (selectorKeys.hasNext() && !stopped) {
                    SelectionKey key = selectorKeys.next();
                    selectorKeys.remove();
                    if (!key.isValid()) {
                        continue;
                    }
                    if (key.isAcceptable()) {
                        // Handle new connections coming in
                        final ServerSocketChannel channel = (ServerSocketChannel) key.channel();
                        final SocketChannel socketChannel = channel.accept();
                        // Check for available connections
                        if (currentConnections.incrementAndGet() > maxConnections) {
                            currentConnections.decrementAndGet();
                            logger.warn("Rejecting connection from {} because max connections has been met", new Object[] { socketChannel.getRemoteAddress().toString() });
                            IOUtils.closeQuietly(socketChannel);
                            continue;
                        }
                        logger.debug("Accepted incoming connection from {}", new Object[] { socketChannel.getRemoteAddress().toString() });
                        // Set socket to non-blocking, and register with selector
                        socketChannel.configureBlocking(false);
                        SelectionKey readKey = socketChannel.register(selector, SelectionKey.OP_READ);
                        // Prepare the byte buffer for the reads, clear it out
                        ByteBuffer buffer = bufferPool.poll();
                        buffer.clear();
                        buffer.mark();
                        // If we have an SSLContext then create an SSLEngine for the channel
                        SSLSocketChannel sslSocketChannel = null;
                        if (sslContext != null) {
                            final SSLEngine sslEngine = sslContext.createSSLEngine();
                            sslEngine.setUseClientMode(false);
                            switch(clientAuth) {
                                case REQUIRED:
                                    sslEngine.setNeedClientAuth(true);
                                    break;
                                case WANT:
                                    sslEngine.setWantClientAuth(true);
                                    break;
                                case NONE:
                                    sslEngine.setNeedClientAuth(false);
                                    sslEngine.setWantClientAuth(false);
                                    break;
                            }
                            sslSocketChannel = new SSLSocketChannel(sslEngine, socketChannel);
                        }
                        // Attach the buffer and SSLSocketChannel to the key
                        SocketChannelAttachment attachment = new SocketChannelAttachment(buffer, sslSocketChannel);
                        readKey.attach(attachment);
                    } else if (key.isReadable()) {
                        // Clear out the operations the select is interested in until done reading
                        key.interestOps(0);
                        // Create a handler based on the protocol and whether an SSLEngine was provided or not
                        final Runnable handler;
                        if (sslContext != null) {
                            handler = handlerFactory.createSSLHandler(key, this, charset, eventFactory, events, logger);
                        } else {
                            handler = handlerFactory.createHandler(key, this, charset, eventFactory, events, logger);
                        }
                        // run the handler
                        executor.execute(handler);
                    }
                }
            }
            // Add back all idle sockets to the select
            SelectionKey key;
            while ((key = keyQueue.poll()) != null) {
                key.interestOps(SelectionKey.OP_READ);
            }
        } catch (IOException e) {
            logger.error("Error accepting connection from SocketChannel", e);
        }
    }
}
Also used : SelectionKey(java.nio.channels.SelectionKey) SocketChannel(java.nio.channels.SocketChannel) SSLSocketChannel(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel) ServerSocketChannel(java.nio.channels.ServerSocketChannel) SSLSocketChannel(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel) SSLEngine(javax.net.ssl.SSLEngine) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) ServerSocketChannel(java.nio.channels.ServerSocketChannel)

Example 2 with SSLSocketChannel

use of org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel in project nifi by apache.

the class SSLSocketChannelHandler method run.

@Override
public void run() {
    boolean eof = false;
    SSLSocketChannel sslSocketChannel = null;
    try {
        int bytesRead;
        final SocketChannel socketChannel = (SocketChannel) key.channel();
        final SocketChannelAttachment attachment = (SocketChannelAttachment) key.attachment();
        // get the SSLSocketChannel from the attachment
        sslSocketChannel = attachment.getSslSocketChannel();
        // SSLSocketChannel deals with byte[] so ByteBuffer isn't used here, but we'll use the size to create a new byte[]
        final ByteBuffer socketBuffer = attachment.getByteBuffer();
        byte[] socketBufferArray = new byte[socketBuffer.limit()];
        // read until no more data
        try {
            while ((bytesRead = sslSocketChannel.read(socketBufferArray)) > 0) {
                processBuffer(sslSocketChannel, socketChannel, bytesRead, socketBufferArray);
                logger.debug("bytes read from sslSocketChannel {}", new Object[] { bytesRead });
            }
        } catch (SocketTimeoutException ste) {
            // SSLSocketChannel will throw this exception when 0 bytes are read and the timeout threshold
            // is exceeded, we don't want to close the connection in this case
            bytesRead = 0;
        }
        // Check for closed socket
        if (bytesRead < 0) {
            eof = true;
            logger.debug("Reached EOF, closing connection");
        } else {
            logger.debug("No more data available, returning for selection");
        }
    } catch (ClosedByInterruptException | InterruptedException e) {
        logger.debug("read loop interrupted, closing connection");
        // Treat same as closed socket
        eof = true;
    } catch (ClosedChannelException e) {
        // ClosedChannelException doesn't have a message so handle it separately from IOException
        logger.error("Error reading from channel due to channel being closed", e);
        // Treat same as closed socket
        eof = true;
    } catch (IOException e) {
        logger.error("Error reading from channel due to {}", new Object[] { e.getMessage() }, e);
        // Treat same as closed socket
        eof = true;
    } finally {
        if (eof == true) {
            IOUtils.closeQuietly(sslSocketChannel);
            dispatcher.completeConnection(key);
        } else {
            dispatcher.addBackForSelection(key);
        }
    }
}
Also used : SSLSocketChannel(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel) SocketChannel(java.nio.channels.SocketChannel) ClosedChannelException(java.nio.channels.ClosedChannelException) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) SocketChannelAttachment(org.apache.nifi.processor.util.listen.dispatcher.SocketChannelAttachment) ClosedByInterruptException(java.nio.channels.ClosedByInterruptException) SSLSocketChannel(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel) SocketTimeoutException(java.net.SocketTimeoutException)

Example 3 with SSLSocketChannel

use of org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel in project nifi by apache.

the class SSLSocketChannelSender method open.

@Override
public void open() throws IOException {
    if (sslChannel == null) {
        super.open();
        sslChannel = new SSLSocketChannel(sslContext, channel, true);
    }
    sslChannel.setTimeout(timeout);
    // SSLSocketChannel will check if already connected so we can safely call this
    sslChannel.connect();
    sslOutputStream = new SSLSocketChannelOutputStream(sslChannel);
}
Also used : SSLSocketChannelOutputStream(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannelOutputStream) SSLSocketChannel(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel)

Example 4 with SSLSocketChannel

use of org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel in project nifi by apache.

the class SocketChannelRecordReaderDispatcher method run.

@Override
public void run() {
    while (!stopped) {
        try {
            final SocketChannel socketChannel = serverSocketChannel.accept();
            if (socketChannel == null) {
                Thread.sleep(20);
                continue;
            }
            final SocketAddress remoteSocketAddress = socketChannel.getRemoteAddress();
            socketChannel.socket().setSoTimeout(socketReadTimeout);
            socketChannel.socket().setReceiveBufferSize(receiveBufferSize);
            if (currentConnections.incrementAndGet() > maxConnections) {
                currentConnections.decrementAndGet();
                final String remoteAddress = remoteSocketAddress == null ? "null" : remoteSocketAddress.toString();
                logger.warn("Rejecting connection from {} because max connections has been met", new Object[] { remoteAddress });
                IOUtils.closeQuietly(socketChannel);
                continue;
            }
            if (logger.isDebugEnabled()) {
                final String remoteAddress = remoteSocketAddress == null ? "null" : remoteSocketAddress.toString();
                logger.debug("Accepted connection from {}", new Object[] { remoteAddress });
            }
            // create a StandardSocketChannelRecordReader or an SSLSocketChannelRecordReader based on presence of SSLContext
            final SocketChannelRecordReader socketChannelRecordReader;
            if (sslContext == null) {
                socketChannelRecordReader = new StandardSocketChannelRecordReader(socketChannel, readerFactory, this);
            } else {
                final SSLEngine sslEngine = sslContext.createSSLEngine();
                sslEngine.setUseClientMode(false);
                switch(clientAuth) {
                    case REQUIRED:
                        sslEngine.setNeedClientAuth(true);
                        break;
                    case WANT:
                        sslEngine.setWantClientAuth(true);
                        break;
                    case NONE:
                        sslEngine.setNeedClientAuth(false);
                        sslEngine.setWantClientAuth(false);
                        break;
                }
                final SSLSocketChannel sslSocketChannel = new SSLSocketChannel(sslEngine, socketChannel);
                socketChannelRecordReader = new SSLSocketChannelRecordReader(socketChannel, sslSocketChannel, readerFactory, this);
            }
            // queue the SocketChannelRecordReader for processing by the processor
            recordReaders.offer(socketChannelRecordReader);
        } catch (Exception e) {
            logger.error("Error dispatching connection: " + e.getMessage(), e);
        }
    }
}
Also used : SSLSocketChannel(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel) SocketChannel(java.nio.channels.SocketChannel) ServerSocketChannel(java.nio.channels.ServerSocketChannel) SSLSocketChannel(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel) SSLEngine(javax.net.ssl.SSLEngine) SocketAddress(java.net.SocketAddress)

Example 5 with SSLSocketChannel

use of org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel in project nifi by apache.

the class SocketRemoteSiteListener method start.

@Override
public void start() throws IOException {
    final boolean secure = (sslContext != null);
    final List<Thread> threads = new ArrayList<Thread>();
    final ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.configureBlocking(true);
    serverSocketChannel.bind(new InetSocketAddress(socketPort));
    stopped.set(false);
    final Thread listenerThread = new Thread(new Runnable() {

        private int threadCount = 0;

        @Override
        public void run() {
            while (!stopped.get()) {
                final ProcessGroup processGroup = rootGroup.get();
                // the processGroup.
                if ((nodeInformant == null) && (processGroup == null || (processGroup.getInputPorts().isEmpty() && processGroup.getOutputPorts().isEmpty()))) {
                    try {
                        Thread.sleep(2000L);
                    } catch (final Exception e) {
                    }
                    continue;
                }
                LOG.trace("Accepting Connection...");
                Socket acceptedSocket = null;
                try {
                    serverSocketChannel.configureBlocking(false);
                    final ServerSocket serverSocket = serverSocketChannel.socket();
                    serverSocket.setSoTimeout(2000);
                    while (!stopped.get() && acceptedSocket == null) {
                        try {
                            acceptedSocket = serverSocket.accept();
                        } catch (final SocketTimeoutException ste) {
                            continue;
                        }
                    }
                } catch (final IOException e) {
                    LOG.error("RemoteSiteListener Unable to accept connection due to {}", e.toString());
                    if (LOG.isDebugEnabled()) {
                        LOG.error("", e);
                    }
                    continue;
                }
                LOG.trace("Got connection");
                if (stopped.get()) {
                    break;
                }
                final Socket socket = acceptedSocket;
                final SocketChannel socketChannel = socket.getChannel();
                final Thread thread = new Thread(new Runnable() {

                    @Override
                    public void run() {
                        LOG.debug("{} Determining URL of connection", this);
                        final InetAddress inetAddress = socket.getInetAddress();
                        String clientHostName = inetAddress.getHostName();
                        final int slashIndex = clientHostName.indexOf("/");
                        if (slashIndex == 0) {
                            clientHostName = clientHostName.substring(1);
                        } else if (slashIndex > 0) {
                            clientHostName = clientHostName.substring(0, slashIndex);
                        }
                        final int clientPort = socket.getPort();
                        final String peerUri = "nifi://" + clientHostName + ":" + clientPort;
                        LOG.debug("{} Connection URL is {}", this, peerUri);
                        final CommunicationsSession commsSession;
                        final String dn;
                        try {
                            if (secure) {
                                final SSLSocketChannel sslSocketChannel = new SSLSocketChannel(sslContext, socketChannel, false);
                                LOG.trace("Channel is secure; connecting...");
                                sslSocketChannel.connect();
                                LOG.trace("Channel connected");
                                commsSession = new SSLSocketChannelCommunicationsSession(sslSocketChannel);
                                dn = sslSocketChannel.getDn();
                                commsSession.setUserDn(dn);
                            } else {
                                LOG.trace("{} Channel is not secure", this);
                                commsSession = new SocketChannelCommunicationsSession(socketChannel);
                                dn = null;
                            }
                        } catch (final Exception e) {
                            LOG.error("RemoteSiteListener Unable to accept connection from {} due to {}", socket, e.toString());
                            if (LOG.isDebugEnabled()) {
                                LOG.error("", e);
                            }
                            try {
                                socketChannel.close();
                            } catch (IOException swallow) {
                            }
                            return;
                        }
                        LOG.info("Received connection from {}, User DN: {}", socket.getInetAddress(), dn);
                        final InputStream socketIn;
                        final OutputStream socketOut;
                        try {
                            socketIn = commsSession.getInput().getInputStream();
                            socketOut = commsSession.getOutput().getOutputStream();
                        } catch (final IOException e) {
                            LOG.error("Connection dropped from {} before any data was transmitted", peerUri);
                            try {
                                commsSession.close();
                            } catch (final IOException ioe) {
                            }
                            return;
                        }
                        final DataInputStream dis = new DataInputStream(socketIn);
                        final DataOutputStream dos = new DataOutputStream(socketOut);
                        ServerProtocol protocol = null;
                        Peer peer = null;
                        try {
                            // ensure that we are communicating with another NiFi
                            LOG.debug("Verifying magic bytes...");
                            verifyMagicBytes(dis, peerUri);
                            LOG.debug("Receiving Server Protocol Negotiation");
                            protocol = RemoteResourceFactory.receiveServerProtocolNegotiation(dis, dos);
                            protocol.setRootProcessGroup(rootGroup.get());
                            protocol.setNodeInformant(nodeInformant);
                            final PeerDescription description = new PeerDescription(clientHostName, clientPort, sslContext != null);
                            peer = new Peer(description, commsSession, peerUri, "nifi://localhost:" + getPort());
                            LOG.debug("Handshaking....");
                            protocol.handshake(peer);
                            if (!protocol.isHandshakeSuccessful()) {
                                LOG.error("Handshake failed with {}; closing connection", peer);
                                try {
                                    peer.close();
                                } catch (final IOException e) {
                                    LOG.warn("Failed to close {} due to {}", peer, e);
                                }
                                // no need to shutdown protocol because we failed to perform handshake
                                return;
                            }
                            commsSession.setTimeout((int) protocol.getRequestExpiration());
                            LOG.info("Successfully negotiated ServerProtocol {} Version {} with {}", new Object[] { protocol.getResourceName(), protocol.getVersionNegotiator().getVersion(), peer });
                            try {
                                while (!protocol.isShutdown()) {
                                    LOG.trace("Getting Protocol Request Type...");
                                    int timeoutCount = 0;
                                    RequestType requestType = null;
                                    while (requestType == null) {
                                        try {
                                            requestType = protocol.getRequestType(peer);
                                        } catch (final SocketTimeoutException e) {
                                            // Give the timeout a bit longer (twice as long) to receive the Request Type,
                                            // in order to attempt to receive more data without shutting down the socket if we don't
                                            // have to.
                                            LOG.debug("{} Timed out waiting to receive RequestType using {} with {}", new Object[] { this, protocol, peer });
                                            timeoutCount++;
                                            requestType = null;
                                            if (timeoutCount >= 2) {
                                                throw e;
                                            }
                                        }
                                    }
                                    handleRequest(protocol, peer, requestType);
                                }
                                LOG.debug("Finished communicating with {} ({})", peer, protocol);
                            } catch (final Exception e) {
                                LOG.error("Unable to communicate with remote instance {} ({}) due to {}; closing connection", peer, protocol, e.toString());
                                if (LOG.isDebugEnabled()) {
                                    LOG.error("", e);
                                }
                            }
                        } catch (final IOException e) {
                            LOG.error("Unable to communicate with remote instance {} due to {}; closing connection", peer, e.toString());
                            if (LOG.isDebugEnabled()) {
                                LOG.error("", e);
                            }
                        } catch (final Throwable t) {
                            LOG.error("Handshake failed when communicating with {}; closing connection. Reason for failure: {}", peerUri, t.toString());
                            if (LOG.isDebugEnabled()) {
                                LOG.error("", t);
                            }
                        } finally {
                            LOG.trace("Cleaning up");
                            try {
                                if (protocol != null && peer != null) {
                                    protocol.shutdown(peer);
                                }
                            } catch (final Exception protocolException) {
                                LOG.warn("Failed to shutdown protocol due to {}", protocolException.toString());
                            }
                            try {
                                if (peer != null) {
                                    peer.close();
                                }
                            } catch (final Exception peerException) {
                                LOG.warn("Failed to close peer due to {}; some resources may not be appropriately cleaned up", peerException.toString());
                            }
                            LOG.trace("Finished cleaning up");
                        }
                    }
                });
                thread.setName("Site-to-Site Worker Thread-" + (threadCount++));
                LOG.debug("Handing connection to {}", thread);
                thread.start();
                threads.add(thread);
                threads.removeIf(t -> !t.isAlive());
            }
            for (Thread thread : threads) {
                if (thread != null) {
                    thread.interrupt();
                }
            }
        }
    });
    listenerThread.setName("Site-to-Site Listener");
    listenerThread.start();
}
Also used : DataInputStream(java.io.DataInputStream) SSLContext(javax.net.ssl.SSLContext) Socket(java.net.Socket) Arrays(java.util.Arrays) ProcessGroup(org.apache.nifi.groups.ProcessGroup) BadRequestException(org.apache.nifi.remote.exception.BadRequestException) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) NodeInformant(org.apache.nifi.remote.cluster.NodeInformant) NotAuthorizedException(org.apache.nifi.remote.exception.NotAuthorizedException) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) InetAddress(java.net.InetAddress) ServerSocket(java.net.ServerSocket) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) SocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.SocketChannelCommunicationsSession) DataOutputStream(java.io.DataOutputStream) SocketChannel(java.nio.channels.SocketChannel) SocketTimeoutException(java.net.SocketTimeoutException) ServerProtocol(org.apache.nifi.remote.protocol.ServerProtocol) CommunicationsSession(org.apache.nifi.remote.protocol.CommunicationsSession) OutputStream(java.io.OutputStream) RequestType(org.apache.nifi.remote.protocol.RequestType) NodeInformation(org.apache.nifi.remote.cluster.NodeInformation) Logger(org.slf4j.Logger) SSLSocketChannel(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel) IOException(java.io.IOException) SSLSocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannelCommunicationsSession) EOFException(java.io.EOFException) InetSocketAddress(java.net.InetSocketAddress) ServerSocketChannel(java.nio.channels.ServerSocketChannel) List(java.util.List) NiFiProperties(org.apache.nifi.util.NiFiProperties) RequestExpiredException(org.apache.nifi.remote.exception.RequestExpiredException) Optional(java.util.Optional) ClusterNodeInformation(org.apache.nifi.remote.cluster.ClusterNodeInformation) InputStream(java.io.InputStream) SocketChannel(java.nio.channels.SocketChannel) SSLSocketChannel(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel) ServerSocketChannel(java.nio.channels.ServerSocketChannel) SSLSocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannelCommunicationsSession) InetSocketAddress(java.net.InetSocketAddress) DataOutputStream(java.io.DataOutputStream) DataOutputStream(java.io.DataOutputStream) OutputStream(java.io.OutputStream) ArrayList(java.util.ArrayList) SocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.SocketChannelCommunicationsSession) CommunicationsSession(org.apache.nifi.remote.protocol.CommunicationsSession) SSLSocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannelCommunicationsSession) ServerSocketChannel(java.nio.channels.ServerSocketChannel) DataInputStream(java.io.DataInputStream) InputStream(java.io.InputStream) ServerSocket(java.net.ServerSocket) IOException(java.io.IOException) DataInputStream(java.io.DataInputStream) ServerProtocol(org.apache.nifi.remote.protocol.ServerProtocol) BadRequestException(org.apache.nifi.remote.exception.BadRequestException) NotAuthorizedException(org.apache.nifi.remote.exception.NotAuthorizedException) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) SocketTimeoutException(java.net.SocketTimeoutException) IOException(java.io.IOException) EOFException(java.io.EOFException) RequestExpiredException(org.apache.nifi.remote.exception.RequestExpiredException) SocketTimeoutException(java.net.SocketTimeoutException) SSLSocketChannel(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel) ProcessGroup(org.apache.nifi.groups.ProcessGroup) SocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.SocketChannelCommunicationsSession) SSLSocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannelCommunicationsSession) InetAddress(java.net.InetAddress) Socket(java.net.Socket) ServerSocket(java.net.ServerSocket) RequestType(org.apache.nifi.remote.protocol.RequestType)

Aggregations

SSLSocketChannel (org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel)7 SocketChannel (java.nio.channels.SocketChannel)6 IOException (java.io.IOException)5 ServerSocketChannel (java.nio.channels.ServerSocketChannel)4 InetSocketAddress (java.net.InetSocketAddress)3 SocketTimeoutException (java.net.SocketTimeoutException)3 InputStream (java.io.InputStream)2 OutputStream (java.io.OutputStream)2 SocketAddress (java.net.SocketAddress)2 ByteBuffer (java.nio.ByteBuffer)2 SSLEngine (javax.net.ssl.SSLEngine)2 SocketChannelCommunicationsSession (org.apache.nifi.remote.io.socket.SocketChannelCommunicationsSession)2 SSLSocketChannelCommunicationsSession (org.apache.nifi.remote.io.socket.ssl.SSLSocketChannelCommunicationsSession)2 CommunicationsSession (org.apache.nifi.remote.protocol.CommunicationsSession)2 BufferedInputStream (java.io.BufferedInputStream)1 BufferedOutputStream (java.io.BufferedOutputStream)1 DataInputStream (java.io.DataInputStream)1 DataOutputStream (java.io.DataOutputStream)1 EOFException (java.io.EOFException)1 InetAddress (java.net.InetAddress)1