Search in sources :

Example 11 with ProtocolException

use of org.apache.nifi.remote.exception.ProtocolException 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)

Example 12 with ProtocolException

use of org.apache.nifi.remote.exception.ProtocolException in project nifi by apache.

the class SocketClientProtocol method negotiateCodec.

@Override
public FlowFileCodec negotiateCodec(final Peer peer) throws IOException, ProtocolException {
    if (!handshakeComplete) {
        throw new IllegalStateException("Handshake has not been performed");
    }
    logger.debug("{} Negotiating Codec with {}", this, peer);
    final CommunicationsSession commsSession = peer.getCommunicationsSession();
    final DataInputStream dis = new DataInputStream(commsSession.getInput().getInputStream());
    final DataOutputStream dos = new DataOutputStream(commsSession.getOutput().getOutputStream());
    RequestType.NEGOTIATE_FLOWFILE_CODEC.writeRequestType(dos);
    FlowFileCodec codec = new StandardFlowFileCodec();
    try {
        codec = (FlowFileCodec) RemoteResourceInitiator.initiateResourceNegotiation(codec, dis, dos);
    } catch (HandshakeException e) {
        throw new ProtocolException(e.toString());
    }
    logger.debug("{} negotiated FlowFileCodec {} with {}", new Object[] { this, codec, commsSession });
    return codec;
}
Also used : ProtocolException(org.apache.nifi.remote.exception.ProtocolException) DataOutputStream(java.io.DataOutputStream) StandardFlowFileCodec(org.apache.nifi.remote.codec.StandardFlowFileCodec) CommunicationsSession(org.apache.nifi.remote.protocol.CommunicationsSession) DataInputStream(java.io.DataInputStream) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) FlowFileCodec(org.apache.nifi.remote.codec.FlowFileCodec) StandardFlowFileCodec(org.apache.nifi.remote.codec.StandardFlowFileCodec)

Example 13 with ProtocolException

use of org.apache.nifi.remote.exception.ProtocolException in project nifi by apache.

the class SiteToSiteRestApiClient method initiateTransaction.

public String initiateTransaction(final TransferDirection direction, final String portId) throws IOException {
    final String portType = TransferDirection.RECEIVE.equals(direction) ? "output-ports" : "input-ports";
    logger.debug("initiateTransaction handshaking portType={}, portId={}", portType, portId);
    final HttpPost post = createPost("/data-transfer/" + portType + "/" + portId + "/transactions");
    post.setHeader("Accept", "application/json");
    post.setHeader(HttpHeaders.PROTOCOL_VERSION, String.valueOf(transportProtocolVersionNegotiator.getVersion()));
    setHandshakeProperties(post);
    final HttpResponse response;
    if (TransferDirection.RECEIVE.equals(direction)) {
        response = initiateTransactionForReceive(post);
    } else {
        response = initiateTransactionForSend(post);
    }
    final int responseCode = response.getStatusLine().getStatusCode();
    logger.debug("initiateTransaction responseCode={}", responseCode);
    String transactionUrl;
    switch(responseCode) {
        case RESPONSE_CODE_CREATED:
            EntityUtils.consume(response.getEntity());
            transactionUrl = readTransactionUrl(response);
            if (isEmpty(transactionUrl)) {
                throw new ProtocolException("Server returned RESPONSE_CODE_CREATED without Location header");
            }
            final Header transportProtocolVersionHeader = response.getFirstHeader(HttpHeaders.PROTOCOL_VERSION);
            if (transportProtocolVersionHeader == null) {
                throw new ProtocolException("Server didn't return confirmed protocol version");
            }
            final Integer protocolVersionConfirmedByServer = Integer.valueOf(transportProtocolVersionHeader.getValue());
            logger.debug("Finished version negotiation, protocolVersionConfirmedByServer={}", protocolVersionConfirmedByServer);
            transportProtocolVersionNegotiator.setVersion(protocolVersionConfirmedByServer);
            final Header serverTransactionTtlHeader = response.getFirstHeader(HttpHeaders.SERVER_SIDE_TRANSACTION_TTL);
            if (serverTransactionTtlHeader == null) {
                throw new ProtocolException("Server didn't return " + HttpHeaders.SERVER_SIDE_TRANSACTION_TTL);
            }
            serverTransactionTtl = Integer.parseInt(serverTransactionTtlHeader.getValue());
            break;
        default:
            try (InputStream content = response.getEntity().getContent()) {
                throw handleErrResponse(responseCode, content);
            }
    }
    logger.debug("initiateTransaction handshaking finished, transactionUrl={}", transactionUrl);
    return transactionUrl;
}
Also used : HttpPost(org.apache.http.client.methods.HttpPost) ProtocolException(org.apache.nifi.remote.exception.ProtocolException) Header(org.apache.http.Header) PipedInputStream(java.io.PipedInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) HttpResponse(org.apache.http.HttpResponse) CloseableHttpResponse(org.apache.http.client.methods.CloseableHttpResponse)

