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;
}
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);
}
}
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");
}
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);
}
}
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);
}
}
Aggregations