Search in sources :

Example 1 with TransportException

use of com.microsoft.azure.sdk.iot.device.exceptions.TransportException in project azure-iot-sdk-java by Azure.

the class AmqpsIotHubConnection method closeConnectionWithException.

// "isRetryable" is currently always "true", but can be "false" if required.
@SuppressWarnings("SameParameterValue")
private void closeConnectionWithException(String errorMessage, boolean isRetryable) throws TransportException {
    TransportException transportException = new TransportException(errorMessage);
    transportException.setRetryable(isRetryable);
    log.error(errorMessage, transportException);
    this.close();
    throw transportException;
}
Also used : TransportException(com.microsoft.azure.sdk.iot.device.exceptions.TransportException)

Example 2 with TransportException

use of com.microsoft.azure.sdk.iot.device.exceptions.TransportException in project azure-iot-sdk-java by Azure.

the class AmqpsIotHubConnection method sendQueuedMessages.

private void sendQueuedMessages() {
    int messagesAttemptedToBeProcessed = 0;
    Message message = messagesToSend.poll();
    while (message != null && messagesAttemptedToBeProcessed < MAX_MESSAGES_TO_SEND_PER_CALLBACK) {
        messagesAttemptedToBeProcessed++;
        SendResult sendResult = sendQueuedMessage(message);
        // was unregistered by the user and the message should report that it failed to send before the device session was unregistered.
        if (sendResult == SendResult.WRONG_DEVICE) {
            AmqpsSessionHandler reconnectingDeviceSessionHandler = this.reconnectingDeviceSessionHandlers.get(message.getConnectionDeviceId());
            if (reconnectingDeviceSessionHandler != null) {
                log.trace("Amqp message failed to send because its AMQP session is currently reconnecting. Adding it back to messages to send queue ({})", message);
                messagesToSend.add(message);
            } else {
                TransportException transportException = new TransportException("Message failed to send because it belonged to a device that was unregistered from the AMQP connetion");
                transportException.setRetryable(false);
                this.listener.onMessageSent(message, message.getConnectionDeviceId(), transportException);
            }
        } else if (sendResult == SendResult.DUPLICATE_SUBSCRIPTION_MESSAGE) {
            // No need to send a twin/method subscription message if you are already subscribed or if the subscription is in progress
            log.trace("Attempted to send subscription message while the subscription was already in progress. Discarding the message ({})", message);
        } else if (sendResult == SendResult.SUBSCRIPTION_IN_PROGRESS) {
            // Proton-j doesn't handle the scenario of sending twin/method messages on links that haven't been opened remotely yet, so hold
            // off on sending them until the subscription has finished.
            log.trace("Attempted to send twin/method message while the twin/method subscription was in progress. Adding it back to messages to send queue to try again after the subscription has finished ({})", message);
            messagesToSend.add(message);
        } else if (sendResult == SendResult.LINKS_NOT_OPEN) {
            // Shouldn't happen. If it does, it signals that we have a bug in this SDK.
            log.warn("Failed to send a message because its AMQP links were not open yet. Adding it back to messages to send queue ({})", message);
            messagesToSend.add(message);
        } else if (sendResult == SendResult.UNKNOWN_FAILURE) {
            // Shouldn't happen. If it does, it signals that we have a bug in this SDK.
            log.warn("Unknown failure occurred while attempting to send. Adding it back to messages to send queue ({})", message);
            messagesToSend.add(message);
        }
        message = messagesToSend.poll();
    }
    if (message != null) {
        // message was polled out of list, but loop exited from processing too many messages before it could process this message, so re-queue it for later
        messagesToSend.add(message);
    }
}
Also used : TransportException(com.microsoft.azure.sdk.iot.device.exceptions.TransportException)

Example 3 with TransportException

use of com.microsoft.azure.sdk.iot.device.exceptions.TransportException in project azure-iot-sdk-java by Azure.

the class AmqpsIotHubConnection method open.

