Search in sources :

Example 11 with CommunicationsSession

use of org.apache.nifi.remote.protocol.CommunicationsSession in project nifi by apache.

the class SocketFlowFileServerProtocol method negotiateCodec.

@Override
public FlowFileCodec negotiateCodec(final Peer peer) throws IOException, ProtocolException {
    if (!handshakeCompleted) {
        throw new IllegalStateException("Handshake has not been completed");
    }
    if (shutdown) {
        throw new IllegalStateException("Protocol is shutdown");
    }
    logger.debug("{} Negotiating Codec with {} using {}", new Object[] { this, peer, peer.getCommunicationsSession() });
    final CommunicationsSession commsSession = peer.getCommunicationsSession();
    final DataInputStream dis = new DataInputStream(commsSession.getInput().getInputStream());
    final DataOutputStream dos = new DataOutputStream(commsSession.getOutput().getOutputStream());
    if (port == null) {
        RemoteResourceFactory.rejectCodecNegotiation(dis, dos, "Cannot transfer FlowFiles because no port was specified");
    }
    // Negotiate the FlowFileCodec to use.
    try {
        negotiatedFlowFileCodec = RemoteResourceFactory.receiveCodecNegotiation(dis, dos);
        logger.debug("{} Negotiated Codec {} with {}", new Object[] { this, negotiatedFlowFileCodec, peer });
        return negotiatedFlowFileCodec;
    } catch (final HandshakeException e) {
        throw new ProtocolException(e.toString());
    }
}
Also used : ProtocolException(org.apache.nifi.remote.exception.ProtocolException) DataOutputStream(java.io.DataOutputStream) CommunicationsSession(org.apache.nifi.remote.protocol.CommunicationsSession) DataInputStream(java.io.DataInputStream) HandshakeException(org.apache.nifi.remote.exception.HandshakeException)

Example 12 with CommunicationsSession

use of org.apache.nifi.remote.protocol.CommunicationsSession in project nifi by apache.

the class EndpointConnectionPool method establishSiteToSiteConnection.

private CommunicationsSession establishSiteToSiteConnection(final String hostname, final int port) throws IOException {
    final boolean siteToSiteSecure = siteInfoProvider.isSecure();
    CommunicationsSession commsSession = null;
    try {
        if (siteToSiteSecure) {
            if (sslContext == null) {
                throw new IOException("Unable to communicate with " + hostname + ":" + port + " because it requires Secure Site-to-Site communications, but this instance is not configured for secure communications");
            }
            final SSLSocketChannel socketChannel = new SSLSocketChannel(sslContext, hostname, port, localAddress, true);
            socketChannel.connect();
            commsSession = new SSLSocketChannelCommunicationsSession(socketChannel);
            try {
                commsSession.setUserDn(socketChannel.getDn());
            } catch (final CertificateException ex) {
                throw new IOException(ex);
            }
        } else {
            final SocketChannel socketChannel = SocketChannel.open();
            if (localAddress != null) {
                final SocketAddress localSocketAddress = new InetSocketAddress(localAddress, 0);
                socketChannel.socket().bind(localSocketAddress);
            }
            socketChannel.socket().connect(new InetSocketAddress(hostname, port), commsTimeout);
            socketChannel.socket().setSoTimeout(commsTimeout);
            commsSession = new SocketChannelCommunicationsSession(socketChannel);
        }
        commsSession.getOutput().getOutputStream().write(CommunicationsSession.MAGIC_BYTES);
    } catch (final IOException ioe) {
        if (commsSession != null) {
            commsSession.close();
        }
        throw ioe;
    }
    return commsSession;
}
Also used : SocketChannel(java.nio.channels.SocketChannel) SSLSocketChannel(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel) SSLSocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannelCommunicationsSession) SSLSocketChannel(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannel) InetSocketAddress(java.net.InetSocketAddress) CertificateException(java.security.cert.CertificateException) CommunicationsSession(org.apache.nifi.remote.protocol.CommunicationsSession) SocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.SocketChannelCommunicationsSession) SSLSocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannelCommunicationsSession) IOException(java.io.IOException) SocketAddress(java.net.SocketAddress) InetSocketAddress(java.net.InetSocketAddress) SocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.SocketChannelCommunicationsSession) SSLSocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannelCommunicationsSession)