Example 14 with ProtocolException

use of org.apache.nifi.remote.exception.ProtocolException in project nifi by apache.

the class AbstractTransaction method receive.

@Override
public final DataPacket receive() throws IOException {
    try {
        try {
            if (state != TransactionState.DATA_EXCHANGED && state != TransactionState.TRANSACTION_STARTED) {
                throw new IllegalStateException("Cannot receive data from " + peer + " because Transaction State is " + state);
            }
            if (direction == TransferDirection.SEND) {
                throw new IllegalStateException("Attempting to receive data from " + peer + " but started a SEND Transaction");
            }
            // if we already know there's no data, just return null
            if (!dataAvailable) {
                return null;
            }
            // if we have already received a packet, check if another is available.
            if (transfers > 0) {
                // Determine if Peer will send us data or has no data to send us
                final Response dataAvailableCode = readTransactionResponse();
                switch(dataAvailableCode.getCode()) {
                    case CONTINUE_TRANSACTION:
                        logger.debug("{} {} Indicates Transaction should continue", this, peer);
                        this.dataAvailable = true;
                        break;
                    case FINISH_TRANSACTION:
                        logger.debug("{} {} Indicates Transaction should finish", this, peer);
                        this.dataAvailable = false;
                        break;
                    default:
                        throw new ProtocolException("Got unexpected response from " + peer + " when asking for data: " + dataAvailableCode);
                }
            }
            // if no data available, return null
            if (!dataAvailable) {
                return null;
            }
            logger.debug("{} Receiving data from {}", this, peer);
            final InputStream is = peer.getCommunicationsSession().getInput().getInputStream();
            final InputStream dataIn = compress ? new CompressionInputStream(is) : is;
            final DataPacket packet = codec.decode(new CheckedInputStream(dataIn, crc));
            if (packet == null) {
                this.dataAvailable = false;
            } else {
                transfers++;
                contentBytes += packet.getSize();
            }
            this.state = TransactionState.DATA_EXCHANGED;
            return packet;
        } catch (final IOException ioe) {
            throw new IOException("Failed to receive data from " + peer + " due to " + ioe, ioe);
        }
    } catch (final Exception e) {
        error();
        throw e;
    }
}
Also used : Response(org.apache.nifi.remote.protocol.Response) ProtocolException(org.apache.nifi.remote.exception.ProtocolException) CompressionInputStream(org.apache.nifi.remote.io.CompressionInputStream) CheckedInputStream(java.util.zip.CheckedInputStream) CompressionInputStream(org.apache.nifi.remote.io.CompressionInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) StandardDataPacket(org.apache.nifi.remote.util.StandardDataPacket) DataPacket(org.apache.nifi.remote.protocol.DataPacket) CheckedInputStream(java.util.zip.CheckedInputStream) IOException(java.io.IOException) ProtocolException(org.apache.nifi.remote.exception.ProtocolException)

Example 15 with ProtocolException

use of org.apache.nifi.remote.exception.ProtocolException in project nifi by apache.

the class AbstractTransaction method confirm.