public void open() throws TransportException {
    log.debug("Opening amqp layer...");
    reconnectionScheduled = false;
    connectionId = UUID.randomUUID().toString();
    this.savedException = null;
    if (this.state == IotHubConnectionStatus.DISCONNECTED) {
        for (DeviceClientConfig clientConfig : deviceClientConfigs) {
            this.addSessionHandler(clientConfig);
        }
        initializeStateLatches();
        try {
            this.openAsync();
            if (this.authenticationType == DeviceClientConfig.AuthType.SAS_TOKEN) {
                // x509 authenticated connections don't open authentication links since the SSL handshake does all the authentication
                log.trace("Waiting for authentication links to open...");
            }
            Iterator<DeviceClientConfig> configsIterator = this.deviceClientConfigs.iterator();
            DeviceClientConfig defaultConfig = configsIterator.hasNext() ? configsIterator.next() : null;
            int timeoutSeconds = DeviceClientConfig.DEFAULT_AMQP_OPEN_AUTHENTICATION_SESSION_TIMEOUT_IN_SECONDS;
            if (defaultConfig != null) {
                timeoutSeconds = defaultConfig.getAmqpOpenAuthenticationSessionTimeout();
            }
            boolean authenticationSessionOpenTimedOut = !this.authenticationSessionOpenedLatch.await(timeoutSeconds, TimeUnit.SECONDS);
            if (this.savedException != null) {
                throw this.savedException;
            }
            if (authenticationSessionOpenTimedOut) {
                closeConnectionWithException("Timed out waiting for authentication session to open", true);
            }
            log.trace("Waiting for device sessions to open...");
            boolean deviceSessionsOpenTimedOut = false;
            for (DeviceClientConfig config : this.deviceClientConfigs) {
                // Each device has its own worker session timeout according to its config settings
                deviceSessionsOpenTimedOut = !this.deviceSessionsOpenedLatches.get(config.getDeviceId()).await(config.getAmqpOpenDeviceSessionsTimeout(), TimeUnit.SECONDS);
                if (deviceSessionsOpenTimedOut) {
                    // If any device session times out while opening, don't wait for the others
                    break;
                }
            }
            if (this.savedException != null) {
                throw this.savedException;
            }
            if (deviceSessionsOpenTimedOut) {
                closeConnectionWithException("Timed out waiting for worker links to open", true);
            }
        } catch (TransportException e) {
            // since some session handlers were created and saved locally, they must be deleted so that the next open
            // call doesn't add new session handlers on top of a list of the same session handlers from the last attempt.
            clearLocalState();
            // clean up network resources and thread scheduler before exiting this layer. Subsequent open attempts
            // will create a new reactor and a new executor service
            closeNetworkResources();
            throw e;
        } catch (InterruptedException e) {
            // since some session handlers were created and saved locally, they must be deleted so that the next open
            // call doesn't add new session handlers on top of a list of the same session handlers from the last attempt.
            clearLocalState();
            // clean up network resources and thread scheduler before exiting this layer. Subsequent open attempts
            // will create a new reactor and a new executor service
            closeNetworkResources();
            TransportException interruptedTransportException = new TransportException("Interrupted while waiting for links to open for AMQP connection", e);
            interruptedTransportException.setRetryable(true);
            throw interruptedTransportException;
        }
    }
    this.state = IotHubConnectionStatus.CONNECTED;
    this.listener.onConnectionEstablished(this.connectionId);
    log.debug("Amqp connection opened successfully");
}
Also used : TransportException(com.microsoft.azure.sdk.iot.device.exceptions.TransportException)

Example 4 with TransportException

use of com.microsoft.azure.sdk.iot.device.exceptions.TransportException in project azure-iot-sdk-java by Azure.

the class AmqpsIotHubConnection method onConnectionBound.

@Override
public void onConnectionBound(Event event) {
    Transport transport = event.getTransport();
    // Convert from seconds to milliseconds since this proton-j API only accepts keep alive in milliseconds
    transport.setIdleTimeout(keepAliveInterval * 1000);
    if (this.isWebsocketConnection) {
        addWebSocketLayer(transport);
    }
    try {
        Iterator<DeviceClientConfig> configsIterator = this.deviceClientConfigs.iterator();
        DeviceClientConfig defaultConfig = configsIterator.hasNext() ? configsIterator.next() : null;
        SSLContext sslContext;
        if (defaultConfig != null) {
            sslContext = defaultConfig.getAuthenticationProvider().getSSLContext();
        } else if (this.sslContext != null) {
            // This should only be hit when a user creates a multiplexing client and specifies an SSLContext
            // that they want to use
            sslContext = this.sslContext;
        } else {
            // This should only be hit when a user creates a multiplexing client and doesn't specify an SSLContext
            // that they want to use
            sslContext = new IotHubSSLContext().getSSLContext();
        }
        if (this.authenticationType == DeviceClientConfig.AuthType.SAS_TOKEN) {
            Sasl sasl = transport.sasl();
            sasl.setMechanisms("ANONYMOUS");
        }
        SslDomain domain = Proton.sslDomain();
        domain.setSslContext(sslContext);
        domain.setPeerAuthentication(SslDomain.VerifyMode.VERIFY_PEER);
        domain.init(SslDomain.Mode.CLIENT);
        transport.ssl(domain);
    } catch (IOException | CertificateException | NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
        this.savedException = new TransportException(e);
        log.error("Encountered an exception while setting ssl domain for the amqp connection", this.savedException);
    }
    // Adding proxy layer needs to be done after sending SSL message
    if (proxySettings != null) {
        addProxyLayer(transport, event.getConnection().getHostname() + ":" + WEB_SOCKET_PORT);
    }
}
Also used : CertificateException(java.security.cert.CertificateException) SSLContext(javax.net.ssl.SSLContext) IotHubSSLContext(com.microsoft.azure.sdk.iot.deps.auth.IotHubSSLContext) IOException(java.io.IOException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) KeyStoreException(java.security.KeyStoreException) TransportException(com.microsoft.azure.sdk.iot.device.exceptions.TransportException) KeyManagementException(java.security.KeyManagementException) IotHubSSLContext(com.microsoft.azure.sdk.iot.deps.auth.IotHubSSLContext)