Example 13 with CommunicationsSession

use of org.apache.nifi.remote.protocol.CommunicationsSession in project nifi by apache.

the class EndpointConnectionPool method getEndpointConnection.

public EndpointConnection getEndpointConnection(final TransferDirection direction, final SiteToSiteClientConfig config) throws IOException {
    // 
    // Attempt to get a connection state that already exists for this URL.
    // 
    FlowFileCodec codec = null;
    CommunicationsSession commsSession = null;
    SocketClientProtocol protocol = null;
    EndpointConnection connection;
    Peer peer = null;
    final URI clusterUrl;
    try {
        clusterUrl = siteInfoProvider.getActiveClusterUrl();
    } catch (final IOException ioe) {
        throw new UnreachableClusterException("Unable to refresh details from any of the configured remote instances.", ioe);
    }
    do {
        final List<EndpointConnection> addBack = new ArrayList<>();
        logger.debug("{} getting next peer status", this);
        final PeerStatus peerStatus = peerSelector.getNextPeerStatus(direction);
        logger.debug("{} next peer status = {}", this, peerStatus);
        if (peerStatus == null) {
            return null;
        }
        final PeerDescription peerDescription = peerStatus.getPeerDescription();
        BlockingQueue<EndpointConnection> connectionQueue = connectionQueueMap.get(peerDescription);
        if (connectionQueue == null) {
            connectionQueue = new LinkedBlockingQueue<>();
            BlockingQueue<EndpointConnection> existing = connectionQueueMap.putIfAbsent(peerDescription, connectionQueue);
            if (existing != null) {
                connectionQueue = existing;
            }
        }
        try {
            connection = connectionQueue.poll();
            logger.debug("{} Connection State for {} = {}", this, clusterUrl, connection);
            final String portId = getPortIdentifier(direction);
            if (connection == null && !addBack.isEmpty()) {
                // all available connections have been penalized.
                logger.debug("{} all Connections for {} are penalized; returning no Connection", this, portId);
                return null;
            }
            if (connection != null && connection.getPeer().isPenalized(portId)) {
                // we have a connection, but it's penalized. We want to add it back to the queue
                // when we've found one to use.
                addBack.add(connection);
                continue;
            }
            // if we can't get an existing Connection, create one
            if (connection == null) {
                logger.debug("{} No Connection available for Port {}; creating new Connection", this, portId);
                protocol = new SocketClientProtocol();
                protocol.setDestination(new IdEnrichedRemoteDestination(remoteDestination, portId));
                protocol.setEventReporter(eventReporter);
                final long penalizationMillis = remoteDestination.getYieldPeriod(TimeUnit.MILLISECONDS);
                try {
                    logger.debug("{} Establishing site-to-site connection with {}", this, peerStatus);
                    commsSession = establishSiteToSiteConnection(peerStatus);
                } catch (final IOException ioe) {
                    peerSelector.penalize(peerStatus.getPeerDescription(), penalizationMillis);
                    throw ioe;
                }
                final DataInputStream dis = new DataInputStream(commsSession.getInput().getInputStream());
                final DataOutputStream dos = new DataOutputStream(commsSession.getOutput().getOutputStream());
                try {
                    logger.debug("{} Negotiating protocol", this);
                    RemoteResourceInitiator.initiateResourceNegotiation(protocol, dis, dos);
                } catch (final HandshakeException e) {
                    try {
                        commsSession.close();
                    } catch (final IOException ioe) {
                        throw e;
                    }
                }
                final String peerUrl = "nifi://" + peerDescription.getHostname() + ":" + peerDescription.getPort();
                peer = new Peer(peerDescription, commsSession, peerUrl, clusterUrl.toString());
                // set properties based on config
                if (config != null) {
                    protocol.setTimeout((int) config.getTimeout(TimeUnit.MILLISECONDS));
                    protocol.setPreferredBatchCount(config.getPreferredBatchCount());
                    protocol.setPreferredBatchSize(config.getPreferredBatchSize());
                    protocol.setPreferredBatchDuration(config.getPreferredBatchDuration(TimeUnit.MILLISECONDS));
                }
                // perform handshake
                try {
                    logger.debug("{} performing handshake", this);
                    protocol.handshake(peer);
                    // handle error cases
                    if (protocol.isDestinationFull()) {
                        logger.warn("{} {} indicates that port {}'s destination is full; penalizing peer", this, peer, config.getPortName() == null ? config.getPortIdentifier() : config.getPortName());
                        peerSelector.penalize(peer, penalizationMillis);
                        try {
                            peer.close();
                        } catch (final IOException ioe) {
                        }
                        continue;
                    } else if (protocol.isPortInvalid()) {
                        peerSelector.penalize(peer, penalizationMillis);
                        cleanup(protocol, peer);
                        throw new PortNotRunningException(peer.toString() + " indicates that port " + portId + " is not running");
                    } else if (protocol.isPortUnknown()) {
                        peerSelector.penalize(peer, penalizationMillis);
                        cleanup(protocol, peer);
                        throw new UnknownPortException(peer.toString() + " indicates that port " + portId + " is not known");
                    }
                    // negotiate the FlowFileCodec to use
                    logger.debug("{} negotiating codec", this);
                    codec = protocol.negotiateCodec(peer);
                    logger.debug("{} negotiated codec is {}", this, codec);
                } catch (final PortNotRunningException | UnknownPortException e) {
                    throw e;
                } catch (final Exception e) {
                    peerSelector.penalize(peer, penalizationMillis);
                    cleanup(protocol, peer);
                    final String message = String.format("%s failed to communicate with %s due to %s", this, peer == null ? clusterUrl : peer, e.toString());
                    error(logger, eventReporter, message);
                    if (logger.isDebugEnabled()) {
                        logger.error("", e);
                    }
                    throw e;
                }
                connection = new EndpointConnection(peer, protocol, codec);
            } else {
                final long lastTimeUsed = connection.getLastTimeUsed();
                final long millisSinceLastUse = System.currentTimeMillis() - lastTimeUsed;
                if (commsTimeout > 0L && millisSinceLastUse >= commsTimeout) {
                    cleanup(connection.getSocketClientProtocol(), connection.getPeer());
                    connection = null;
                } else {
                    codec = connection.getCodec();
                    peer = connection.getPeer();
                    commsSession = peer.getCommunicationsSession();
                    protocol = connection.getSocketClientProtocol();
                }
            }
        } catch (final Throwable t) {
            if (commsSession != null) {
                try {
                    commsSession.close();
                } catch (final IOException ioe) {
                }
            }
            throw t;
        } finally {
            if (!addBack.isEmpty()) {
                connectionQueue.addAll(addBack);
                addBack.clear();
            }
        }
    } while (connection == null || codec == null || commsSession == null || protocol == null);
    activeConnections.add(connection);
    return connection;
}
Also used : DataOutputStream(java.io.DataOutputStream) ArrayList(java.util.ArrayList) UnknownPortException(org.apache.nifi.remote.exception.UnknownPortException) CommunicationsSession(org.apache.nifi.remote.protocol.CommunicationsSession) SocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.SocketChannelCommunicationsSession) SSLSocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannelCommunicationsSession) URI(java.net.URI) FlowFileCodec(org.apache.nifi.remote.codec.FlowFileCodec) PeerStatus(org.apache.nifi.remote.PeerStatus) UnreachableClusterException(org.apache.nifi.remote.exception.UnreachableClusterException) PeerDescription(org.apache.nifi.remote.PeerDescription) Peer(org.apache.nifi.remote.Peer) IOException(java.io.IOException) DataInputStream(java.io.DataInputStream) SocketClientProtocol(org.apache.nifi.remote.protocol.socket.SocketClientProtocol) UnreachableClusterException(org.apache.nifi.remote.exception.UnreachableClusterException) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) TransmissionDisabledException(org.apache.nifi.remote.exception.TransmissionDisabledException) PortNotRunningException(org.apache.nifi.remote.exception.PortNotRunningException) UnknownPortException(org.apache.nifi.remote.exception.UnknownPortException) IOException(java.io.IOException) CertificateException(java.security.cert.CertificateException) PortNotRunningException(org.apache.nifi.remote.exception.PortNotRunningException) HandshakeException(org.apache.nifi.remote.exception.HandshakeException)