@Override
public final void confirm() throws IOException {
    try {
        try {
            if (state == TransactionState.TRANSACTION_STARTED && !dataAvailable && direction == TransferDirection.RECEIVE) {
                // client requested to receive data but no data available. no need to confirm.
                state = TransactionState.TRANSACTION_CONFIRMED;
                return;
            }
            if (state != TransactionState.DATA_EXCHANGED) {
                throw new IllegalStateException("Cannot confirm Transaction because state is " + state + "; Transaction can only be confirmed when state is " + TransactionState.DATA_EXCHANGED);
            }
            final CommunicationsSession commsSession = peer.getCommunicationsSession();
            if (direction == TransferDirection.RECEIVE) {
                if (dataAvailable) {
                    throw new IllegalStateException("Cannot complete transaction because the sender has already sent more data than client has consumed.");
                }
                // we received a FINISH_TRANSACTION indicator. Send back a CONFIRM_TRANSACTION message
                // to peer so that we can verify that the connection is still open. This is a two-phase commit,
                // which helps to prevent the chances of data duplication. Without doing this, we may commit the
                // session and then when we send the response back to the peer, the peer may have timed out and may not
                // be listening. As a result, it will re-send the data. By doing this two-phase commit, we narrow the
                // Critical Section involved in this transaction so that rather than the Critical Section being the
                // time window involved in the entire transaction, it is reduced to a simple round-trip conversation.
                logger.trace("{} Sending CONFIRM_TRANSACTION Response Code to {}", this, peer);
                final String calculatedCRC = String.valueOf(crc.getValue());
                writeTransactionResponse(ResponseCode.CONFIRM_TRANSACTION, calculatedCRC);
                final Response confirmTransactionResponse;
                try {
                    confirmTransactionResponse = readTransactionResponse();
                } catch (final IOException ioe) {
                    logger.error("Failed to receive response code from {} when expecting confirmation of transaction", peer);
                    if (eventReporter != null) {
                        eventReporter.reportEvent(Severity.ERROR, "Site-to-Site", "Failed to receive response code from " + peer + " when expecting confirmation of transaction");
                    }
                    throw ioe;
                }
                logger.trace("{} Received {} from {}", this, confirmTransactionResponse, peer);
                switch(confirmTransactionResponse.getCode()) {
                    case CONFIRM_TRANSACTION:
                        break;
                    case BAD_CHECKSUM:
                        throw new IOException(this + " Received a BadChecksum response from peer " + peer);
                    default:
                        throw new ProtocolException(this + " Received unexpected Response from peer " + peer + " : " + confirmTransactionResponse + "; expected 'Confirm Transaction' Response Code");
                }
                state = TransactionState.TRANSACTION_CONFIRMED;
            } else {
                logger.debug("{} Sent FINISH_TRANSACTION indicator to {}", this, peer);
                writeTransactionResponse(ResponseCode.FINISH_TRANSACTION);
                final String calculatedCRC = String.valueOf(crc.getValue());
                // we've sent a FINISH_TRANSACTION. Now we'll wait for the peer to send a 'Confirm Transaction' response
                final Response transactionConfirmationResponse = readTransactionResponse();
                if (transactionConfirmationResponse.getCode() == ResponseCode.CONFIRM_TRANSACTION) {
                    // Confirm checksum and echo back the confirmation.
                    logger.trace("{} Received {} from {}", this, transactionConfirmationResponse, peer);
                    final String receivedCRC = transactionConfirmationResponse.getMessage();
                    // CRC was not used before version 4
                    if (protocolVersion > 3) {
                        if (!receivedCRC.equals(calculatedCRC)) {
                            writeTransactionResponse(ResponseCode.BAD_CHECKSUM);
                            throw new IOException(this + " Sent data to peer " + peer + " but calculated CRC32 Checksum as " + calculatedCRC + " while peer calculated CRC32 Checksum as " + receivedCRC + "; canceling transaction and rolling back session");
                        }
                    }
                    writeTransactionResponse(ResponseCode.CONFIRM_TRANSACTION, "");
                } else {
                    throw new ProtocolException("Expected to receive 'Confirm Transaction' response from peer " + peer + " but received " + transactionConfirmationResponse);
                }
                state = TransactionState.TRANSACTION_CONFIRMED;
            }
        } catch (final IOException ioe) {
            throw new IOException("Failed to confirm transaction with " + peer + " due to " + ioe, ioe);
        }
    } catch (final Exception e) {
        error();
        throw e;
    }
}
Also used : Response(org.apache.nifi.remote.protocol.Response) ProtocolException(org.apache.nifi.remote.exception.ProtocolException) CommunicationsSession(org.apache.nifi.remote.protocol.CommunicationsSession) IOException(java.io.IOException) IOException(java.io.IOException) ProtocolException(org.apache.nifi.remote.exception.ProtocolException)

Aggregations

ProtocolException (org.apache.nifi.remote.exception.ProtocolException)16 IOException (java.io.IOException)10 DataInputStream (java.io.DataInputStream)5 CommunicationsSession (org.apache.nifi.remote.protocol.CommunicationsSession)5 InputStream (java.io.InputStream)4 FlowFile (org.apache.nifi.flowfile.FlowFile)4 HandshakeException (org.apache.nifi.remote.exception.HandshakeException)4 Response (org.apache.nifi.remote.protocol.Response)4 StandardDataPacket (org.apache.nifi.remote.util.StandardDataPacket)4 StopWatch (org.apache.nifi.util.StopWatch)4 DataOutputStream (java.io.DataOutputStream)3 HashMap (java.util.HashMap)3 ByteArrayInputStream (java.io.ByteArrayInputStream)2 SocketTimeoutException (java.net.SocketTimeoutException)2 HashSet (java.util.HashSet)2 CheckedInputStream (java.util.zip.CheckedInputStream)2 ProcessSession (org.apache.nifi.processor.ProcessSession)2 ProcessException (org.apache.nifi.processor.exception.ProcessException)2 BadRequestException (org.apache.nifi.remote.exception.BadRequestException)2 NotAuthorizedException (org.apache.nifi.remote.exception.NotAuthorizedException)2