Example 5 with TransportException

use of com.microsoft.azure.sdk.iot.device.exceptions.TransportException in project azure-iot-sdk-java by Azure.

the class HttpsTransportManager method send.

/**
 * This is a blocking send message. It send the provide message, wait for the IotHub answer, and return is
 * in the ResponseMessage, which contains the status and the payload.
 *
 * @param message is the message to send.
 * @return the IotHub response with the status and payload.
 * @throws IOException if the IotHub communication failed.
 * @throws IllegalArgumentException if the provided message is null, or invalid.
 */
public ResponseMessage send(IotHubTransportMessage message, Map<String, String> additionalHeaders) throws IOException, IllegalArgumentException {
    HttpsMessage httpsMessage = HttpsSingleMessage.parseHttpsJsonMessage(message);
    if ((message.getIotHubMethod() == null) || (message.getUriPath() == null)) {
        throw new IllegalArgumentException("method or path is null");
    }
    HttpsMethod httpsMethod;
    switch(message.getIotHubMethod()) {
        case GET:
            httpsMethod = HttpsMethod.GET;
            break;
        case POST:
            httpsMethod = HttpsMethod.POST;
            break;
        default:
            throw new IllegalArgumentException("Unknown IoT Hub type " + message.getIotHubMethod().toString());
    }
    String httpsPath = message.getUriPath();
    try {
        return this.httpsIotHubConnection.sendHttpsMessage(httpsMessage, httpsMethod, httpsPath, additionalHeaders);
    } catch (TransportException e) {
        // Wrapping this as IOException to avoid breaking changes.
        throw new IOException(e);
    }
}
Also used : IOException(java.io.IOException) TransportException(com.microsoft.azure.sdk.iot.device.exceptions.TransportException)

Aggregations

TransportException (com.microsoft.azure.sdk.iot.device.exceptions.TransportException)46 Test (org.junit.Test)18 IOException (java.io.IOException)14 ProtocolException (com.microsoft.azure.sdk.iot.device.exceptions.ProtocolException)8 MqttException (org.eclipse.paho.client.mqttv3.MqttException)7 CountDownLatch (java.util.concurrent.CountDownLatch)4 Expectations (mockit.Expectations)4 NonStrictExpectations (mockit.NonStrictExpectations)4 Message (com.microsoft.azure.sdk.iot.device.Message)3 HttpsConnection (com.microsoft.azure.sdk.iot.device.transport.https.HttpsConnection)3 HttpsMethod (com.microsoft.azure.sdk.iot.device.transport.https.HttpsMethod)3 MqttMessaging (com.microsoft.azure.sdk.iot.device.transport.mqtt.MqttMessaging)3 Pair (org.apache.commons.lang3.tuple.Pair)3 IotHubConnectionString (com.microsoft.azure.sdk.iot.device.IotHubConnectionString)2 ModuleClientException (com.microsoft.azure.sdk.iot.device.exceptions.ModuleClientException)2 URISyntaxException (java.net.URISyntaxException)2 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)2 IotHubSSLContext (com.microsoft.azure.sdk.iot.deps.auth.IotHubSSLContext)1 IotHubAuthenticationProvider (com.microsoft.azure.sdk.iot.device.auth.IotHubAuthenticationProvider)1 SignatureProvider (com.microsoft.azure.sdk.iot.device.auth.SignatureProvider)1