Example 14 with CommunicationsSession

use of org.apache.nifi.remote.protocol.CommunicationsSession in project nifi by apache.

the class EndpointConnectionPool method fetchRemotePeerStatuses.

@Override
public Set<PeerStatus> fetchRemotePeerStatuses(final PeerDescription peerDescription) throws IOException {
    final String hostname = peerDescription.getHostname();
    final int port = peerDescription.getPort();
    final URI clusterUrl = siteInfoProvider.getActiveClusterUrl();
    final PeerDescription clusterPeerDescription = new PeerDescription(hostname, port, clusterUrl.toString().startsWith("https://"));
    final CommunicationsSession commsSession = establishSiteToSiteConnection(hostname, port);
    final Peer peer = new Peer(clusterPeerDescription, commsSession, "nifi://" + hostname + ":" + port, clusterUrl.toString());
    final SocketClientProtocol clientProtocol = new SocketClientProtocol();
    final DataInputStream dis = new DataInputStream(commsSession.getInput().getInputStream());
    final DataOutputStream dos = new DataOutputStream(commsSession.getOutput().getOutputStream());
    RemoteResourceInitiator.initiateResourceNegotiation(clientProtocol, dis, dos);
    clientProtocol.setTimeout(commsTimeout);
    if (clientProtocol.getVersionNegotiator().getVersion() < 5) {
        String portId = getPortIdentifier(TransferDirection.RECEIVE);
        if (portId == null) {
            portId = getPortIdentifier(TransferDirection.SEND);
        }
        if (portId == null) {
            peer.close();
            throw new IOException("Failed to determine the identifier of port " + remoteDestination.getName());
        }
        clientProtocol.handshake(peer, portId);
    } else {
        clientProtocol.handshake(peer, null);
    }
    final Set<PeerStatus> peerStatuses = clientProtocol.getPeerStatuses(peer);
    try {
        clientProtocol.shutdown(peer);
    } catch (final IOException e) {
        final String message = String.format("%s Failed to shutdown protocol when updating list of peers due to %s", this, e.toString());
        warn(logger, eventReporter, message);
        if (logger.isDebugEnabled()) {
            logger.warn("", e);
        }
    }
    try {
        peer.close();
    } catch (final IOException e) {
        final String message = String.format("%s Failed to close resources when updating list of peers due to %s", this, e.toString());
        warn(logger, eventReporter, message);
        if (logger.isDebugEnabled()) {
            logger.warn("", e);
        }
    }
    return peerStatuses;
}
Also used : PeerDescription(org.apache.nifi.remote.PeerDescription) DataOutputStream(java.io.DataOutputStream) PeerStatus(org.apache.nifi.remote.PeerStatus) Peer(org.apache.nifi.remote.Peer) CommunicationsSession(org.apache.nifi.remote.protocol.CommunicationsSession) SocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.SocketChannelCommunicationsSession) SSLSocketChannelCommunicationsSession(org.apache.nifi.remote.io.socket.ssl.SSLSocketChannelCommunicationsSession) IOException(java.io.IOException) DataInputStream(java.io.DataInputStream) URI(java.net.URI) SocketClientProtocol(org.apache.nifi.remote.protocol.socket.SocketClientProtocol)

