Search in sources :

Example 1 with NodeInformant

use of org.apache.nifi.remote.cluster.NodeInformant 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

DataInputStream (java.io.DataInputStream)1 DataOutputStream (java.io.DataOutputStream)1 EOFException (java.io.EOFException)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 OutputStream (java.io.OutputStream)1 InetAddress (java.net.InetAddress)1 InetSocketAddress (java.net.InetSocketAddress)1 ServerSocket (java.net.ServerSocket)1 Socket (java.net.Socket)1 SocketTimeoutException (java.net.SocketTimeoutException)1 ServerSocketChannel (java.nio.channels.ServerSocketChannel)1 SocketChannel (java.nio.channels.SocketChannel)1 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 List (java.util.List)1 Optional (java.util.Optional)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1 SSLContext (javax.net.ssl.SSLContext)1