Example 15 with CommunicationsSession

use of org.apache.nifi.remote.protocol.CommunicationsSession in project nifi by apache.

the class SocketClientProtocol method handshake.

public void handshake(final Peer peer, final String destinationId) throws IOException, HandshakeException {
    if (handshakeComplete) {
        throw new IllegalStateException("Handshake has already been completed");
    }
    commsIdentifier = UUID.randomUUID().toString();
    logger.debug("{} handshaking with {}", this, peer);
    final Map<HandshakeProperty, String> properties = new HashMap<>();
    properties.put(HandshakeProperty.GZIP, String.valueOf(useCompression));
    if (destinationId != null) {
        properties.put(HandshakeProperty.PORT_IDENTIFIER, destinationId);
    }
    properties.put(HandshakeProperty.REQUEST_EXPIRATION_MILLIS, String.valueOf(timeoutMillis));
    if (versionNegotiator.getVersion() >= 5) {
        if (batchCount > 0) {
            properties.put(HandshakeProperty.BATCH_COUNT, String.valueOf(batchCount));
        }
        if (batchSize > 0L) {
            properties.put(HandshakeProperty.BATCH_SIZE, String.valueOf(batchSize));
        }
        if (batchMillis > 0L) {
            properties.put(HandshakeProperty.BATCH_DURATION, String.valueOf(batchMillis));
        }
    }
    final CommunicationsSession commsSession = peer.getCommunicationsSession();
    commsSession.setTimeout(timeoutMillis);
    final DataInputStream dis = new DataInputStream(commsSession.getInput().getInputStream());
    final DataOutputStream dos = new DataOutputStream(commsSession.getOutput().getOutputStream());
    dos.writeUTF(commsIdentifier);
    if (versionNegotiator.getVersion() >= 3) {
        dos.writeUTF(peer.getUrl());
        transitUriPrefix = peer.getUrl();
        if (!transitUriPrefix.endsWith("/")) {
            transitUriPrefix = transitUriPrefix + "/";
        }
    }
    logger.debug("Handshaking with properties {}", properties);
    dos.writeInt(properties.size());
    for (final Map.Entry<HandshakeProperty, String> entry : properties.entrySet()) {
        dos.writeUTF(entry.getKey().name());
        dos.writeUTF(entry.getValue());
    }
    dos.flush();
    try {
        handshakeResponse = Response.read(dis);
    } catch (final ProtocolException e) {
        throw new HandshakeException(e);
    }
    switch(handshakeResponse.getCode()) {
        case PORT_NOT_IN_VALID_STATE:
        case UNKNOWN_PORT:
        case PORTS_DESTINATION_FULL:
            break;
        case PROPERTIES_OK:
            readyForFileTransfer = true;
            break;
        default:
            logger.error("{} received unexpected response {} from {} when negotiating Codec", new Object[] { this, handshakeResponse, peer });
            peer.close();
            throw new HandshakeException("Received unexpected response " + handshakeResponse);
    }
    logger.debug("{} Finished handshake with {}", this, peer);
    handshakeComplete = true;
}
Also used : ProtocolException(org.apache.nifi.remote.exception.ProtocolException) HandshakeProperty(org.apache.nifi.remote.protocol.HandshakeProperty) HashMap(java.util.HashMap) DataOutputStream(java.io.DataOutputStream) CommunicationsSession(org.apache.nifi.remote.protocol.CommunicationsSession) DataInputStream(java.io.DataInputStream) HashMap(java.util.HashMap) Map(java.util.Map) HandshakeException(org.apache.nifi.remote.exception.HandshakeException)

Aggregations

CommunicationsSession (org.apache.nifi.remote.protocol.CommunicationsSession)19 DataOutputStream (java.io.DataOutputStream)10 IOException (java.io.IOException)9 DataInputStream (java.io.DataInputStream)8 HandshakeException (org.apache.nifi.remote.exception.HandshakeException)8 ProtocolException (org.apache.nifi.remote.exception.ProtocolException)8 SocketChannelCommunicationsSession (org.apache.nifi.remote.io.socket.SocketChannelCommunicationsSession)6 SocketChannel (java.nio.channels.SocketChannel)4 PeerStatus (org.apache.nifi.remote.PeerStatus)4 SSLSocketChannelCommunicationsSession (org.apache.nifi.remote.io.socket.ssl.SSLSocketChannelCommunicationsSession)4 SocketTimeoutException (java.net.SocketTimeoutException)3 URI (java.net.URI)3 CertificateException (java.security.cert.CertificateException)3 HashMap (java.util.HashMap)3 Peer (org.apache.nifi.remote.Peer)3 PeerDescription (org.apache.nifi.remote.PeerDescription)3 FlowFileCodec (org.apache.nifi.remote.codec.FlowFileCodec)3 BadRequestException (org.apache.nifi.remote.exception.BadRequestException)3 NotAuthorizedException (org.apache.nifi.remote.exception.NotAuthorizedException)3 PortNotRunningException (org.apache.nifi.remote.exception.PortNotRunningException)3