Microsoft Azure IoTHub client AMQP transport

Dependents:   sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp iothub_client_sample_amqp ... more

This library implements the AMQP transport for Microsoft Azure IoTHub client. The code is replicated from https://github.com/Azure/azure-iot-sdks

Committer:
Azure.IoT Build
Date:
Thu Feb 04 11:39:49 2016 -0800
Revision:
7:07bc440836b3
Parent:
5:8d58d20699dd
Child:
8:450043aa3c5c
1.0.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AzureIoTClient 4:57e049bce51e 1 // Copyright (c) Microsoft. All rights reserved.
AzureIoTClient 4:57e049bce51e 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
AzureIoTClient 4:57e049bce51e 3
AzureIoTClient 4:57e049bce51e 4 #include <stdlib.h>
AzureIoTClient 4:57e049bce51e 5 #ifdef _CRTDBG_MAP_ALLOC
AzureIoTClient 4:57e049bce51e 6 #include <crtdbg.h>
AzureIoTClient 4:57e049bce51e 7 #endif
AzureIoTClient 4:57e049bce51e 8 #include "gballoc.h"
AzureIoTClient 4:57e049bce51e 9
Azure.IoT Build 7:07bc440836b3 10 #include "cbs.h"
Azure.IoT Build 7:07bc440836b3 11 #include "link.h"
Azure.IoT Build 7:07bc440836b3 12 #include "message.h"
Azure.IoT Build 7:07bc440836b3 13 #include "message_receiver.h"
Azure.IoT Build 7:07bc440836b3 14 #include "message_sender.h"
Azure.IoT Build 7:07bc440836b3 15 #include "messaging.h"
Azure.IoT Build 7:07bc440836b3 16 #include "sasl_mssbcbs.h"
Azure.IoT Build 7:07bc440836b3 17 #include "saslclientio.h"
AzureIoTClient 4:57e049bce51e 18
Azure.IoT Build 7:07bc440836b3 19 #include "crt_abstractions.h"
Azure.IoT Build 7:07bc440836b3 20 #include "doublylinkedlist.h"
AzureIoTClient 4:57e049bce51e 21 #include "iot_logging.h"
Azure.IoT Build 7:07bc440836b3 22 #include "platform.h"
Azure.IoT Build 7:07bc440836b3 23 #include "sastoken.h"
AzureIoTClient 4:57e049bce51e 24 #include "strings.h"
Azure.IoT Build 7:07bc440836b3 25 #include "tlsio_openssl.h"
Azure.IoT Build 7:07bc440836b3 26 #include "tlsio_schannel.h"
Azure.IoT Build 7:07bc440836b3 27 #include "tlsio_wolfssl.h"
AzureIoTClient 4:57e049bce51e 28 #include "urlencode.h"
Azure.IoT Build 7:07bc440836b3 29
Azure.IoT Build 7:07bc440836b3 30 #include "tlsio.h"
AzureIoTClient 4:57e049bce51e 31
AzureIoTClient 4:57e049bce51e 32 #include "iothub_client_ll.h"
AzureIoTClient 4:57e049bce51e 33 #include "iothub_client_private.h"
AzureIoTClient 4:57e049bce51e 34 #include "iothubtransportamqp.h"
Azure.IoT Build 7:07bc440836b3 35 #include "iothub_client_version.h"
Azure.IoT Build 7:07bc440836b3 36
Azure.IoT Build 7:07bc440836b3 37 #define RESULT_OK 0
Azure.IoT Build 7:07bc440836b3 38 #define RESULT_FAILURE 1
Azure.IoT Build 7:07bc440836b3 39 #define RESULT_TIMEOUT 2
Azure.IoT Build 7:07bc440836b3 40
Azure.IoT Build 7:07bc440836b3 41 #define TIME_MAX SIZE_MAX
Azure.IoT Build 7:07bc440836b3 42 #define RFC1035_MAX_FQDN_LENGTH 255
Azure.IoT Build 7:07bc440836b3 43 #define DEFAULT_IOTHUB_AMQP_PORT 5671
Azure.IoT Build 7:07bc440836b3 44 #define DEFAULT_SAS_TOKEN_LIFETIME_MS 3600000
Azure.IoT Build 7:07bc440836b3 45 #define DEFAULT_CBS_REQUEST_TIMEOUT_MS 30000
Azure.IoT Build 7:07bc440836b3 46 #define DEFAULT_MESSAGE_SEND_TIMEOUT_MS 300000
Azure.IoT Build 7:07bc440836b3 47 #define CBS_AUDIENCE "servicebus.windows.net:sastoken"
Azure.IoT Build 7:07bc440836b3 48 #define DEFAULT_CONTAINER_ID "default_container_id"
Azure.IoT Build 7:07bc440836b3 49 #define DEFAULT_INCOMING_WINDOW_SIZE SIZE_MAX
Azure.IoT Build 7:07bc440836b3 50 #define DEFAULT_OUTGOING_WINDOW_SIZE 100
Azure.IoT Build 7:07bc440836b3 51 #define MESSAGE_RECEIVER_LINK_NAME "receiver-link"
Azure.IoT Build 7:07bc440836b3 52 #define MESSAGE_RECEIVER_TARGET_ADDRESS "ingress-rx"
Azure.IoT Build 7:07bc440836b3 53 #define MESSAGE_RECEIVER_MAX_LINK_SIZE 65536
Azure.IoT Build 7:07bc440836b3 54 #define MESSAGE_SENDER_LINK_NAME "sender-link"
Azure.IoT Build 7:07bc440836b3 55 #define MESSAGE_SENDER_SOURCE_ADDRESS "ingress"
Azure.IoT Build 7:07bc440836b3 56 #define MESSAGE_SENDER_MAX_LINK_SIZE 65536
Azure.IoT Build 7:07bc440836b3 57
Azure.IoT Build 7:07bc440836b3 58 typedef XIO_HANDLE(*TLS_IO_TRANSPORT_PROVIDER)(const char* fqdn, int port, const char* certificates);
Azure.IoT Build 7:07bc440836b3 59
Azure.IoT Build 7:07bc440836b3 60 typedef enum CBS_STATE_TAG
Azure.IoT Build 7:07bc440836b3 61 {
Azure.IoT Build 7:07bc440836b3 62 CBS_STATE_IDLE,
Azure.IoT Build 7:07bc440836b3 63 CBS_STATE_AUTH_IN_PROGRESS,
Azure.IoT Build 7:07bc440836b3 64 CBS_STATE_AUTHENTICATED
Azure.IoT Build 7:07bc440836b3 65 } CBS_STATE;
AzureIoTClient 4:57e049bce51e 66
Azure.IoT Build 7:07bc440836b3 67 typedef struct AMQP_TRANSPORT_STATE_TAG
Azure.IoT Build 7:07bc440836b3 68 {
Azure.IoT Build 7:07bc440836b3 69 // FQDN of the IoT Hub.
Azure.IoT Build 7:07bc440836b3 70 STRING_HANDLE iotHubHostFqdn;
Azure.IoT Build 7:07bc440836b3 71 // AMQP port of the IoT Hub.
Azure.IoT Build 7:07bc440836b3 72 int iotHubPort;
Azure.IoT Build 7:07bc440836b3 73 // Certificates to be used by the TLS I/O.
Azure.IoT Build 7:07bc440836b3 74 char* trusted_certificates;
Azure.IoT Build 7:07bc440836b3 75 // Key associated to the device to be used.
Azure.IoT Build 7:07bc440836b3 76 STRING_HANDLE deviceKey;
Azure.IoT Build 7:07bc440836b3 77 // Address to which the transport will connect to and send events.
Azure.IoT Build 7:07bc440836b3 78 STRING_HANDLE targetAddress;
Azure.IoT Build 7:07bc440836b3 79 // Address to which the transport will connect to and receive messages from.
Azure.IoT Build 7:07bc440836b3 80 STRING_HANDLE messageReceiveAddress;
Azure.IoT Build 7:07bc440836b3 81 // A component of the SAS token. Currently this must be an empty string.
Azure.IoT Build 7:07bc440836b3 82 STRING_HANDLE sasTokenKeyName;
Azure.IoT Build 7:07bc440836b3 83 // Internal parameter that identifies the current logical device within the service.
Azure.IoT Build 7:07bc440836b3 84 STRING_HANDLE devicesPath;
Azure.IoT Build 7:07bc440836b3 85 // How long a SAS token created by the transport is valid, in milliseconds.
Azure.IoT Build 7:07bc440836b3 86 size_t sas_token_lifetime;
Azure.IoT Build 7:07bc440836b3 87 // Maximum period of time for the transport to wait before refreshing the SAS token it created previously, in milliseconds.
Azure.IoT Build 7:07bc440836b3 88 size_t sas_token_refresh_time;
Azure.IoT Build 7:07bc440836b3 89 // Maximum time the transport waits for uAMQP cbs_put_token() to complete before marking it a failure, in milliseconds.
Azure.IoT Build 7:07bc440836b3 90 size_t cbs_request_timeout;
Azure.IoT Build 7:07bc440836b3 91 // Maximum time the transport waits for an event to be sent before marking it a failure, in milliseconds.
Azure.IoT Build 7:07bc440836b3 92 size_t message_send_timeout;
Azure.IoT Build 7:07bc440836b3 93 // Maximum time for the connection establishment/retry logic should wait for a connection to succeed, in milliseconds.
Azure.IoT Build 7:07bc440836b3 94 size_t connection_timeout;
Azure.IoT Build 7:07bc440836b3 95 // Saved reference to the IoTHub LL Client.
Azure.IoT Build 7:07bc440836b3 96 IOTHUB_CLIENT_LL_HANDLE iothub_client_handle;
Azure.IoT Build 7:07bc440836b3 97
Azure.IoT Build 7:07bc440836b3 98 // TSL I/O transport.
Azure.IoT Build 7:07bc440836b3 99 XIO_HANDLE tls_io;
Azure.IoT Build 7:07bc440836b3 100 // Pointer to the function that creates the TLS I/O (internal use only).
Azure.IoT Build 7:07bc440836b3 101 TLS_IO_TRANSPORT_PROVIDER tls_io_transport_provider;
Azure.IoT Build 7:07bc440836b3 102 // AMQP SASL I/O transport created on top of the TLS I/O layer.
Azure.IoT Build 7:07bc440836b3 103 XIO_HANDLE sasl_io;
Azure.IoT Build 7:07bc440836b3 104 // AMQP SASL I/O mechanism to be used.
Azure.IoT Build 7:07bc440836b3 105 SASL_MECHANISM_HANDLE sasl_mechanism;
Azure.IoT Build 7:07bc440836b3 106 // AMQP connection.
Azure.IoT Build 7:07bc440836b3 107 CONNECTION_HANDLE connection;
Azure.IoT Build 7:07bc440836b3 108 // Current AMQP connection state;
Azure.IoT Build 7:07bc440836b3 109 AMQP_MANAGEMENT_STATE connection_state;
Azure.IoT Build 7:07bc440836b3 110 // Last time the AMQP connection establishment was initiated.
Azure.IoT Build 7:07bc440836b3 111 size_t connection_establish_time;
Azure.IoT Build 7:07bc440836b3 112 // AMQP session.
Azure.IoT Build 7:07bc440836b3 113 SESSION_HANDLE session;
Azure.IoT Build 7:07bc440836b3 114 // AMQP link used by the event sender.
Azure.IoT Build 7:07bc440836b3 115 LINK_HANDLE sender_link;
Azure.IoT Build 7:07bc440836b3 116 // uAMQP event sender.
Azure.IoT Build 7:07bc440836b3 117 MESSAGE_SENDER_HANDLE message_sender;
Azure.IoT Build 7:07bc440836b3 118 // Internal flag that controls if messages should be received or not.
Azure.IoT Build 7:07bc440836b3 119 bool receive_messages;
Azure.IoT Build 7:07bc440836b3 120 // AMQP link used by the message receiver.
Azure.IoT Build 7:07bc440836b3 121 LINK_HANDLE receiver_link;
Azure.IoT Build 7:07bc440836b3 122 // uAMQP message receiver.
Azure.IoT Build 7:07bc440836b3 123 MESSAGE_RECEIVER_HANDLE message_receiver;
Azure.IoT Build 7:07bc440836b3 124 // List with events still pending to be sent. It is provided by the upper layer.
Azure.IoT Build 7:07bc440836b3 125 PDLIST_ENTRY waitingToSend;
Azure.IoT Build 7:07bc440836b3 126 // Internal list with the items currently being processed/sent through uAMQP.
Azure.IoT Build 7:07bc440836b3 127 DLIST_ENTRY inProgress;
Azure.IoT Build 7:07bc440836b3 128 // Connection instance with the Azure IoT CBS.
Azure.IoT Build 7:07bc440836b3 129 CBS_HANDLE cbs;
Azure.IoT Build 7:07bc440836b3 130 // Current state of the CBS connection.
Azure.IoT Build 7:07bc440836b3 131 CBS_STATE cbs_state;
Azure.IoT Build 7:07bc440836b3 132 // Time when the current SAS token was created, in seconds since epoch.
Azure.IoT Build 7:07bc440836b3 133 size_t current_sas_token_create_time;
Azure.IoT Build 7:07bc440836b3 134 } AMQP_TRANSPORT_INSTANCE;
Azure.IoT Build 7:07bc440836b3 135
Azure.IoT Build 7:07bc440836b3 136 // This structure is used to track an event being sent and the time it was sent.
Azure.IoT Build 7:07bc440836b3 137 typedef struct EVENT_TRACKER_TAG
Azure.IoT Build 7:07bc440836b3 138 {
Azure.IoT Build 7:07bc440836b3 139 IOTHUB_CLIENT_LL_HANDLE iothub_client_handle;
Azure.IoT Build 7:07bc440836b3 140 IOTHUB_MESSAGE_LIST* message;
Azure.IoT Build 7:07bc440836b3 141 time_t time_sent;
Azure.IoT Build 7:07bc440836b3 142 DLIST_ENTRY entry;
Azure.IoT Build 7:07bc440836b3 143 } EVENT_TRACKER;
AzureIoTClient 4:57e049bce51e 144
AzureIoTClient 4:57e049bce51e 145
Azure.IoT Build 7:07bc440836b3 146 // Auxiliary functions
AzureIoTClient 4:57e049bce51e 147
Azure.IoT Build 7:07bc440836b3 148 static STRING_HANDLE concat3Params(const char* prefix, const char* infix, const char* suffix)
AzureIoTClient 4:57e049bce51e 149 {
Azure.IoT Build 7:07bc440836b3 150 STRING_HANDLE result = NULL;
Azure.IoT Build 7:07bc440836b3 151 char* concat = NULL;
Azure.IoT Build 7:07bc440836b3 152 size_t totalLength = strlen(prefix) + strlen(infix) + strlen(suffix) + 1; // One extra for \0.
AzureIoTClient 5:8d58d20699dd 153
Azure.IoT Build 7:07bc440836b3 154 if ((concat = (char*)malloc(sizeof(char) * totalLength)) != NULL)
AzureIoTClient 5:8d58d20699dd 155 {
Azure.IoT Build 7:07bc440836b3 156 if (snprintf(concat, totalLength, "%s%s%s", prefix, infix, suffix) > 0)
AzureIoTClient 5:8d58d20699dd 157 {
Azure.IoT Build 7:07bc440836b3 158 result = STRING_construct(concat);
AzureIoTClient 5:8d58d20699dd 159 }
Azure.IoT Build 7:07bc440836b3 160 free(concat);
AzureIoTClient 5:8d58d20699dd 161 }
AzureIoTClient 5:8d58d20699dd 162
AzureIoTClient 4:57e049bce51e 163 return result;
AzureIoTClient 4:57e049bce51e 164 }
AzureIoTClient 4:57e049bce51e 165
Azure.IoT Build 7:07bc440836b3 166 static size_t getSecondsSinceEpoch()
AzureIoTClient 4:57e049bce51e 167 {
Azure.IoT Build 7:07bc440836b3 168 return (size_t)(difftime(get_time(NULL), (time_t)0) + 0);
AzureIoTClient 4:57e049bce51e 169 }
AzureIoTClient 4:57e049bce51e 170
Azure.IoT Build 7:07bc440836b3 171 static EVENT_TRACKER* trackEvent(IOTHUB_MESSAGE_LIST* message, AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 172 {
Azure.IoT Build 7:07bc440836b3 173 EVENT_TRACKER* event_tracker = NULL;
Azure.IoT Build 7:07bc440836b3 174
Azure.IoT Build 7:07bc440836b3 175 if ((event_tracker = (EVENT_TRACKER*)malloc(sizeof(EVENT_TRACKER))) != NULL)
Azure.IoT Build 7:07bc440836b3 176 {
Azure.IoT Build 7:07bc440836b3 177 event_tracker->iothub_client_handle = transport_state->iothub_client_handle;
Azure.IoT Build 7:07bc440836b3 178 event_tracker->message = message;
Azure.IoT Build 7:07bc440836b3 179 event_tracker->time_sent = get_time(NULL);
Azure.IoT Build 7:07bc440836b3 180 DList_InitializeListHead(&event_tracker->entry);
Azure.IoT Build 7:07bc440836b3 181
Azure.IoT Build 7:07bc440836b3 182 DList_RemoveEntryList(&message->entry);
Azure.IoT Build 7:07bc440836b3 183 DList_InsertTailList(&transport_state->inProgress, &event_tracker->entry);
Azure.IoT Build 7:07bc440836b3 184 }
Azure.IoT Build 7:07bc440836b3 185
Azure.IoT Build 7:07bc440836b3 186 return event_tracker;
Azure.IoT Build 7:07bc440836b3 187 }
Azure.IoT Build 7:07bc440836b3 188
Azure.IoT Build 7:07bc440836b3 189 static void destroyEventTracker(EVENT_TRACKER* event_tracker)
Azure.IoT Build 7:07bc440836b3 190 {
Azure.IoT Build 7:07bc440836b3 191 free(event_tracker);
AzureIoTClient 4:57e049bce51e 192 }
AzureIoTClient 4:57e049bce51e 193
Azure.IoT Build 7:07bc440836b3 194 static IOTHUB_MESSAGE_LIST* getNextEventToSend(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 195 {
Azure.IoT Build 7:07bc440836b3 196 IOTHUB_MESSAGE_LIST* message = NULL;
Azure.IoT Build 7:07bc440836b3 197
Azure.IoT Build 7:07bc440836b3 198 if (!DList_IsListEmpty(transport_state->waitingToSend))
AzureIoTClient 4:57e049bce51e 199 {
Azure.IoT Build 7:07bc440836b3 200 PDLIST_ENTRY list_entry = transport_state->waitingToSend->Flink;
Azure.IoT Build 7:07bc440836b3 201 message = containingRecord(list_entry, IOTHUB_MESSAGE_LIST, entry);
AzureIoTClient 4:57e049bce51e 202 }
Azure.IoT Build 7:07bc440836b3 203
Azure.IoT Build 7:07bc440836b3 204 return message;
Azure.IoT Build 7:07bc440836b3 205 }
Azure.IoT Build 7:07bc440836b3 206
Azure.IoT Build 7:07bc440836b3 207 static int isEventInInProgressList(EVENT_TRACKER* event_tracker)
Azure.IoT Build 7:07bc440836b3 208 {
Azure.IoT Build 7:07bc440836b3 209 return !DList_IsListEmpty(&event_tracker->entry);
AzureIoTClient 4:57e049bce51e 210 }
AzureIoTClient 4:57e049bce51e 211
Azure.IoT Build 7:07bc440836b3 212 static void removeEventFromInProgressList(EVENT_TRACKER* event_tracker)
AzureIoTClient 4:57e049bce51e 213 {
Azure.IoT Build 7:07bc440836b3 214 DList_RemoveEntryList(&event_tracker->entry);
Azure.IoT Build 7:07bc440836b3 215 DList_InitializeListHead(&event_tracker->entry);
AzureIoTClient 4:57e049bce51e 216 }
AzureIoTClient 4:57e049bce51e 217
Azure.IoT Build 7:07bc440836b3 218 static void rollEventBackToWaitList(EVENT_TRACKER* event_tracker, AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 219 {
Azure.IoT Build 7:07bc440836b3 220 removeEventFromInProgressList(event_tracker);
Azure.IoT Build 7:07bc440836b3 221 DList_InsertTailList(transport_state->waitingToSend, &event_tracker->message->entry);
Azure.IoT Build 7:07bc440836b3 222 destroyEventTracker(event_tracker);
Azure.IoT Build 7:07bc440836b3 223 }
Azure.IoT Build 7:07bc440836b3 224
Azure.IoT Build 7:07bc440836b3 225 static void rollEventsBackToWaitList(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 226 {
Azure.IoT Build 7:07bc440836b3 227 PDLIST_ENTRY entry = transport_state->inProgress.Blink;
Azure.IoT Build 7:07bc440836b3 228
Azure.IoT Build 7:07bc440836b3 229 while (entry != &transport_state->inProgress)
AzureIoTClient 4:57e049bce51e 230 {
Azure.IoT Build 7:07bc440836b3 231 EVENT_TRACKER* event_tracker = containingRecord(entry, EVENT_TRACKER, entry);
Azure.IoT Build 7:07bc440836b3 232 entry = entry->Blink;
Azure.IoT Build 7:07bc440836b3 233 rollEventBackToWaitList(event_tracker, transport_state);
AzureIoTClient 4:57e049bce51e 234 }
AzureIoTClient 4:57e049bce51e 235 }
AzureIoTClient 4:57e049bce51e 236
Azure.IoT Build 7:07bc440836b3 237 static void on_message_send_complete(const void* context, MESSAGE_SEND_RESULT send_result)
AzureIoTClient 4:57e049bce51e 238 {
Azure.IoT Build 7:07bc440836b3 239 if (context != NULL)
AzureIoTClient 4:57e049bce51e 240 {
Azure.IoT Build 7:07bc440836b3 241 EVENT_TRACKER* event_tracker = (EVENT_TRACKER*)context;
AzureIoTClient 4:57e049bce51e 242
Azure.IoT Build 7:07bc440836b3 243 IOTHUB_CLIENT_RESULT iot_hub_send_result;
Azure.IoT Build 7:07bc440836b3 244
Azure.IoT Build 7:07bc440836b3 245 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_142: [The callback ‘on_message_send_complete’ shall pass to the upper layer callback an IOTHUB_CLIENT_CONFIRMATION_OK if the result received is MESSAGE_SEND_OK]
Azure.IoT Build 7:07bc440836b3 246 if (send_result == MESSAGE_SEND_OK)
AzureIoTClient 4:57e049bce51e 247 {
Azure.IoT Build 7:07bc440836b3 248 iot_hub_send_result = IOTHUB_CLIENT_CONFIRMATION_OK;
AzureIoTClient 4:57e049bce51e 249 }
Azure.IoT Build 7:07bc440836b3 250 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_143: [The callback ‘on_message_send_complete’ shall pass to the upper layer callback an IOTHUB_CLIENT_CONFIRMATION_ERROR if the result received is MESSAGE_SEND_ERROR]
Azure.IoT Build 7:07bc440836b3 251 else if (send_result == MESSAGE_SEND_ERROR)
AzureIoTClient 4:57e049bce51e 252 {
Azure.IoT Build 7:07bc440836b3 253 iot_hub_send_result = IOTHUB_CLIENT_CONFIRMATION_ERROR;
AzureIoTClient 5:8d58d20699dd 254 }
AzureIoTClient 4:57e049bce51e 255
Azure.IoT Build 7:07bc440836b3 256 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_102: [The callback ‘on_message_send_complete’ shall invoke the upper layer callback for message received if provided]
Azure.IoT Build 7:07bc440836b3 257 if (event_tracker->message->callback != NULL)
AzureIoTClient 4:57e049bce51e 258 {
Azure.IoT Build 7:07bc440836b3 259 event_tracker->message->callback(iot_hub_send_result, event_tracker->message->context);
Azure.IoT Build 7:07bc440836b3 260 }
AzureIoTClient 4:57e049bce51e 261
Azure.IoT Build 7:07bc440836b3 262 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_151: [The callback ‘on_message_send_complete’ shall destroy the message handle (IOTHUB_MESSAGE_HANDLE) using IoTHubMessage_Destroy()]
Azure.IoT Build 7:07bc440836b3 263 IoTHubMessage_Destroy(event_tracker->message->messageHandle);
Azure.IoT Build 7:07bc440836b3 264 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_152: [The callback ‘on_message_send_complete’ shall destroy the IOTHUB_MESSAGE_LIST instance]
Azure.IoT Build 7:07bc440836b3 265 free(event_tracker->message);
AzureIoTClient 4:57e049bce51e 266
Azure.IoT Build 7:07bc440836b3 267 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_100: [The callback ‘on_message_send_complete’ shall remove the target message from the in-progress list after the upper layer callback]
Azure.IoT Build 7:07bc440836b3 268 if (isEventInInProgressList(event_tracker))
AzureIoTClient 4:57e049bce51e 269 {
Azure.IoT Build 7:07bc440836b3 270 removeEventFromInProgressList(event_tracker);
Azure.IoT Build 7:07bc440836b3 271 destroyEventTracker(event_tracker);
AzureIoTClient 4:57e049bce51e 272 }
AzureIoTClient 4:57e049bce51e 273 }
AzureIoTClient 4:57e049bce51e 274 }
AzureIoTClient 4:57e049bce51e 275
Azure.IoT Build 7:07bc440836b3 276 static void on_put_token_complete(const void* context, CBS_OPERATION_RESULT operation_result, unsigned int status_code, const char* status_description)
AzureIoTClient 4:57e049bce51e 277 {
Azure.IoT Build 7:07bc440836b3 278 AMQP_TRANSPORT_INSTANCE* transportState = (AMQP_TRANSPORT_INSTANCE*)context;
Azure.IoT Build 7:07bc440836b3 279
Azure.IoT Build 7:07bc440836b3 280 if (operation_result == OPERATION_RESULT_OK)
AzureIoTClient 4:57e049bce51e 281 {
Azure.IoT Build 7:07bc440836b3 282 transportState->cbs_state = CBS_STATE_AUTHENTICATED;
Azure.IoT Build 7:07bc440836b3 283 }
Azure.IoT Build 7:07bc440836b3 284 }
Azure.IoT Build 7:07bc440836b3 285
Azure.IoT Build 7:07bc440836b3 286 AMQP_VALUE on_message_received(const void* context, MESSAGE_HANDLE message)
Azure.IoT Build 7:07bc440836b3 287 {
Azure.IoT Build 7:07bc440836b3 288 AMQP_VALUE result = NULL;
Azure.IoT Build 7:07bc440836b3 289 IOTHUBMESSAGE_DISPOSITION_RESULT disposition_result = IOTHUBMESSAGE_REJECTED;
Azure.IoT Build 7:07bc440836b3 290
Azure.IoT Build 7:07bc440836b3 291 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_104: [The callback ‘on_message_received’ shall invoke IoTHubClient_LL_MessageCallback() passing the client and the incoming message handles as parameters]
Azure.IoT Build 7:07bc440836b3 292 IOTHUB_CLIENT_LL_HANDLE iothub_client_handle = (IOTHUB_CLIENT_LL_HANDLE)context;
Azure.IoT Build 7:07bc440836b3 293 IOTHUB_MESSAGE_HANDLE iothub_message = NULL;
Azure.IoT Build 7:07bc440836b3 294 MESSAGE_BODY_TYPE body_type;
Azure.IoT Build 7:07bc440836b3 295
Azure.IoT Build 7:07bc440836b3 296
Azure.IoT Build 7:07bc440836b3 297 if (message_get_body_type(message, &body_type) != 0)
Azure.IoT Build 7:07bc440836b3 298 {
Azure.IoT Build 7:07bc440836b3 299 LogError("Failed to get the type of the message received by the transport.\r\n");
Azure.IoT Build 7:07bc440836b3 300 }
Azure.IoT Build 7:07bc440836b3 301 else
Azure.IoT Build 7:07bc440836b3 302 {
Azure.IoT Build 7:07bc440836b3 303 if (body_type == MESSAGE_BODY_TYPE_DATA)
AzureIoTClient 4:57e049bce51e 304 {
Azure.IoT Build 7:07bc440836b3 305 BINARY_DATA binary_data;
Azure.IoT Build 7:07bc440836b3 306 if (message_get_body_amqp_data(message, 0, &binary_data) != 0)
Azure.IoT Build 7:07bc440836b3 307 {
Azure.IoT Build 7:07bc440836b3 308 LogError("Failed to get the body of the message received by the transport.\r\n");
Azure.IoT Build 7:07bc440836b3 309 }
Azure.IoT Build 7:07bc440836b3 310 else
Azure.IoT Build 7:07bc440836b3 311 {
Azure.IoT Build 7:07bc440836b3 312 iothub_message = IoTHubMessage_CreateFromByteArray(binary_data.bytes, binary_data.length);
Azure.IoT Build 7:07bc440836b3 313 }
AzureIoTClient 4:57e049bce51e 314 }
Azure.IoT Build 7:07bc440836b3 315 }
Azure.IoT Build 7:07bc440836b3 316
Azure.IoT Build 7:07bc440836b3 317 if (iothub_message == NULL)
Azure.IoT Build 7:07bc440836b3 318 {
Azure.IoT Build 7:07bc440836b3 319 LogError("Transport failed processing the message received.\r\n");
Azure.IoT Build 7:07bc440836b3 320 }
Azure.IoT Build 7:07bc440836b3 321 else
Azure.IoT Build 7:07bc440836b3 322 {
Azure.IoT Build 7:07bc440836b3 323 disposition_result = IoTHubClient_LL_MessageCallback((IOTHUB_CLIENT_LL_HANDLE)context, iothub_message);
Azure.IoT Build 7:07bc440836b3 324
Azure.IoT Build 7:07bc440836b3 325 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_105: [The callback ‘on_message_received’ shall return the result of messaging_delivery_accepted() if the IoTHubClient_LL_MessageCallback() returns IOTHUBMESSAGE_ACCEPTED]
Azure.IoT Build 7:07bc440836b3 326 if (disposition_result == IOTHUBMESSAGE_ACCEPTED)
AzureIoTClient 5:8d58d20699dd 327 {
Azure.IoT Build 7:07bc440836b3 328 result = messaging_delivery_accepted();
Azure.IoT Build 7:07bc440836b3 329 }
Azure.IoT Build 7:07bc440836b3 330 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_106: [The callback ‘on_message_received’ shall return the result of messaging_delivery_released() if the IoTHubClient_LL_MessageCallback() returns IOTHUBMESSAGE_ABANDONED]
Azure.IoT Build 7:07bc440836b3 331 else if (disposition_result == IOTHUBMESSAGE_ABANDONED)
Azure.IoT Build 7:07bc440836b3 332 {
Azure.IoT Build 7:07bc440836b3 333 result = messaging_delivery_released();
AzureIoTClient 5:8d58d20699dd 334 }
Azure.IoT Build 7:07bc440836b3 335 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_107: [The callback ‘on_message_received’ shall return the result of messaging_delivery_rejected(“Rejected by application”, “Rejected by application”) if the IoTHubClient_LL_MessageCallback() returns IOTHUBMESSAGE_REJECTED]
Azure.IoT Build 7:07bc440836b3 336 else if (disposition_result == IOTHUBMESSAGE_REJECTED)
AzureIoTClient 4:57e049bce51e 337 {
Azure.IoT Build 7:07bc440836b3 338 result = messaging_delivery_rejected("Rejected by application", "Rejected by application");
AzureIoTClient 4:57e049bce51e 339 }
Azure.IoT Build 7:07bc440836b3 340 }
Azure.IoT Build 7:07bc440836b3 341
Azure.IoT Build 7:07bc440836b3 342 return result;
Azure.IoT Build 7:07bc440836b3 343 }
Azure.IoT Build 7:07bc440836b3 344
Azure.IoT Build 7:07bc440836b3 345 XIO_HANDLE getTLSIOTransport(const char* fqdn, int port, const char* certificates)
Azure.IoT Build 7:07bc440836b3 346 {
Azure.IoT Build 7:07bc440836b3 347 TLSIO_CONFIG tls_io_config = { fqdn, port };
Azure.IoT Build 7:07bc440836b3 348 const IO_INTERFACE_DESCRIPTION* io_interface_description = platform_get_default_tlsio();
Azure.IoT Build 7:07bc440836b3 349 return xio_create(io_interface_description, &tls_io_config, NULL);
Azure.IoT Build 7:07bc440836b3 350 }
Azure.IoT Build 7:07bc440836b3 351
Azure.IoT Build 7:07bc440836b3 352 static void destroyConnection(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 353 {
Azure.IoT Build 7:07bc440836b3 354 if (transport_state != NULL)
Azure.IoT Build 7:07bc440836b3 355 {
Azure.IoT Build 7:07bc440836b3 356 if (transport_state->cbs != NULL)
AzureIoTClient 4:57e049bce51e 357 {
Azure.IoT Build 7:07bc440836b3 358 cbs_destroy(transport_state->cbs);
Azure.IoT Build 7:07bc440836b3 359 transport_state->cbs = NULL;
AzureIoTClient 4:57e049bce51e 360 }
Azure.IoT Build 7:07bc440836b3 361
Azure.IoT Build 7:07bc440836b3 362 if (transport_state->session != NULL)
Azure.IoT Build 7:07bc440836b3 363 {
Azure.IoT Build 7:07bc440836b3 364 session_destroy(transport_state->session);
Azure.IoT Build 7:07bc440836b3 365 transport_state->session = NULL;
Azure.IoT Build 7:07bc440836b3 366 }
Azure.IoT Build 7:07bc440836b3 367
Azure.IoT Build 7:07bc440836b3 368 if (transport_state->connection != NULL)
AzureIoTClient 4:57e049bce51e 369 {
Azure.IoT Build 7:07bc440836b3 370 connection_destroy(transport_state->connection);
Azure.IoT Build 7:07bc440836b3 371 transport_state->connection = NULL;
AzureIoTClient 4:57e049bce51e 372 }
Azure.IoT Build 7:07bc440836b3 373
Azure.IoT Build 7:07bc440836b3 374 if (transport_state->sasl_io != NULL)
AzureIoTClient 4:57e049bce51e 375 {
Azure.IoT Build 7:07bc440836b3 376 xio_destroy(transport_state->sasl_io);
Azure.IoT Build 7:07bc440836b3 377 transport_state->sasl_io = NULL;
Azure.IoT Build 7:07bc440836b3 378 }
Azure.IoT Build 7:07bc440836b3 379
Azure.IoT Build 7:07bc440836b3 380 if (transport_state->sasl_mechanism != NULL)
Azure.IoT Build 7:07bc440836b3 381 {
Azure.IoT Build 7:07bc440836b3 382 saslmechanism_destroy(transport_state->sasl_mechanism);
Azure.IoT Build 7:07bc440836b3 383 transport_state->sasl_mechanism = NULL;
AzureIoTClient 4:57e049bce51e 384 }
Azure.IoT Build 7:07bc440836b3 385
Azure.IoT Build 7:07bc440836b3 386 if (transport_state->tls_io != NULL)
Azure.IoT Build 7:07bc440836b3 387 {
Azure.IoT Build 7:07bc440836b3 388 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_034: [IoTHubTransportAMQP_Destroy shall destroy the AMQP TLS I/O transport.]
Azure.IoT Build 7:07bc440836b3 389 xio_destroy(transport_state->tls_io);
Azure.IoT Build 7:07bc440836b3 390 transport_state->tls_io = NULL;
Azure.IoT Build 7:07bc440836b3 391 }
Azure.IoT Build 7:07bc440836b3 392 }
Azure.IoT Build 7:07bc440836b3 393 }
Azure.IoT Build 7:07bc440836b3 394
Azure.IoT Build 7:07bc440836b3 395 static void on_amqp_management_state_changed(void* context, AMQP_MANAGEMENT_STATE new_amqp_management_state, AMQP_MANAGEMENT_STATE previous_amqp_management_state)
Azure.IoT Build 7:07bc440836b3 396 {
Azure.IoT Build 7:07bc440836b3 397 if (context != NULL)
Azure.IoT Build 7:07bc440836b3 398 {
Azure.IoT Build 7:07bc440836b3 399 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)context;
Azure.IoT Build 7:07bc440836b3 400 transport_state->connection_state = new_amqp_management_state;
Azure.IoT Build 7:07bc440836b3 401 }
Azure.IoT Build 7:07bc440836b3 402 }
Azure.IoT Build 7:07bc440836b3 403
Azure.IoT Build 7:07bc440836b3 404 static int establishConnection(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 405 {
Azure.IoT Build 7:07bc440836b3 406 int result;
Azure.IoT Build 7:07bc440836b3 407
Azure.IoT Build 7:07bc440836b3 408 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_110: [IoTHubTransportAMQP_DoWork shall create the TLS IO using transport_state->io_transport_provider callback function]
Azure.IoT Build 7:07bc440836b3 409 if (transport_state->tls_io == NULL &&
Azure.IoT Build 7:07bc440836b3 410 (transport_state->tls_io = transport_state->tls_io_transport_provider(STRING_c_str(transport_state->iotHubHostFqdn), transport_state->iotHubPort, transport_state->trusted_certificates)) == NULL)
Azure.IoT Build 7:07bc440836b3 411 {
Azure.IoT Build 7:07bc440836b3 412 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_136: [If transport_state->io_transport_provider_callback fails, IoTHubTransportAMQP_DoWork shall fail and return immediately]
Azure.IoT Build 7:07bc440836b3 413 result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 414 LogError("Failed to obtain a TLS I/O transport layer.\r\n");
Azure.IoT Build 7:07bc440836b3 415 }
Azure.IoT Build 7:07bc440836b3 416 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_056: [IoTHubTransportAMQP_DoWork shall create the SASL mechanism using AMQP’s saslmechanism_create() API]
Azure.IoT Build 7:07bc440836b3 417 else if ((transport_state->sasl_mechanism = saslmechanism_create(saslmssbcbs_get_interface(), NULL)) == NULL)
Azure.IoT Build 7:07bc440836b3 418 {
Azure.IoT Build 7:07bc440836b3 419 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_057: [If saslmechanism_create() fails, IoTHubTransportAMQP_DoWork shall fail and return immediately]
Azure.IoT Build 7:07bc440836b3 420 result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 421 LogError("Failed to create a SASL mechanism.\r\n");
Azure.IoT Build 7:07bc440836b3 422 }
Azure.IoT Build 7:07bc440836b3 423 else
Azure.IoT Build 7:07bc440836b3 424 {
Azure.IoT Build 7:07bc440836b3 425 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_060: [IoTHubTransportAMQP_DoWork shall create the SASL I / O layer using the xio_create() C Shared Utility API]
Azure.IoT Build 7:07bc440836b3 426 SASLCLIENTIO_CONFIG sasl_client_config = { transport_state->tls_io, transport_state->sasl_mechanism };
Azure.IoT Build 7:07bc440836b3 427 if ((transport_state->sasl_io = xio_create(saslclientio_get_interface_description(), &sasl_client_config, NULL)) == NULL)
AzureIoTClient 4:57e049bce51e 428 {
Azure.IoT Build 7:07bc440836b3 429 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_061: [If xio_create() fails creating the SASL I/O layer, IoTHubTransportAMQP_DoWork shall fail and return immediately]
Azure.IoT Build 7:07bc440836b3 430 result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 431 LogError("Failed to create a SASL I/O layer.\r\n");
AzureIoTClient 4:57e049bce51e 432 }
Azure.IoT Build 7:07bc440836b3 433 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_062: [IoTHubTransportAMQP_DoWork shall create the connection with the IoT service using connection_create() AMQP API, passing the SASL I/O layer, IoT Hub FQDN and container ID as parameters (pass NULL for callbacks)]
Azure.IoT Build 7:07bc440836b3 434 else if ((transport_state->connection = connection_create(transport_state->sasl_io, STRING_c_str(transport_state->iotHubHostFqdn), DEFAULT_CONTAINER_ID, NULL, NULL)) == NULL)
AzureIoTClient 4:57e049bce51e 435 {
Azure.IoT Build 7:07bc440836b3 436 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_063: [If connection_create() fails, IoTHubTransportAMQP_DoWork shall fail and return immediately.]
Azure.IoT Build 7:07bc440836b3 437 result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 438 LogError("Failed to create the AMQP connection.\r\n");
Azure.IoT Build 7:07bc440836b3 439 }
Azure.IoT Build 7:07bc440836b3 440 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_137: [IoTHubTransportAMQP_DoWork shall create the AMQP session session_create() AMQP API, passing the connection instance as parameter]
Azure.IoT Build 7:07bc440836b3 441 else if ((transport_state->session = session_create(transport_state->connection, NULL, NULL)) == NULL)
Azure.IoT Build 7:07bc440836b3 442 {
Azure.IoT Build 7:07bc440836b3 443 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_138 : [If session_create() fails, IoTHubTransportAMQP_DoWork shall fail and return immediately]
Azure.IoT Build 7:07bc440836b3 444 result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 445 LogError("Failed to create the AMQP session.\r\n");
AzureIoTClient 4:57e049bce51e 446 }
AzureIoTClient 4:57e049bce51e 447 else
AzureIoTClient 4:57e049bce51e 448 {
Azure.IoT Build 7:07bc440836b3 449 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_065: [IoTHubTransportAMQP_DoWork shall apply a default value of UINT_MAX for the parameter ‘AMQP incoming window’]
Azure.IoT Build 7:07bc440836b3 450 if (session_set_incoming_window(transport_state->session, (uint32_t)DEFAULT_INCOMING_WINDOW_SIZE) != 0)
Azure.IoT Build 7:07bc440836b3 451 {
Azure.IoT Build 7:07bc440836b3 452 LogError("Failed to set the AMQP incoming window size.\r\n");
Azure.IoT Build 7:07bc440836b3 453 }
Azure.IoT Build 7:07bc440836b3 454
Azure.IoT Build 7:07bc440836b3 455 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_115: [IoTHubTransportAMQP_DoWork shall apply a default value of 100 for the parameter ‘AMQP outgoing window’]
Azure.IoT Build 7:07bc440836b3 456 if (session_set_outgoing_window(transport_state->session, DEFAULT_OUTGOING_WINDOW_SIZE) != 0)
Azure.IoT Build 7:07bc440836b3 457 {
Azure.IoT Build 7:07bc440836b3 458 LogError("Failed to set the AMQP outgoing window size.\r\n");
Azure.IoT Build 7:07bc440836b3 459 }
Azure.IoT Build 7:07bc440836b3 460
Azure.IoT Build 7:07bc440836b3 461 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_066: [IoTHubTransportAMQP_DoWork shall establish the CBS connection using the cbs_create() AMQP API]
Azure.IoT Build 7:07bc440836b3 462 if ((transport_state->cbs = cbs_create(transport_state->session, on_amqp_management_state_changed, NULL)) == NULL)
AzureIoTClient 4:57e049bce51e 463 {
Azure.IoT Build 7:07bc440836b3 464 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_067: [If cbs_create() fails, IoTHubTransportAMQP_DoWork shall fail and return immediately]
Azure.IoT Build 7:07bc440836b3 465 result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 466 LogError("Failed to create the CBS connection.\r\n");
Azure.IoT Build 7:07bc440836b3 467 }
Azure.IoT Build 7:07bc440836b3 468 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_139: [IoTHubTransportAMQP_DoWork shall open the CBS connection using the cbs_open() AMQP API]
Azure.IoT Build 7:07bc440836b3 469 else if ((cbs_open(transport_state->cbs)) != 0)
Azure.IoT Build 7:07bc440836b3 470 {
Azure.IoT Build 7:07bc440836b3 471 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_140: [If cbs_open() fails, IoTHubTransportAMQP_DoWork shall fail and return immediately]
Azure.IoT Build 7:07bc440836b3 472 result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 473 LogError("Failed to open the connection with CBS.\r\n");
Azure.IoT Build 7:07bc440836b3 474 }
Azure.IoT Build 7:07bc440836b3 475 else
Azure.IoT Build 7:07bc440836b3 476 {
Azure.IoT Build 7:07bc440836b3 477 transport_state->connection_establish_time = getSecondsSinceEpoch();
Azure.IoT Build 7:07bc440836b3 478 transport_state->cbs_state = CBS_STATE_IDLE;
Azure.IoT Build 7:07bc440836b3 479 result = RESULT_OK;
AzureIoTClient 4:57e049bce51e 480 }
AzureIoTClient 4:57e049bce51e 481 }
AzureIoTClient 4:57e049bce51e 482 }
Azure.IoT Build 7:07bc440836b3 483
Azure.IoT Build 7:07bc440836b3 484 if (result == RESULT_FAILURE)
Azure.IoT Build 7:07bc440836b3 485 {
Azure.IoT Build 7:07bc440836b3 486 destroyConnection(transport_state);
Azure.IoT Build 7:07bc440836b3 487 }
Azure.IoT Build 7:07bc440836b3 488
Azure.IoT Build 7:07bc440836b3 489 return result;
AzureIoTClient 4:57e049bce51e 490 }
AzureIoTClient 4:57e049bce51e 491
Azure.IoT Build 7:07bc440836b3 492 static int startAuthentication(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 493 {
Azure.IoT Build 7:07bc440836b3 494 int result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 495
Azure.IoT Build 7:07bc440836b3 496 size_t sas_token_create_time = getSecondsSinceEpoch(); // I.e.: NOW, in seconds since epoch.
Azure.IoT Build 7:07bc440836b3 497
Azure.IoT Build 7:07bc440836b3 498 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_083: [Each new SAS token created by the transport shall be valid for up to ‘sas_token_lifetime’ milliseconds from the time of creation]
Azure.IoT Build 7:07bc440836b3 499 size_t new_expiry_time = sas_token_create_time + (transport_state->sas_token_lifetime / 1000);
Azure.IoT Build 7:07bc440836b3 500
Azure.IoT Build 7:07bc440836b3 501 STRING_HANDLE newSASToken = SASToken_Create(transport_state->deviceKey, transport_state->devicesPath, transport_state->sasTokenKeyName, new_expiry_time);
Azure.IoT Build 7:07bc440836b3 502
Azure.IoT Build 7:07bc440836b3 503 if (newSASToken == NULL)
AzureIoTClient 4:57e049bce51e 504 {
Azure.IoT Build 7:07bc440836b3 505 LogError("Could not generate a new SAS token for the CBS\r\n");
Azure.IoT Build 7:07bc440836b3 506 }
Azure.IoT Build 7:07bc440836b3 507 else if (cbs_put_token(transport_state->cbs, CBS_AUDIENCE, STRING_c_str(transport_state->devicesPath), STRING_c_str(newSASToken), on_put_token_complete, transport_state) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 508 {
Azure.IoT Build 7:07bc440836b3 509 LogError("Failed applying new SAS token to CBS\r\n");
AzureIoTClient 4:57e049bce51e 510 }
AzureIoTClient 4:57e049bce51e 511 else
AzureIoTClient 4:57e049bce51e 512 {
Azure.IoT Build 7:07bc440836b3 513 transport_state->cbs_state = CBS_STATE_AUTH_IN_PROGRESS;
Azure.IoT Build 7:07bc440836b3 514 transport_state->current_sas_token_create_time = sas_token_create_time;
Azure.IoT Build 7:07bc440836b3 515 result = RESULT_OK;
AzureIoTClient 4:57e049bce51e 516 }
Azure.IoT Build 7:07bc440836b3 517
Azure.IoT Build 7:07bc440836b3 518 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_145: [Each new SAS token created shall be deleted from memory immediately after sending it to CBS]
Azure.IoT Build 7:07bc440836b3 519 if (newSASToken != NULL)
Azure.IoT Build 7:07bc440836b3 520 STRING_delete(newSASToken);
Azure.IoT Build 7:07bc440836b3 521
AzureIoTClient 4:57e049bce51e 522 return result;
AzureIoTClient 4:57e049bce51e 523 }
AzureIoTClient 4:57e049bce51e 524
Azure.IoT Build 7:07bc440836b3 525 static int verifyAuthenticationTimeout(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 526 {
Azure.IoT Build 7:07bc440836b3 527 return ((getSecondsSinceEpoch() - transport_state->current_sas_token_create_time) * 1000 >= transport_state->cbs_request_timeout) ? RESULT_TIMEOUT : RESULT_OK;
Azure.IoT Build 7:07bc440836b3 528 }
AzureIoTClient 4:57e049bce51e 529
Azure.IoT Build 7:07bc440836b3 530 static void handleEventSendTimeouts(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 531 {
Azure.IoT Build 7:07bc440836b3 532 time_t current_time = get_time(NULL);
Azure.IoT Build 7:07bc440836b3 533 PDLIST_ENTRY entry = transport_state->inProgress.Flink;
Azure.IoT Build 7:07bc440836b3 534
Azure.IoT Build 7:07bc440836b3 535 while (entry != &transport_state->inProgress)
AzureIoTClient 4:57e049bce51e 536 {
Azure.IoT Build 7:07bc440836b3 537 EVENT_TRACKER* event_tracker = containingRecord(entry, EVENT_TRACKER, entry);
Azure.IoT Build 7:07bc440836b3 538
Azure.IoT Build 7:07bc440836b3 539 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_085: [IoTHubTransportAMQP_DoWork shall attempt to send all the queued messages for up to ‘message_send_timeout’ milliseconds]
Azure.IoT Build 7:07bc440836b3 540 if (difftime(current_time, event_tracker->time_sent) * 1000 >= transport_state->message_send_timeout)
Azure.IoT Build 7:07bc440836b3 541 {
Azure.IoT Build 7:07bc440836b3 542 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_120: [If a ‘message_send_timeout’ occurs the timed out events removed from the inProgress and the upper layer notified of the send error]
Azure.IoT Build 7:07bc440836b3 543 on_message_send_complete(event_tracker, MESSAGE_SEND_ERROR);
Azure.IoT Build 7:07bc440836b3 544 }
Azure.IoT Build 7:07bc440836b3 545
Azure.IoT Build 7:07bc440836b3 546 entry = entry->Flink;
AzureIoTClient 4:57e049bce51e 547 }
Azure.IoT Build 7:07bc440836b3 548 }
Azure.IoT Build 7:07bc440836b3 549
Azure.IoT Build 7:07bc440836b3 550 static void attachDeviceClientTypeToLink(LINK_HANDLE link)
Azure.IoT Build 7:07bc440836b3 551 {
Azure.IoT Build 7:07bc440836b3 552 fields attach_properties = NULL;
Azure.IoT Build 7:07bc440836b3 553 AMQP_VALUE deviceClientTypeKeyName = NULL;
Azure.IoT Build 7:07bc440836b3 554 AMQP_VALUE deviceClientTypeValue = NULL;
Azure.IoT Build 7:07bc440836b3 555 int result;
Azure.IoT Build 7:07bc440836b3 556
Azure.IoT Build 7:07bc440836b3 557 //
Azure.IoT Build 7:07bc440836b3 558 // Attempt to add the device client type string to the attach properties.
Azure.IoT Build 7:07bc440836b3 559 // If this doesn't happen, well, this isn't that important. We can operate
Azure.IoT Build 7:07bc440836b3 560 // without this property. It's worth noting that even though we are going
Azure.IoT Build 7:07bc440836b3 561 // on, the reasons any of these operations fail don't bode well for the
Azure.IoT Build 7:07bc440836b3 562 // actual upcoming attach.
Azure.IoT Build 7:07bc440836b3 563 //
Azure.IoT Build 7:07bc440836b3 564
Azure.IoT Build 7:07bc440836b3 565 // Codes_SRS_IOTHUBTRANSPORTAMQP_06_187: [If IotHubTransportAMQP_DoWork fails to create an attach properties map and assign that map to the link the function will STILL proceed with the attempt to create the message sender.]
Azure.IoT Build 7:07bc440836b3 566
Azure.IoT Build 7:07bc440836b3 567 if ((attach_properties = amqpvalue_create_map()) == NULL)
AzureIoTClient 4:57e049bce51e 568 {
Azure.IoT Build 7:07bc440836b3 569 LogError("Failed to create the map for device client type.\r\n");
AzureIoTClient 4:57e049bce51e 570 }
Azure.IoT Build 7:07bc440836b3 571 else if ((deviceClientTypeKeyName = amqpvalue_create_symbol("com.microsoft:client-version")) == NULL)
Azure.IoT Build 7:07bc440836b3 572 {
Azure.IoT Build 7:07bc440836b3 573 LogError("Failed to create the key name for the device client type.\r\n");
Azure.IoT Build 7:07bc440836b3 574 }
Azure.IoT Build 7:07bc440836b3 575 else if ((deviceClientTypeValue = amqpvalue_create_string(CLIENT_DEVICE_TYPE_PREFIX CLIENT_DEVICE_BACKSLASH IOTHUB_SDK_VERSION)) == NULL)
AzureIoTClient 4:57e049bce51e 576 {
Azure.IoT Build 7:07bc440836b3 577 LogError("Failed to create the key value for the device client type.\r\n");
Azure.IoT Build 7:07bc440836b3 578 }
Azure.IoT Build 7:07bc440836b3 579 else if ((result = amqpvalue_set_map_value(attach_properties, deviceClientTypeKeyName, deviceClientTypeValue)) != 0)
Azure.IoT Build 7:07bc440836b3 580 {
Azure.IoT Build 7:07bc440836b3 581 LogError("Failed to set the property map for the device client type. Error code is: %d\r\n", result);
AzureIoTClient 4:57e049bce51e 582 }
Azure.IoT Build 7:07bc440836b3 583 else if ((result = link_set_attach_properties(link, attach_properties)) != 0)
AzureIoTClient 4:57e049bce51e 584 {
Azure.IoT Build 7:07bc440836b3 585 LogError("Unable to attach the device client type to the link properties. Error code is: %d\r\n", result);
Azure.IoT Build 7:07bc440836b3 586 }
Azure.IoT Build 7:07bc440836b3 587 amqpvalue_destroy(attach_properties);
Azure.IoT Build 7:07bc440836b3 588 amqpvalue_destroy(deviceClientTypeKeyName);
Azure.IoT Build 7:07bc440836b3 589 amqpvalue_destroy(deviceClientTypeValue);
Azure.IoT Build 7:07bc440836b3 590
Azure.IoT Build 7:07bc440836b3 591 }
Azure.IoT Build 7:07bc440836b3 592
Azure.IoT Build 7:07bc440836b3 593 static int destroyEventSender(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 594 {
Azure.IoT Build 7:07bc440836b3 595 int result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 596
Azure.IoT Build 7:07bc440836b3 597 if (transport_state->message_sender != NULL)
Azure.IoT Build 7:07bc440836b3 598 {
Azure.IoT Build 7:07bc440836b3 599 messagesender_destroy(transport_state->message_sender);
Azure.IoT Build 7:07bc440836b3 600
Azure.IoT Build 7:07bc440836b3 601 transport_state->message_sender = NULL;
Azure.IoT Build 7:07bc440836b3 602
Azure.IoT Build 7:07bc440836b3 603 link_destroy(transport_state->sender_link);
Azure.IoT Build 7:07bc440836b3 604
Azure.IoT Build 7:07bc440836b3 605 transport_state->sender_link = NULL;
Azure.IoT Build 7:07bc440836b3 606
Azure.IoT Build 7:07bc440836b3 607 result = RESULT_OK;
AzureIoTClient 4:57e049bce51e 608 }
AzureIoTClient 4:57e049bce51e 609
AzureIoTClient 4:57e049bce51e 610 return result;
AzureIoTClient 4:57e049bce51e 611 }
AzureIoTClient 4:57e049bce51e 612
Azure.IoT Build 7:07bc440836b3 613 static int createEventSender(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 614 {
Azure.IoT Build 7:07bc440836b3 615 int result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 616
Azure.IoT Build 7:07bc440836b3 617 if (transport_state->message_sender == NULL)
AzureIoTClient 4:57e049bce51e 618 {
Azure.IoT Build 7:07bc440836b3 619 AMQP_VALUE source = NULL;
Azure.IoT Build 7:07bc440836b3 620 AMQP_VALUE target = NULL;
Azure.IoT Build 7:07bc440836b3 621
Azure.IoT Build 7:07bc440836b3 622 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_068: [IoTHubTransportAMQP_DoWork shall create the AMQP link for sending messages using ‘source’ as “ingress”, target as the IoT hub FQDN, link name as “sender-link” and role as ‘role_sender’]
Azure.IoT Build 7:07bc440836b3 623 if ((source = messaging_create_source(MESSAGE_SENDER_SOURCE_ADDRESS)) == NULL)
AzureIoTClient 4:57e049bce51e 624 {
Azure.IoT Build 7:07bc440836b3 625 LogError("Failed creating AMQP messaging source attribute.\r\n");
AzureIoTClient 4:57e049bce51e 626 }
Azure.IoT Build 7:07bc440836b3 627 else if ((target = messaging_create_target(STRING_c_str(transport_state->targetAddress))) == NULL)
AzureIoTClient 4:57e049bce51e 628 {
Azure.IoT Build 7:07bc440836b3 629 LogError("Failed creating AMQP messaging target attribute.\r\n");
Azure.IoT Build 7:07bc440836b3 630 }
Azure.IoT Build 7:07bc440836b3 631 else if ((transport_state->sender_link = link_create(transport_state->session, MESSAGE_SENDER_LINK_NAME, role_sender, source, target)) == NULL)
Azure.IoT Build 7:07bc440836b3 632 {
Azure.IoT Build 7:07bc440836b3 633 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_069: [If IoTHubTransportAMQP_DoWork fails to create the AMQP link for sending messages, the function shall fail and return immediately, flagging the connection to be re-stablished]
Azure.IoT Build 7:07bc440836b3 634 LogError("Failed creating AMQP link for message sender.\r\n");
AzureIoTClient 4:57e049bce51e 635 }
AzureIoTClient 4:57e049bce51e 636 else
AzureIoTClient 4:57e049bce51e 637 {
Azure.IoT Build 7:07bc440836b3 638 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_119: [IoTHubTransportAMQP_DoWork shall apply a default value of 65536 for the parameter ‘Link MAX message size’]
Azure.IoT Build 7:07bc440836b3 639 if (link_set_max_message_size(transport_state->sender_link, MESSAGE_SENDER_MAX_LINK_SIZE) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 640 {
Azure.IoT Build 7:07bc440836b3 641 LogError("Failed setting AMQP link max message size.\r\n");
Azure.IoT Build 7:07bc440836b3 642 }
Azure.IoT Build 7:07bc440836b3 643
Azure.IoT Build 7:07bc440836b3 644 attachDeviceClientTypeToLink(transport_state->sender_link);
Azure.IoT Build 7:07bc440836b3 645
Azure.IoT Build 7:07bc440836b3 646 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_070: [IoTHubTransportAMQP_DoWork shall create the AMQP message sender using messagesender_create() AMQP API]
Azure.IoT Build 7:07bc440836b3 647 if ((transport_state->message_sender = messagesender_create(transport_state->sender_link, NULL, NULL, NULL)) == NULL)
Azure.IoT Build 7:07bc440836b3 648 {
Azure.IoT Build 7:07bc440836b3 649 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_071: [IoTHubTransportAMQP_DoWork shall fail and return immediately if the AMQP message sender instance fails to be created, flagging the connection to be re-established]
Azure.IoT Build 7:07bc440836b3 650 LogError("Could not allocate AMQP message sender\r\n");
Azure.IoT Build 7:07bc440836b3 651 }
Azure.IoT Build 7:07bc440836b3 652 else
Azure.IoT Build 7:07bc440836b3 653 {
Azure.IoT Build 7:07bc440836b3 654 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_072: [IoTHubTransportAMQP_DoWork shall open the AMQP message sender using messagesender_open() AMQP API]
Azure.IoT Build 7:07bc440836b3 655 if (messagesender_open(transport_state->message_sender) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 656 {
Azure.IoT Build 7:07bc440836b3 657 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_073: [IoTHubTransportAMQP_DoWork shall fail and return immediately if the AMQP message sender instance fails to be opened, flagging the connection to be re-established]
Azure.IoT Build 7:07bc440836b3 658 LogError("Failed opening the AMQP message sender.\r\n");
Azure.IoT Build 7:07bc440836b3 659 }
Azure.IoT Build 7:07bc440836b3 660 else
Azure.IoT Build 7:07bc440836b3 661 {
Azure.IoT Build 7:07bc440836b3 662 result = RESULT_OK;
Azure.IoT Build 7:07bc440836b3 663 }
Azure.IoT Build 7:07bc440836b3 664 }
AzureIoTClient 4:57e049bce51e 665 }
Azure.IoT Build 7:07bc440836b3 666
Azure.IoT Build 7:07bc440836b3 667 if (source != NULL)
Azure.IoT Build 7:07bc440836b3 668 amqpvalue_destroy(source);
Azure.IoT Build 7:07bc440836b3 669 if (target != NULL)
Azure.IoT Build 7:07bc440836b3 670 amqpvalue_destroy(target);
AzureIoTClient 4:57e049bce51e 671 }
Azure.IoT Build 7:07bc440836b3 672
Azure.IoT Build 7:07bc440836b3 673 return result;
AzureIoTClient 4:57e049bce51e 674 }
Azure.IoT Build 7:07bc440836b3 675
Azure.IoT Build 7:07bc440836b3 676 static int destroyMessageReceiver(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 677 {
Azure.IoT Build 7:07bc440836b3 678 int result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 679
Azure.IoT Build 7:07bc440836b3 680 if (transport_state->message_receiver != NULL)
AzureIoTClient 4:57e049bce51e 681 {
Azure.IoT Build 7:07bc440836b3 682 if (messagereceiver_close(transport_state->message_receiver) != RESULT_OK)
AzureIoTClient 4:57e049bce51e 683 {
Azure.IoT Build 7:07bc440836b3 684 LogError("Failed closing the AMQP message receiver.\r\n");
Azure.IoT Build 7:07bc440836b3 685 }
Azure.IoT Build 7:07bc440836b3 686
Azure.IoT Build 7:07bc440836b3 687 messagereceiver_destroy(transport_state->message_receiver);
Azure.IoT Build 7:07bc440836b3 688
Azure.IoT Build 7:07bc440836b3 689 transport_state->message_receiver = NULL;
Azure.IoT Build 7:07bc440836b3 690
Azure.IoT Build 7:07bc440836b3 691 link_destroy(transport_state->receiver_link);
Azure.IoT Build 7:07bc440836b3 692
Azure.IoT Build 7:07bc440836b3 693 transport_state->receiver_link = NULL;
Azure.IoT Build 7:07bc440836b3 694
Azure.IoT Build 7:07bc440836b3 695 result = RESULT_OK;
Azure.IoT Build 7:07bc440836b3 696 }
Azure.IoT Build 7:07bc440836b3 697
Azure.IoT Build 7:07bc440836b3 698 return result;
Azure.IoT Build 7:07bc440836b3 699 }
Azure.IoT Build 7:07bc440836b3 700
Azure.IoT Build 7:07bc440836b3 701 static int createMessageReceiver(AMQP_TRANSPORT_INSTANCE* transport_state, IOTHUB_CLIENT_LL_HANDLE iothub_client_handle)
Azure.IoT Build 7:07bc440836b3 702 {
Azure.IoT Build 7:07bc440836b3 703 int result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 704
Azure.IoT Build 7:07bc440836b3 705 if (transport_state->message_sender == NULL)
Azure.IoT Build 7:07bc440836b3 706 {
Azure.IoT Build 7:07bc440836b3 707 AMQP_VALUE source = NULL;
Azure.IoT Build 7:07bc440836b3 708 AMQP_VALUE target = NULL;
Azure.IoT Build 7:07bc440836b3 709
Azure.IoT Build 7:07bc440836b3 710 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_074: [IoTHubTransportAMQP_DoWork shall create the AMQP link for receiving messages using ‘source’ as messageReceiveAddress, target as the “ingress-rx”, link name as “receiver-link” and role as ‘role_receiver’]
Azure.IoT Build 7:07bc440836b3 711 if ((source = messaging_create_source(STRING_c_str(transport_state->messageReceiveAddress))) == NULL)
Azure.IoT Build 7:07bc440836b3 712 {
Azure.IoT Build 7:07bc440836b3 713 LogError("Failed creating AMQP message receiver source attribute.\r\n");
Azure.IoT Build 7:07bc440836b3 714 }
Azure.IoT Build 7:07bc440836b3 715 else if ((target = messaging_create_target(MESSAGE_RECEIVER_TARGET_ADDRESS)) == NULL)
Azure.IoT Build 7:07bc440836b3 716 {
Azure.IoT Build 7:07bc440836b3 717 LogError("Failed creating AMQP message receiver target attribute.\r\n");
Azure.IoT Build 7:07bc440836b3 718 }
Azure.IoT Build 7:07bc440836b3 719 else if ((transport_state->receiver_link = link_create(transport_state->session, MESSAGE_RECEIVER_LINK_NAME, role_receiver, source, target)) == NULL)
Azure.IoT Build 7:07bc440836b3 720 {
Azure.IoT Build 7:07bc440836b3 721 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_075: [If IoTHubTransportAMQP_DoWork fails to create the AMQP link for receiving messages, the function shall fail and return immediately, flagging the connection to be re-stablished]
Azure.IoT Build 7:07bc440836b3 722 LogError("Failed creating AMQP link for message receiver.\r\n");
Azure.IoT Build 7:07bc440836b3 723 }
Azure.IoT Build 7:07bc440836b3 724 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_076: [IoTHubTransportAMQP_DoWork shall set the receiver link settle mode as receiver_settle_mode_first]
Azure.IoT Build 7:07bc440836b3 725 else if (link_set_rcv_settle_mode(transport_state->receiver_link, receiver_settle_mode_first) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 726 {
Azure.IoT Build 7:07bc440836b3 727 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_141: [If IoTHubTransportAMQP_DoWork fails to set the settle mode on the AMQP link for receiving messages, the function shall fail and return immediately, flagging the connection to be re-stablished]
Azure.IoT Build 7:07bc440836b3 728 LogError("Failed setting AMQP link settle mode for message receiver.\r\n");
AzureIoTClient 4:57e049bce51e 729 }
AzureIoTClient 4:57e049bce51e 730 else
AzureIoTClient 4:57e049bce51e 731 {
Azure.IoT Build 7:07bc440836b3 732 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_119: [IoTHubTransportAMQP_DoWork shall apply a default value of 65536 for the parameter ‘Link MAX message size’]
Azure.IoT Build 7:07bc440836b3 733 if (link_set_max_message_size(transport_state->receiver_link, MESSAGE_RECEIVER_MAX_LINK_SIZE) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 734 {
Azure.IoT Build 7:07bc440836b3 735 LogError("Failed setting AMQP link max message size for message receiver.\r\n");
Azure.IoT Build 7:07bc440836b3 736 }
Azure.IoT Build 7:07bc440836b3 737
Azure.IoT Build 7:07bc440836b3 738 attachDeviceClientTypeToLink(transport_state->receiver_link);
AzureIoTClient 4:57e049bce51e 739
Azure.IoT Build 7:07bc440836b3 740 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_077: [IoTHubTransportAMQP_DoWork shall create the AMQP message receiver using messagereceiver_create() AMQP API]
Azure.IoT Build 7:07bc440836b3 741 if ((transport_state->message_receiver = messagereceiver_create(transport_state->receiver_link, NULL, NULL)) == NULL)
Azure.IoT Build 7:07bc440836b3 742 {
Azure.IoT Build 7:07bc440836b3 743 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_078: [IoTHubTransportAMQP_DoWork shall fail and return immediately if the AMQP message receiver instance fails to be created, flagging the connection to be re-established]
Azure.IoT Build 7:07bc440836b3 744 LogError("Could not allocate AMQP message receiver.\r\n");
Azure.IoT Build 7:07bc440836b3 745 }
Azure.IoT Build 7:07bc440836b3 746 else
AzureIoTClient 4:57e049bce51e 747 {
Azure.IoT Build 7:07bc440836b3 748 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_079: [IoTHubTransportAMQP_DoWork shall open the AMQP message receiver using messagereceiver_open() AMQP API, passing a callback function for handling C2D incoming messages]
Azure.IoT Build 7:07bc440836b3 749 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_123: [IoTHubTransportAMQP_DoWork shall create each AMQP message_receiver passing the ‘on_message_received’ as the callback function]
Azure.IoT Build 7:07bc440836b3 750 if (messagereceiver_open(transport_state->message_receiver, on_message_received, (const void*)iothub_client_handle) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 751 {
Azure.IoT Build 7:07bc440836b3 752 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_080: [IoTHubTransportAMQP_DoWork shall fail and return immediately if the AMQP message receiver instance fails to be opened, flagging the connection to be re-established]
Azure.IoT Build 7:07bc440836b3 753 LogError("Failed opening the AMQP message receiver.\r\n");
Azure.IoT Build 7:07bc440836b3 754 }
Azure.IoT Build 7:07bc440836b3 755 else
Azure.IoT Build 7:07bc440836b3 756 {
Azure.IoT Build 7:07bc440836b3 757 result = RESULT_OK;
Azure.IoT Build 7:07bc440836b3 758 }
AzureIoTClient 4:57e049bce51e 759 }
AzureIoTClient 4:57e049bce51e 760 }
Azure.IoT Build 7:07bc440836b3 761
Azure.IoT Build 7:07bc440836b3 762 if (source != NULL)
Azure.IoT Build 7:07bc440836b3 763 amqpvalue_destroy(source);
Azure.IoT Build 7:07bc440836b3 764 if (target != NULL)
Azure.IoT Build 7:07bc440836b3 765 amqpvalue_destroy(target);
AzureIoTClient 4:57e049bce51e 766 }
Azure.IoT Build 7:07bc440836b3 767
Azure.IoT Build 7:07bc440836b3 768 return result;
AzureIoTClient 4:57e049bce51e 769 }
AzureIoTClient 4:57e049bce51e 770
Azure.IoT Build 7:07bc440836b3 771 static int sendPendingEvents(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 772 {
Azure.IoT Build 7:07bc440836b3 773 int result = RESULT_OK;
Azure.IoT Build 7:07bc440836b3 774 IOTHUB_MESSAGE_LIST* message = NULL;
Azure.IoT Build 7:07bc440836b3 775
Azure.IoT Build 7:07bc440836b3 776 while ((message = getNextEventToSend(transport_state)) != NULL)
AzureIoTClient 4:57e049bce51e 777 {
Azure.IoT Build 7:07bc440836b3 778 result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 779
Azure.IoT Build 7:07bc440836b3 780 IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(message->messageHandle);
Azure.IoT Build 7:07bc440836b3 781 const unsigned char* messageContent = NULL;
Azure.IoT Build 7:07bc440836b3 782 size_t messageContentSize = 0;
Azure.IoT Build 7:07bc440836b3 783 MESSAGE_HANDLE amqp_message;
Azure.IoT Build 7:07bc440836b3 784 bool is_message_error = false;
Azure.IoT Build 7:07bc440836b3 785 EVENT_TRACKER* event_tracker;
Azure.IoT Build 7:07bc440836b3 786
Azure.IoT Build 7:07bc440836b3 787 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_086: [IoTHubTransportAMQP_DoWork shall move queued events to an “in-progress” list right before processing them for sending]
Azure.IoT Build 7:07bc440836b3 788 if ((event_tracker = trackEvent(message, transport_state)) == NULL)
Azure.IoT Build 7:07bc440836b3 789 {
Azure.IoT Build 7:07bc440836b3 790 LogError("Failed tracking the event to be sent.\r\n");
Azure.IoT Build 7:07bc440836b3 791 }
Azure.IoT Build 7:07bc440836b3 792 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_087: [If the event contains a message of type IOTHUBMESSAGE_BYTEARRAY, IoTHubTransportAMQP_DoWork shall obtain its char* representation and size using IoTHubMessage_GetByteArray()]
Azure.IoT Build 7:07bc440836b3 793 else if (contentType == IOTHUBMESSAGE_BYTEARRAY &&
Azure.IoT Build 7:07bc440836b3 794 IoTHubMessage_GetByteArray(message->messageHandle, &messageContent, &messageContentSize) != IOTHUB_MESSAGE_OK)
AzureIoTClient 4:57e049bce51e 795 {
Azure.IoT Build 7:07bc440836b3 796 LogError("Failed getting the BYTE array representation of the event content to be sent.\r\n");
Azure.IoT Build 7:07bc440836b3 797 is_message_error = true;
Azure.IoT Build 7:07bc440836b3 798 }
Azure.IoT Build 7:07bc440836b3 799 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_089: [If the event contains a message of type IOTHUBMESSAGE_STRING, IoTHubTransportAMQP_DoWork shall obtain its char* representation using IoTHubMessage_GetString()]
Azure.IoT Build 7:07bc440836b3 800 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_090: [If the event contains a message of type IOTHUBMESSAGE_STRING, IoTHubTransportAMQP_DoWork shall obtain the size of its char* representation using strlen()]
Azure.IoT Build 7:07bc440836b3 801 else if (contentType == IOTHUBMESSAGE_STRING &&
Azure.IoT Build 7:07bc440836b3 802 ((messageContent = IoTHubMessage_GetString(message->messageHandle)) == NULL || (messageContentSize = strlen(messageContent)) <= 0))
Azure.IoT Build 7:07bc440836b3 803 {
Azure.IoT Build 7:07bc440836b3 804 LogError("Failed getting the STRING representation of the event content to be sent.\r\n");
Azure.IoT Build 7:07bc440836b3 805 is_message_error = true;
AzureIoTClient 4:57e049bce51e 806 }
Azure.IoT Build 7:07bc440836b3 807 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_092: [If the event contains a message of type IOTHUBMESSAGE_UNKNOWN, IoTHubTransportAMQP_DoWork shall remove the event from the in-progress list and invoke the upper layer callback reporting the error]
Azure.IoT Build 7:07bc440836b3 808 else if (contentType == IOTHUBMESSAGE_UNKNOWN)
AzureIoTClient 4:57e049bce51e 809 {
Azure.IoT Build 7:07bc440836b3 810 LogError("Cannot send events with content type IOTHUBMESSAGE_UNKNOWN.\r\n");
Azure.IoT Build 7:07bc440836b3 811 is_message_error = true;
Azure.IoT Build 7:07bc440836b3 812 }
Azure.IoT Build 7:07bc440836b3 813 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_093: [IoTHubTransportAMQP_DoWork shall create an amqp message using message_create() AMQP API]
Azure.IoT Build 7:07bc440836b3 814 else if ((amqp_message = message_create()) == NULL)
Azure.IoT Build 7:07bc440836b3 815 {
Azure.IoT Build 7:07bc440836b3 816 LogError("Failed allocating the AMQP message for sending the event.\r\n");
AzureIoTClient 4:57e049bce51e 817 }
AzureIoTClient 4:57e049bce51e 818 else
AzureIoTClient 4:57e049bce51e 819 {
Azure.IoT Build 7:07bc440836b3 820 BINARY_DATA binary_data = { messageContent, messageContentSize };
Azure.IoT Build 7:07bc440836b3 821
Azure.IoT Build 7:07bc440836b3 822 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_095: [IoTHubTransportAMQP_DoWork shall set the AMQP message body using message_add_body_amqp_data() AMQP API]
Azure.IoT Build 7:07bc440836b3 823 if (message_add_body_amqp_data(amqp_message, binary_data) != RESULT_OK)
AzureIoTClient 4:57e049bce51e 824 {
Azure.IoT Build 7:07bc440836b3 825 LogError("Failed setting the body of the AMQP message.\r\n");
AzureIoTClient 4:57e049bce51e 826 }
Azure.IoT Build 7:07bc440836b3 827 else
AzureIoTClient 4:57e049bce51e 828 {
Azure.IoT Build 7:07bc440836b3 829 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_097: [IoTHubTransportAMQP_DoWork shall pass the encoded AMQP message to AMQP for sending (along with on_message_send_complete callback) using messagesender_send()]
Azure.IoT Build 7:07bc440836b3 830 if (messagesender_send(transport_state->message_sender, amqp_message, on_message_send_complete, (const void*)event_tracker) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 831 {
Azure.IoT Build 7:07bc440836b3 832 LogError("Failed sending the AMQP message.\r\n");
Azure.IoT Build 7:07bc440836b3 833 }
Azure.IoT Build 7:07bc440836b3 834 else
Azure.IoT Build 7:07bc440836b3 835 {
Azure.IoT Build 7:07bc440836b3 836 result = RESULT_OK;
Azure.IoT Build 7:07bc440836b3 837 }
AzureIoTClient 4:57e049bce51e 838 }
Azure.IoT Build 7:07bc440836b3 839 }
Azure.IoT Build 7:07bc440836b3 840
Azure.IoT Build 7:07bc440836b3 841 if (amqp_message != NULL)
Azure.IoT Build 7:07bc440836b3 842 {
Azure.IoT Build 7:07bc440836b3 843 // It can be destroyed because AMQP keeps a clone of the message.
Azure.IoT Build 7:07bc440836b3 844 message_destroy(amqp_message);
Azure.IoT Build 7:07bc440836b3 845 }
Azure.IoT Build 7:07bc440836b3 846
Azure.IoT Build 7:07bc440836b3 847 if (result != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 848 {
Azure.IoT Build 7:07bc440836b3 849 if (event_tracker == NULL)
AzureIoTClient 5:8d58d20699dd 850 {
AzureIoTClient 5:8d58d20699dd 851 break;
AzureIoTClient 5:8d58d20699dd 852 }
AzureIoTClient 4:57e049bce51e 853 else
AzureIoTClient 4:57e049bce51e 854 {
Azure.IoT Build 7:07bc440836b3 855 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_088: [If IoTHubMessage_GetByteArray() fails, IoTHubTransportAMQP_DoWork shall remove the event from the in-progress list and invoke the upper layer callback reporting the error]
Azure.IoT Build 7:07bc440836b3 856 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_091: [If IoTHubMessage_GetString() fails, IoTHubTransportAMQP_DoWork shall remove the event from the in-progress list and invoke the upper layer callback reporting the error]
Azure.IoT Build 7:07bc440836b3 857 if (is_message_error)
AzureIoTClient 4:57e049bce51e 858 {
Azure.IoT Build 7:07bc440836b3 859 on_message_send_complete(event_tracker, MESSAGE_SEND_ERROR);
AzureIoTClient 4:57e049bce51e 860 }
AzureIoTClient 4:57e049bce51e 861 else
AzureIoTClient 4:57e049bce51e 862 {
Azure.IoT Build 7:07bc440836b3 863 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_111: [If message_create() fails, IoTHubTransportAMQP_DoWork notify the failure, roll back the event to waitToSent list and return]
Azure.IoT Build 7:07bc440836b3 864 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_112: [If message_add_body_amqp_data() fails, IoTHubTransportAMQP_DoWork notify the failure, roll back the event to waitToSent list and return]
Azure.IoT Build 7:07bc440836b3 865 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_113: [If messagesender_send() fails, IoTHubTransportAMQP_DoWork notify the failure, roll back the event to waitToSent list and return]
Azure.IoT Build 7:07bc440836b3 866 rollEventBackToWaitList(event_tracker, transport_state);
Azure.IoT Build 7:07bc440836b3 867 break;
AzureIoTClient 4:57e049bce51e 868 }
AzureIoTClient 4:57e049bce51e 869 }
AzureIoTClient 4:57e049bce51e 870 }
AzureIoTClient 4:57e049bce51e 871 }
Azure.IoT Build 7:07bc440836b3 872
Azure.IoT Build 7:07bc440836b3 873 return result;
Azure.IoT Build 7:07bc440836b3 874 }
Azure.IoT Build 7:07bc440836b3 875
Azure.IoT Build 7:07bc440836b3 876 static bool isSasTokenRefreshRequired(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 877 {
Azure.IoT Build 7:07bc440836b3 878 return ((getSecondsSinceEpoch() - transport_state->current_sas_token_create_time) >= (transport_state->sas_token_refresh_time / 1000)) ? true : false;
Azure.IoT Build 7:07bc440836b3 879 }
Azure.IoT Build 7:07bc440836b3 880
Azure.IoT Build 7:07bc440836b3 881 static void prepareForConnectionRetry(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 882 {
Azure.IoT Build 7:07bc440836b3 883 destroyConnection(transport_state);
Azure.IoT Build 7:07bc440836b3 884 rollEventsBackToWaitList(transport_state);
AzureIoTClient 4:57e049bce51e 885 }
AzureIoTClient 4:57e049bce51e 886
Azure.IoT Build 7:07bc440836b3 887
Azure.IoT Build 7:07bc440836b3 888 // API functions
Azure.IoT Build 7:07bc440836b3 889
Azure.IoT Build 7:07bc440836b3 890 static TRANSPORT_HANDLE IoTHubTransportAMQP_Create(const IOTHUBTRANSPORT_CONFIG* config)
AzureIoTClient 4:57e049bce51e 891 {
Azure.IoT Build 7:07bc440836b3 892 AMQP_TRANSPORT_INSTANCE* transport_state = NULL;
Azure.IoT Build 7:07bc440836b3 893 bool cleanup_required = false;
Azure.IoT Build 7:07bc440836b3 894 int deviceIdLength = -1;
AzureIoTClient 4:57e049bce51e 895
Azure.IoT Build 7:07bc440836b3 896 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_005: [If parameter config (or its fields) is NULL then IoTHubTransportAMQP_Create shall fail and return NULL.]
Azure.IoT Build 7:07bc440836b3 897 if (config == NULL || config->upperConfig == NULL || config->waitingToSend == NULL)
Azure.IoT Build 7:07bc440836b3 898 {
Azure.IoT Build 7:07bc440836b3 899 LogError("IoTHub AMQP client transport null configuration parameter.\r\n");
Azure.IoT Build 7:07bc440836b3 900 }
Azure.IoT Build 7:07bc440836b3 901 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_006: [IoTHubTransportAMQP_Create shall fail and return NULL if any fields of the config structure are NULL.]
Azure.IoT Build 7:07bc440836b3 902 else if (config->upperConfig->protocol == NULL)
Azure.IoT Build 7:07bc440836b3 903 {
Azure.IoT Build 7:07bc440836b3 904 LogError("Invalid configuration (NULL protocol detected)\r\n");
Azure.IoT Build 7:07bc440836b3 905 }
Azure.IoT Build 7:07bc440836b3 906 else if (config->upperConfig->deviceId == NULL)
Azure.IoT Build 7:07bc440836b3 907 {
Azure.IoT Build 7:07bc440836b3 908 LogError("Invalid configuration (NULL deviceId detected)\r\n");
Azure.IoT Build 7:07bc440836b3 909 }
Azure.IoT Build 7:07bc440836b3 910 else if (config->upperConfig->deviceKey == NULL)
Azure.IoT Build 7:07bc440836b3 911 {
Azure.IoT Build 7:07bc440836b3 912 LogError("Invalid configuration (NULL deviceKey detected)\r\n");
Azure.IoT Build 7:07bc440836b3 913 }
Azure.IoT Build 7:07bc440836b3 914 else if (config->upperConfig->iotHubName == NULL)
Azure.IoT Build 7:07bc440836b3 915 {
Azure.IoT Build 7:07bc440836b3 916 LogError("Invalid configuration (NULL iotHubName detected)\r\n");
AzureIoTClient 4:57e049bce51e 917 }
Azure.IoT Build 7:07bc440836b3 918 else if (config->upperConfig->iotHubSuffix == NULL)
Azure.IoT Build 7:07bc440836b3 919 {
Azure.IoT Build 7:07bc440836b3 920 LogError("Invalid configuration (NULL iotHubSuffix detected)\r\n");
Azure.IoT Build 7:07bc440836b3 921 }
Azure.IoT Build 7:07bc440836b3 922 else if (!config->waitingToSend)
AzureIoTClient 4:57e049bce51e 923 {
Azure.IoT Build 7:07bc440836b3 924 LogError("Invalid configuration (NULL waitingToSend list detected)\r\n");
Azure.IoT Build 7:07bc440836b3 925 }
Azure.IoT Build 7:07bc440836b3 926 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_008: [IoTHubTransportAMQP_Create shall fail and return NULL if any config field of type string is zero length.]
Azure.IoT Build 7:07bc440836b3 927 else if ((deviceIdLength = strlen(config->upperConfig->deviceId)) == 0 ||
Azure.IoT Build 7:07bc440836b3 928 (strlen(config->upperConfig->deviceKey) == 0) ||
Azure.IoT Build 7:07bc440836b3 929 (strlen(config->upperConfig->iotHubName) == 0) ||
Azure.IoT Build 7:07bc440836b3 930 (strlen(config->upperConfig->iotHubSuffix) == 0))
Azure.IoT Build 7:07bc440836b3 931 {
Azure.IoT Build 7:07bc440836b3 932 LogError("Zero-length config parameter (deviceId, deviceKey, iotHubName or iotHubSuffix)\r\n");
Azure.IoT Build 7:07bc440836b3 933 }
Azure.IoT Build 7:07bc440836b3 934 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_007: [IoTHubTransportAMQP_Create shall fail and return NULL if the deviceId length is greater than 128.]
Azure.IoT Build 7:07bc440836b3 935 else if (deviceIdLength > 128U)
Azure.IoT Build 7:07bc440836b3 936 {
Azure.IoT Build 7:07bc440836b3 937 LogError("deviceId is too long\r\n");
Azure.IoT Build 7:07bc440836b3 938 }
Azure.IoT Build 7:07bc440836b3 939 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_134: [IoTHubTransportAMQP_Create shall fail and return NULL if the combined length of config->iotHubName and config->iotHubSuffix exceeds 254 bytes (RFC1035)]
Azure.IoT Build 7:07bc440836b3 940 else if ((strlen(config->upperConfig->iotHubName) + strlen(config->upperConfig->iotHubSuffix)) > (RFC1035_MAX_FQDN_LENGTH - 1))
Azure.IoT Build 7:07bc440836b3 941 {
Azure.IoT Build 7:07bc440836b3 942 LogError("The lengths of iotHubName and iotHubSuffix together exceed the maximum FQDN length allowed (RFC 1035)\r\n");
AzureIoTClient 4:57e049bce51e 943 }
AzureIoTClient 4:57e049bce51e 944 else
AzureIoTClient 4:57e049bce51e 945 {
Azure.IoT Build 7:07bc440836b3 946 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_009: [IoTHubTransportAMQP_Create shall fail and return NULL if memory allocation of the transport’s internal state structure fails.]
Azure.IoT Build 7:07bc440836b3 947 transport_state = (AMQP_TRANSPORT_INSTANCE*)malloc(sizeof(AMQP_TRANSPORT_INSTANCE));
AzureIoTClient 4:57e049bce51e 948
Azure.IoT Build 7:07bc440836b3 949 if (transport_state == NULL)
AzureIoTClient 4:57e049bce51e 950 {
AzureIoTClient 4:57e049bce51e 951 LogError("Could not allocate AMQP transport state\r\n");
AzureIoTClient 4:57e049bce51e 952 }
AzureIoTClient 4:57e049bce51e 953 else
AzureIoTClient 4:57e049bce51e 954 {
Azure.IoT Build 7:07bc440836b3 955 transport_state->iotHubHostFqdn = NULL;
Azure.IoT Build 7:07bc440836b3 956 transport_state->iotHubPort = DEFAULT_IOTHUB_AMQP_PORT;
Azure.IoT Build 7:07bc440836b3 957 transport_state->trusted_certificates = NULL;
Azure.IoT Build 7:07bc440836b3 958 transport_state->deviceKey = NULL;
Azure.IoT Build 7:07bc440836b3 959 transport_state->devicesPath = NULL;
Azure.IoT Build 7:07bc440836b3 960 transport_state->messageReceiveAddress = NULL;
Azure.IoT Build 7:07bc440836b3 961 transport_state->sasTokenKeyName = NULL;
Azure.IoT Build 7:07bc440836b3 962 transport_state->targetAddress = NULL;
Azure.IoT Build 7:07bc440836b3 963 transport_state->waitingToSend = config->waitingToSend;
Azure.IoT Build 7:07bc440836b3 964
Azure.IoT Build 7:07bc440836b3 965 transport_state->cbs = NULL;
Azure.IoT Build 7:07bc440836b3 966 transport_state->cbs_state = CBS_STATE_IDLE;
Azure.IoT Build 7:07bc440836b3 967 transport_state->current_sas_token_create_time = 0;
Azure.IoT Build 7:07bc440836b3 968 transport_state->connection = NULL;
Azure.IoT Build 7:07bc440836b3 969 transport_state->connection_state = AMQP_MANAGEMENT_STATE_IDLE;
Azure.IoT Build 7:07bc440836b3 970 transport_state->connection_establish_time = 0;
Azure.IoT Build 7:07bc440836b3 971 transport_state->iothub_client_handle = NULL;
Azure.IoT Build 7:07bc440836b3 972 transport_state->receive_messages = false;
Azure.IoT Build 7:07bc440836b3 973 transport_state->message_receiver = NULL;
Azure.IoT Build 7:07bc440836b3 974 transport_state->message_sender = NULL;
Azure.IoT Build 7:07bc440836b3 975 transport_state->receiver_link = NULL;
Azure.IoT Build 7:07bc440836b3 976 transport_state->sasl_io = NULL;
Azure.IoT Build 7:07bc440836b3 977 transport_state->sasl_mechanism = NULL;
Azure.IoT Build 7:07bc440836b3 978 transport_state->sender_link = NULL;
Azure.IoT Build 7:07bc440836b3 979 transport_state->session = NULL;
Azure.IoT Build 7:07bc440836b3 980 transport_state->tls_io = NULL;
Azure.IoT Build 7:07bc440836b3 981 transport_state->tls_io_transport_provider = getTLSIOTransport;
Azure.IoT Build 7:07bc440836b3 982
Azure.IoT Build 7:07bc440836b3 983 transport_state->waitingToSend = config->waitingToSend;
Azure.IoT Build 7:07bc440836b3 984 DList_InitializeListHead(&transport_state->inProgress);
Azure.IoT Build 7:07bc440836b3 985
Azure.IoT Build 7:07bc440836b3 986 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_010: [IoTHubTransportAMQP_Create shall create an immutable string, referred to as iotHubHostFqdn, from the following pieces: config->iotHubName + "." + config->iotHubSuffix.]
Azure.IoT Build 7:07bc440836b3 987 if ((transport_state->iotHubHostFqdn = concat3Params(config->upperConfig->iotHubName, ".", config->upperConfig->iotHubSuffix)) == NULL)
AzureIoTClient 4:57e049bce51e 988 {
Azure.IoT Build 7:07bc440836b3 989 LogError("Failed to set transport_state->iotHubHostFqdn.\r\n");
Azure.IoT Build 7:07bc440836b3 990 cleanup_required = true;
AzureIoTClient 4:57e049bce51e 991 }
Azure.IoT Build 7:07bc440836b3 992 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_012: [IoTHubTransportAMQP_Create shall create an immutable string, referred to as devicesPath, from the following parts: host_fqdn + “/devices/” + deviceId.]
Azure.IoT Build 7:07bc440836b3 993 else if ((transport_state->devicesPath = concat3Params(STRING_c_str(transport_state->iotHubHostFqdn), "/devices/", config->upperConfig->deviceId)) == NULL)
AzureIoTClient 4:57e049bce51e 994 {
Azure.IoT Build 7:07bc440836b3 995 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_013: [If creating devicesPath fails for any reason then IoTHubTransportAMQP_Create shall fail and return NULL.]
Azure.IoT Build 7:07bc440836b3 996 LogError("Failed to allocate transport_state->devicesPath.\r\n");
Azure.IoT Build 7:07bc440836b3 997 cleanup_required = true;
Azure.IoT Build 7:07bc440836b3 998 }
Azure.IoT Build 7:07bc440836b3 999 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_014: [IoTHubTransportAMQP_Create shall create an immutable string, referred to as targetAddress, from the following parts: "amqps://" + devicesPath + "/messages/events".]
Azure.IoT Build 7:07bc440836b3 1000 else if ((transport_state->targetAddress = concat3Params("amqps://", STRING_c_str(transport_state->devicesPath), "/messages/events")) == NULL)
Azure.IoT Build 7:07bc440836b3 1001 {
Azure.IoT Build 7:07bc440836b3 1002 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_015: [If creating the targetAddress fails for any reason then IoTHubTransportAMQP_Create shall fail and return NULL.]
Azure.IoT Build 7:07bc440836b3 1003 LogError("Failed to allocate transport_state->targetAddress.\r\n");
Azure.IoT Build 7:07bc440836b3 1004 cleanup_required = true;
Azure.IoT Build 7:07bc440836b3 1005 }
Azure.IoT Build 7:07bc440836b3 1006 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_053: [IoTHubTransportAMQP_Create shall define the source address for receiving messages as "amqps://" + devicesPath + "/messages/devicebound", stored in the transport handle as messageReceiveAddress]
Azure.IoT Build 7:07bc440836b3 1007 else if ((transport_state->messageReceiveAddress = concat3Params("amqps://", STRING_c_str(transport_state->devicesPath), "/messages/devicebound")) == NULL)
Azure.IoT Build 7:07bc440836b3 1008 {
Azure.IoT Build 7:07bc440836b3 1009 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_054: [If creating the messageReceiveAddress fails for any reason then IoTHubTransportAMQP_Create shall fail and return NULL.]
Azure.IoT Build 7:07bc440836b3 1010 LogError("Failed to allocate transport_state->messageReceiveAddress.\r\n");
Azure.IoT Build 7:07bc440836b3 1011 cleanup_required = true;
Azure.IoT Build 7:07bc440836b3 1012 }
Azure.IoT Build 7:07bc440836b3 1013 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_016: [IoTHubTransportAMQP_Create shall initialize handle->sasTokenKeyName with a zero-length STRING_HANDLE instance.]
Azure.IoT Build 7:07bc440836b3 1014 else if ((transport_state->sasTokenKeyName = STRING_new()) == NULL)
Azure.IoT Build 7:07bc440836b3 1015 {
Azure.IoT Build 7:07bc440836b3 1016 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_017: [If IoTHubTransportAMQP_Create fails to initialize handle->sasTokenKeyName with a zero-length STRING the function shall fail and return NULL.]
Azure.IoT Build 7:07bc440836b3 1017 LogError("Failed to allocate transport_state->sasTokenKeyName.\r\n");
Azure.IoT Build 7:07bc440836b3 1018 cleanup_required = true;
Azure.IoT Build 7:07bc440836b3 1019 }
Azure.IoT Build 7:07bc440836b3 1020 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_018: [IoTHubTransportAMQP_Create shall store a copy of config->deviceKey (passed by upper layer) into the transport’s own deviceKey field]
Azure.IoT Build 7:07bc440836b3 1021 else if ((transport_state->deviceKey = STRING_new()) == NULL ||
Azure.IoT Build 7:07bc440836b3 1022 STRING_copy(transport_state->deviceKey, config->upperConfig->deviceKey) != 0)
Azure.IoT Build 7:07bc440836b3 1023 {
Azure.IoT Build 7:07bc440836b3 1024 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_019: [If IoTHubTransportAMQP_Create fails to copy config->deviceKey, the function shall fail and return NULL.]
Azure.IoT Build 7:07bc440836b3 1025 LogError("Failed to allocate transport_state->deviceKey.\r\n");
Azure.IoT Build 7:07bc440836b3 1026 cleanup_required = true;
Azure.IoT Build 7:07bc440836b3 1027 }
Azure.IoT Build 7:07bc440836b3 1028 else
Azure.IoT Build 7:07bc440836b3 1029 {
Azure.IoT Build 7:07bc440836b3 1030 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_020: [IoTHubTransportAMQP_Create shall set parameter transport_state->sas_token_lifetime with the default value of 3600000 (milliseconds).]
Azure.IoT Build 7:07bc440836b3 1031 transport_state->sas_token_lifetime = DEFAULT_SAS_TOKEN_LIFETIME_MS;
Azure.IoT Build 7:07bc440836b3 1032
Azure.IoT Build 7:07bc440836b3 1033 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_128: [IoTHubTransportAMQP_Create shall set parameter transport_state->sas_token_refresh_time with the default value of sas_token_lifetime/2 (milliseconds).]
Azure.IoT Build 7:07bc440836b3 1034 transport_state->sas_token_refresh_time = transport_state->sas_token_lifetime / 2;
Azure.IoT Build 7:07bc440836b3 1035
Azure.IoT Build 7:07bc440836b3 1036 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_129 : [IoTHubTransportAMQP_Create shall set parameter transport_state->cbs_request_timeout with the default value of 30000 (milliseconds).]
Azure.IoT Build 7:07bc440836b3 1037 transport_state->cbs_request_timeout = DEFAULT_CBS_REQUEST_TIMEOUT_MS;
Azure.IoT Build 7:07bc440836b3 1038
Azure.IoT Build 7:07bc440836b3 1039 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_130 : [IoTHubTransportAMQP_Create shall set parameter transport_state->message_send_timeout with the default value of 300000 (milliseconds).]
Azure.IoT Build 7:07bc440836b3 1040 transport_state->message_send_timeout = DEFAULT_MESSAGE_SEND_TIMEOUT_MS;
AzureIoTClient 4:57e049bce51e 1041 }
AzureIoTClient 4:57e049bce51e 1042 }
AzureIoTClient 4:57e049bce51e 1043 }
Azure.IoT Build 7:07bc440836b3 1044
Azure.IoT Build 7:07bc440836b3 1045 if (cleanup_required)
Azure.IoT Build 7:07bc440836b3 1046 {
Azure.IoT Build 7:07bc440836b3 1047 if (transport_state->deviceKey != NULL)
Azure.IoT Build 7:07bc440836b3 1048 STRING_delete(transport_state->deviceKey);
Azure.IoT Build 7:07bc440836b3 1049 if (transport_state->sasTokenKeyName != NULL)
Azure.IoT Build 7:07bc440836b3 1050 STRING_delete(transport_state->sasTokenKeyName);
Azure.IoT Build 7:07bc440836b3 1051 if (transport_state->targetAddress != NULL)
Azure.IoT Build 7:07bc440836b3 1052 STRING_delete(transport_state->targetAddress);
Azure.IoT Build 7:07bc440836b3 1053 if (transport_state->messageReceiveAddress != NULL)
Azure.IoT Build 7:07bc440836b3 1054 STRING_delete(transport_state->messageReceiveAddress);
Azure.IoT Build 7:07bc440836b3 1055 if (transport_state->devicesPath != NULL)
Azure.IoT Build 7:07bc440836b3 1056 STRING_delete(transport_state->devicesPath);
Azure.IoT Build 7:07bc440836b3 1057 if (transport_state->iotHubHostFqdn != NULL)
Azure.IoT Build 7:07bc440836b3 1058 STRING_delete(transport_state->iotHubHostFqdn);
Azure.IoT Build 7:07bc440836b3 1059
Azure.IoT Build 7:07bc440836b3 1060 free(transport_state);
Azure.IoT Build 7:07bc440836b3 1061 transport_state = NULL;
Azure.IoT Build 7:07bc440836b3 1062 }
Azure.IoT Build 7:07bc440836b3 1063
Azure.IoT Build 7:07bc440836b3 1064 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_023: [If IoTHubTransportAMQP_Create succeeds it shall return a non-NULL pointer to the structure that represents the transport.]
Azure.IoT Build 7:07bc440836b3 1065 return transport_state;
AzureIoTClient 4:57e049bce51e 1066 }
AzureIoTClient 4:57e049bce51e 1067
Azure.IoT Build 7:07bc440836b3 1068 static void IoTHubTransportAMQP_Destroy(TRANSPORT_HANDLE handle)
AzureIoTClient 4:57e049bce51e 1069 {
Azure.IoT Build 7:07bc440836b3 1070 if (handle != NULL)
Azure.IoT Build 7:07bc440836b3 1071 {
Azure.IoT Build 7:07bc440836b3 1072 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
Azure.IoT Build 7:07bc440836b3 1073
Azure.IoT Build 7:07bc440836b3 1074 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_024: [IoTHubTransportAMQP_Destroy shall destroy the AMQP message_sender.]
Azure.IoT Build 7:07bc440836b3 1075 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_029 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP link.]
Azure.IoT Build 7:07bc440836b3 1076 destroyEventSender(transport_state);
Azure.IoT Build 7:07bc440836b3 1077
Azure.IoT Build 7:07bc440836b3 1078 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_025: [IoTHubTransportAMQP_Destroy shall destroy the AMQP message_receiver.]
Azure.IoT Build 7:07bc440836b3 1079 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_029 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP link.]
Azure.IoT Build 7:07bc440836b3 1080 destroyMessageReceiver(transport_state);
Azure.IoT Build 7:07bc440836b3 1081
Azure.IoT Build 7:07bc440836b3 1082 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_027 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP cbs instance]
Azure.IoT Build 7:07bc440836b3 1083 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_030 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP session.]
Azure.IoT Build 7:07bc440836b3 1084 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_031 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP connection.]
Azure.IoT Build 7:07bc440836b3 1085 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_032 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP SASL I / O transport.]
Azure.IoT Build 7:07bc440836b3 1086 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_033 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP SASL mechanism.]
Azure.IoT Build 7:07bc440836b3 1087 destroyConnection(transport_state);
Azure.IoT Build 7:07bc440836b3 1088
Azure.IoT Build 7:07bc440836b3 1089 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_035 : [IoTHubTransportAMQP_Destroy shall delete its internally - set parameters(deviceKey, targetAddress, devicesPath, sasTokenKeyName).]
Azure.IoT Build 7:07bc440836b3 1090 STRING_delete(transport_state->targetAddress);
Azure.IoT Build 7:07bc440836b3 1091 STRING_delete(transport_state->messageReceiveAddress);
Azure.IoT Build 7:07bc440836b3 1092 STRING_delete(transport_state->sasTokenKeyName);
Azure.IoT Build 7:07bc440836b3 1093 STRING_delete(transport_state->deviceKey);
Azure.IoT Build 7:07bc440836b3 1094 STRING_delete(transport_state->devicesPath);
Azure.IoT Build 7:07bc440836b3 1095 STRING_delete(transport_state->iotHubHostFqdn);
Azure.IoT Build 7:07bc440836b3 1096
Azure.IoT Build 7:07bc440836b3 1097 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_036 : [IoTHubTransportAMQP_Destroy shall return the remaining items in inProgress to waitingToSend list.]
Azure.IoT Build 7:07bc440836b3 1098 rollEventsBackToWaitList(transport_state);
Azure.IoT Build 7:07bc440836b3 1099
Azure.IoT Build 7:07bc440836b3 1100 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_150: [IoTHubTransportAMQP_Destroy shall destroy the transport instance]
Azure.IoT Build 7:07bc440836b3 1101 free(transport_state);
Azure.IoT Build 7:07bc440836b3 1102 }
Azure.IoT Build 7:07bc440836b3 1103 }
Azure.IoT Build 7:07bc440836b3 1104
Azure.IoT Build 7:07bc440836b3 1105 static void IoTHubTransportAMQP_DoWork(TRANSPORT_HANDLE handle, IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle)
Azure.IoT Build 7:07bc440836b3 1106 {
Azure.IoT Build 7:07bc440836b3 1107 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_051: [IoTHubTransportAMQP_DoWork shall fail and return immediately if the transport handle parameter is NULL]
AzureIoTClient 4:57e049bce51e 1108 if (handle == NULL)
AzureIoTClient 4:57e049bce51e 1109 {
Azure.IoT Build 7:07bc440836b3 1110 LogError("IoTHubClient DoWork failed: transport handle parameter is NULL.\r\n");
Azure.IoT Build 7:07bc440836b3 1111 }
Azure.IoT Build 7:07bc440836b3 1112 // Codes_[IoTHubTransportAMQP_DoWork shall fail and return immediately if the client handle parameter is NULL]
Azure.IoT Build 7:07bc440836b3 1113 else if (iotHubClientHandle == NULL)
Azure.IoT Build 7:07bc440836b3 1114 {
Azure.IoT Build 7:07bc440836b3 1115 LogError("IoTHubClient DoWork failed: client handle parameter is NULL.\r\n");
AzureIoTClient 4:57e049bce51e 1116 }
AzureIoTClient 4:57e049bce51e 1117 else
AzureIoTClient 4:57e049bce51e 1118 {
Azure.IoT Build 7:07bc440836b3 1119 bool trigger_connection_retry = false;
Azure.IoT Build 7:07bc440836b3 1120 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
Azure.IoT Build 7:07bc440836b3 1121
Azure.IoT Build 7:07bc440836b3 1122 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_147: [IoTHubTransportAMQP_DoWork shall save a reference to the client handle in transport_state->iothub_client_handle]
Azure.IoT Build 7:07bc440836b3 1123 transport_state->iothub_client_handle = iotHubClientHandle;
Azure.IoT Build 7:07bc440836b3 1124
Azure.IoT Build 7:07bc440836b3 1125 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_055: [If the transport handle has a NULL connection, IoTHubTransportAMQP_DoWork shall instantiate and initialize the AMQP components and establish the connection]
Azure.IoT Build 7:07bc440836b3 1126 if (transport_state->connection == NULL &&
Azure.IoT Build 7:07bc440836b3 1127 establishConnection(transport_state) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1128 {
Azure.IoT Build 7:07bc440836b3 1129 LogError("AMQP transport failed to establish connection with service.\r\n");
Azure.IoT Build 7:07bc440836b3 1130 trigger_connection_retry = true;
Azure.IoT Build 7:07bc440836b3 1131 }
Azure.IoT Build 7:07bc440836b3 1132 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_081: [IoTHubTransportAMQP_DoWork shall put a new SAS token if the one has not been out already, or if the previous one failed to be put due to timeout of cbs_put_token().]
Azure.IoT Build 7:07bc440836b3 1133 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_082: [IoTHubTransportAMQP_DoWork shall refresh the SAS token if the current token has been used for more than ‘sas_token_refresh_time’ milliseconds]
Azure.IoT Build 7:07bc440836b3 1134 else if ((transport_state->cbs_state == CBS_STATE_IDLE || isSasTokenRefreshRequired(transport_state)) &&
Azure.IoT Build 7:07bc440836b3 1135 startAuthentication(transport_state) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1136 {
Azure.IoT Build 7:07bc440836b3 1137 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_146: [If the SAS token fails to be sent to CBS (cbs_put_token), IoTHubTransportAMQP_DoWork shall fail and exit immediately]
Azure.IoT Build 7:07bc440836b3 1138 LogError("Failed authenticating AMQP connection within CBS.\r\n");
Azure.IoT Build 7:07bc440836b3 1139 trigger_connection_retry = true;
Azure.IoT Build 7:07bc440836b3 1140 }
Azure.IoT Build 7:07bc440836b3 1141 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_084: [IoTHubTransportAMQP_DoWork shall wait for ‘cbs_request_timeout’ milliseconds for the cbs_put_token() to complete before failing due to timeout]
Azure.IoT Build 7:07bc440836b3 1142 else if (transport_state->cbs_state == CBS_STATE_AUTH_IN_PROGRESS &&
Azure.IoT Build 7:07bc440836b3 1143 verifyAuthenticationTimeout(transport_state) == RESULT_TIMEOUT)
Azure.IoT Build 7:07bc440836b3 1144 {
Azure.IoT Build 7:07bc440836b3 1145 LogError("AMQP transport authentication timed out.\r\n");
Azure.IoT Build 7:07bc440836b3 1146 trigger_connection_retry = true;
Azure.IoT Build 7:07bc440836b3 1147 }
Azure.IoT Build 7:07bc440836b3 1148 else if (transport_state->cbs_state == CBS_STATE_AUTHENTICATED)
Azure.IoT Build 7:07bc440836b3 1149 {
Azure.IoT Build 7:07bc440836b3 1150 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_121: [IoTHubTransportAMQP_DoWork shall create an AMQP message_receiver if transport_state->message_receive is NULL and transport_state->receive_messages is true]
Azure.IoT Build 7:07bc440836b3 1151 if (transport_state->receive_messages == true &&
Azure.IoT Build 7:07bc440836b3 1152 transport_state->message_receiver == NULL &&
Azure.IoT Build 7:07bc440836b3 1153 createMessageReceiver(transport_state, iotHubClientHandle) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1154 {
Azure.IoT Build 7:07bc440836b3 1155 LogError("Failed creating AMQP transport message receiver.\r\n");
Azure.IoT Build 7:07bc440836b3 1156 trigger_connection_retry = true;
Azure.IoT Build 7:07bc440836b3 1157 }
Azure.IoT Build 7:07bc440836b3 1158 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_122: [IoTHubTransportAMQP_DoWork shall destroy the transport_state->message_receiver (and set it to NULL) if it exists and transport_state->receive_messages is false]
Azure.IoT Build 7:07bc440836b3 1159 else if (transport_state->receive_messages == false &&
Azure.IoT Build 7:07bc440836b3 1160 transport_state->message_receiver != NULL &&
Azure.IoT Build 7:07bc440836b3 1161 destroyMessageReceiver(transport_state) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1162 {
Azure.IoT Build 7:07bc440836b3 1163 LogError("Failed destroying AMQP transport message receiver.\r\n");
Azure.IoT Build 7:07bc440836b3 1164 }
Azure.IoT Build 7:07bc440836b3 1165
Azure.IoT Build 7:07bc440836b3 1166 if (transport_state->message_sender == NULL &&
Azure.IoT Build 7:07bc440836b3 1167 createEventSender(transport_state) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1168 {
Azure.IoT Build 7:07bc440836b3 1169 LogError("Failed creating AMQP transport event sender.\r\n");
Azure.IoT Build 7:07bc440836b3 1170 trigger_connection_retry = true;
Azure.IoT Build 7:07bc440836b3 1171 }
Azure.IoT Build 7:07bc440836b3 1172 else if (sendPendingEvents(transport_state) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1173 {
Azure.IoT Build 7:07bc440836b3 1174 LogError("AMQP transport failed sending events.\r\n");
Azure.IoT Build 7:07bc440836b3 1175 trigger_connection_retry = true;
Azure.IoT Build 7:07bc440836b3 1176 }
Azure.IoT Build 7:07bc440836b3 1177 }
Azure.IoT Build 7:07bc440836b3 1178
Azure.IoT Build 7:07bc440836b3 1179 if (trigger_connection_retry)
Azure.IoT Build 7:07bc440836b3 1180 {
Azure.IoT Build 7:07bc440836b3 1181 prepareForConnectionRetry(transport_state);
Azure.IoT Build 7:07bc440836b3 1182 }
Azure.IoT Build 7:07bc440836b3 1183 else
Azure.IoT Build 7:07bc440836b3 1184 {
Azure.IoT Build 7:07bc440836b3 1185 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_103: [IoTHubTransportAMQP_DoWork shall invoke connection_dowork() on AMQP for triggering sending and receiving messages]
Azure.IoT Build 7:07bc440836b3 1186 connection_dowork(transport_state->connection);
Azure.IoT Build 7:07bc440836b3 1187 }
Azure.IoT Build 7:07bc440836b3 1188
Azure.IoT Build 7:07bc440836b3 1189 handleEventSendTimeouts(transport_state);
Azure.IoT Build 7:07bc440836b3 1190 }
Azure.IoT Build 7:07bc440836b3 1191 }
Azure.IoT Build 7:07bc440836b3 1192
Azure.IoT Build 7:07bc440836b3 1193 static int IoTHubTransportAMQP_Subscribe(TRANSPORT_HANDLE handle)
Azure.IoT Build 7:07bc440836b3 1194 {
Azure.IoT Build 7:07bc440836b3 1195 int result;
Azure.IoT Build 7:07bc440836b3 1196
Azure.IoT Build 7:07bc440836b3 1197 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_037: [IoTHubTransportAMQP_Subscribe shall fail if the transport handle parameter received is NULL.]
Azure.IoT Build 7:07bc440836b3 1198 if (handle == NULL)
Azure.IoT Build 7:07bc440836b3 1199 {
Azure.IoT Build 7:07bc440836b3 1200 LogError("Invalid handle to IoTHubClient AMQP transport.\r\n");
Azure.IoT Build 7:07bc440836b3 1201 result = __LINE__;
Azure.IoT Build 7:07bc440836b3 1202 }
Azure.IoT Build 7:07bc440836b3 1203 else
Azure.IoT Build 7:07bc440836b3 1204 {
Azure.IoT Build 7:07bc440836b3 1205 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_038: [IoTHubTransportAMQP_Subscribe shall set transport_handle->receive_messages to true and return success code.]
Azure.IoT Build 7:07bc440836b3 1206 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
Azure.IoT Build 7:07bc440836b3 1207 transport_state->receive_messages = true;
AzureIoTClient 4:57e049bce51e 1208 result = 0;
AzureIoTClient 4:57e049bce51e 1209 }
Azure.IoT Build 7:07bc440836b3 1210
AzureIoTClient 4:57e049bce51e 1211 return result;
AzureIoTClient 4:57e049bce51e 1212 }
AzureIoTClient 4:57e049bce51e 1213
Azure.IoT Build 7:07bc440836b3 1214 static void IoTHubTransportAMQP_Unsubscribe(TRANSPORT_HANDLE handle)
AzureIoTClient 4:57e049bce51e 1215 {
Azure.IoT Build 7:07bc440836b3 1216 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_039: [IoTHubTransportAMQP_Unsubscribe shall fail if the transport handle parameter received is NULL.]
Azure.IoT Build 7:07bc440836b3 1217 if (handle == NULL)
AzureIoTClient 4:57e049bce51e 1218 {
Azure.IoT Build 7:07bc440836b3 1219 LogError("Invalid handle to IoTHubClient AMQP transport.\r\n");
Azure.IoT Build 7:07bc440836b3 1220 }
Azure.IoT Build 7:07bc440836b3 1221 else
Azure.IoT Build 7:07bc440836b3 1222 {
Azure.IoT Build 7:07bc440836b3 1223 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_040: [IoTHubTransportAMQP_Unsubscribe shall set transport_handle->receive_messages to false and return success code.]
Azure.IoT Build 7:07bc440836b3 1224 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
Azure.IoT Build 7:07bc440836b3 1225 transport_state->receive_messages = false;
AzureIoTClient 4:57e049bce51e 1226 }
AzureIoTClient 4:57e049bce51e 1227 }
AzureIoTClient 4:57e049bce51e 1228
Azure.IoT Build 7:07bc440836b3 1229 static IOTHUB_CLIENT_RESULT IoTHubTransportAMQP_GetSendStatus(TRANSPORT_HANDLE handle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
AzureIoTClient 4:57e049bce51e 1230 {
AzureIoTClient 4:57e049bce51e 1231 IOTHUB_CLIENT_RESULT result;
AzureIoTClient 4:57e049bce51e 1232
Azure.IoT Build 7:07bc440836b3 1233 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_041: [IoTHubTransportAMQP_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.]
AzureIoTClient 4:57e049bce51e 1234 if (handle == NULL)
AzureIoTClient 4:57e049bce51e 1235 {
AzureIoTClient 4:57e049bce51e 1236 result = IOTHUB_CLIENT_INVALID_ARG;
AzureIoTClient 4:57e049bce51e 1237 LogError("Invalid handle to IoTHubClient AMQP transport instance.\r\n");
AzureIoTClient 4:57e049bce51e 1238 }
AzureIoTClient 4:57e049bce51e 1239 else if (iotHubClientStatus == NULL)
AzureIoTClient 4:57e049bce51e 1240 {
AzureIoTClient 4:57e049bce51e 1241 result = IOTHUB_CLIENT_INVALID_ARG;
AzureIoTClient 4:57e049bce51e 1242 LogError("Invalid pointer to output parameter IOTHUB_CLIENT_STATUS.\r\n");
AzureIoTClient 4:57e049bce51e 1243 }
AzureIoTClient 4:57e049bce51e 1244 else
AzureIoTClient 4:57e049bce51e 1245 {
Azure.IoT Build 7:07bc440836b3 1246 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
AzureIoTClient 4:57e049bce51e 1247
Azure.IoT Build 7:07bc440836b3 1248 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_043: [IoTHubTransportAMQP_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent.]
Azure.IoT Build 7:07bc440836b3 1249 if (!DList_IsListEmpty(transport_state->waitingToSend) || !DList_IsListEmpty(&(transport_state->inProgress)))
AzureIoTClient 4:57e049bce51e 1250 {
AzureIoTClient 4:57e049bce51e 1251 *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_BUSY;
AzureIoTClient 4:57e049bce51e 1252 }
Azure.IoT Build 7:07bc440836b3 1253 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_042: [IoTHubTransportAMQP_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent.]
AzureIoTClient 4:57e049bce51e 1254 else
AzureIoTClient 4:57e049bce51e 1255 {
AzureIoTClient 4:57e049bce51e 1256 *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_IDLE;
AzureIoTClient 4:57e049bce51e 1257 }
AzureIoTClient 4:57e049bce51e 1258
AzureIoTClient 4:57e049bce51e 1259 result = IOTHUB_CLIENT_OK;
AzureIoTClient 4:57e049bce51e 1260 }
AzureIoTClient 4:57e049bce51e 1261
AzureIoTClient 4:57e049bce51e 1262 return result;
AzureIoTClient 4:57e049bce51e 1263 }
AzureIoTClient 4:57e049bce51e 1264
Azure.IoT Build 7:07bc440836b3 1265 static IOTHUB_CLIENT_RESULT IoTHubTransportAMQP_SetOption(TRANSPORT_HANDLE handle, const char* option, const void* value)
AzureIoTClient 4:57e049bce51e 1266 {
AzureIoTClient 4:57e049bce51e 1267 IOTHUB_CLIENT_RESULT result;
AzureIoTClient 4:57e049bce51e 1268
Azure.IoT Build 7:07bc440836b3 1269 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_044: [If handle parameter is NULL then IoTHubTransportAMQP_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]
Azure.IoT Build 7:07bc440836b3 1270 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_045: [If parameter optionName is NULL then IoTHubTransportAMQP_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]
Azure.IoT Build 7:07bc440836b3 1271 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_046: [If parameter value is NULL then IoTHubTransportAMQP_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]
AzureIoTClient 5:8d58d20699dd 1272 if (
AzureIoTClient 5:8d58d20699dd 1273 (handle == NULL) ||
AzureIoTClient 5:8d58d20699dd 1274 (option == NULL) ||
AzureIoTClient 5:8d58d20699dd 1275 (value == NULL)
AzureIoTClient 5:8d58d20699dd 1276 )
AzureIoTClient 5:8d58d20699dd 1277 {
AzureIoTClient 5:8d58d20699dd 1278 result = IOTHUB_CLIENT_INVALID_ARG;
Azure.IoT Build 7:07bc440836b3 1279 LogError("Invalid parameter (NULL) passed to AMQP transport SetOption()\r\n");
AzureIoTClient 5:8d58d20699dd 1280 }
AzureIoTClient 5:8d58d20699dd 1281 else
AzureIoTClient 5:8d58d20699dd 1282 {
Azure.IoT Build 7:07bc440836b3 1283 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
AzureIoTClient 4:57e049bce51e 1284
Azure.IoT Build 7:07bc440836b3 1285 if (strcmp("trusted_certificates", option) == 0)
Azure.IoT Build 7:07bc440836b3 1286 {
Azure.IoT Build 7:07bc440836b3 1287 transport_state->trusted_certificates = (char*)value;
Azure.IoT Build 7:07bc440836b3 1288 result = IOTHUB_CLIENT_OK;
Azure.IoT Build 7:07bc440836b3 1289 }
Azure.IoT Build 7:07bc440836b3 1290 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_048: [IotHubTransportAMQP_SetOption shall save and apply the value if the option name is "sas_token_lifetime", returning IOTHUB_CLIENT_OK]
Azure.IoT Build 7:07bc440836b3 1291 else if (strcmp("sas_token_lifetime", option) == 0)
Azure.IoT Build 7:07bc440836b3 1292 {
Azure.IoT Build 7:07bc440836b3 1293 transport_state->sas_token_lifetime = *((size_t*)value);
Azure.IoT Build 7:07bc440836b3 1294 result = IOTHUB_CLIENT_OK;
Azure.IoT Build 7:07bc440836b3 1295 }
Azure.IoT Build 7:07bc440836b3 1296 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_049: [IotHubTransportAMQP_SetOption shall save and apply the value if the option name is "sas_token_refresh_time", returning IOTHUB_CLIENT_OK]
Azure.IoT Build 7:07bc440836b3 1297 else if (strcmp("sas_token_refresh_time", option) == 0)
Azure.IoT Build 7:07bc440836b3 1298 {
Azure.IoT Build 7:07bc440836b3 1299 transport_state->sas_token_refresh_time = *((size_t*)value);
Azure.IoT Build 7:07bc440836b3 1300 result = IOTHUB_CLIENT_OK;
Azure.IoT Build 7:07bc440836b3 1301 }
Azure.IoT Build 7:07bc440836b3 1302 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_148: [IotHubTransportAMQP_SetOption shall save and apply the value if the option name is "cbs_request_timeout", returning IOTHUB_CLIENT_OK]
Azure.IoT Build 7:07bc440836b3 1303 else if (strcmp("cbs_request_timeout", option) == 0)
Azure.IoT Build 7:07bc440836b3 1304 {
Azure.IoT Build 7:07bc440836b3 1305 transport_state->cbs_request_timeout = *((size_t*)value);
Azure.IoT Build 7:07bc440836b3 1306 result = IOTHUB_CLIENT_OK;
Azure.IoT Build 7:07bc440836b3 1307 }
Azure.IoT Build 7:07bc440836b3 1308 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_149: [IotHubTransportAMQP_SetOption shall save and apply the value if the option name is "message_send_timeout", returning IOTHUB_CLIENT_OK]
Azure.IoT Build 7:07bc440836b3 1309 else if (strcmp("message_send_timeout", option) == 0)
Azure.IoT Build 7:07bc440836b3 1310 {
Azure.IoT Build 7:07bc440836b3 1311 transport_state->message_send_timeout = *((size_t*)value);
Azure.IoT Build 7:07bc440836b3 1312 result = IOTHUB_CLIENT_OK;
Azure.IoT Build 7:07bc440836b3 1313 }
Azure.IoT Build 7:07bc440836b3 1314 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_047: [If optionName is not an option supported then IotHubTransportAMQP_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]
Azure.IoT Build 7:07bc440836b3 1315 else
Azure.IoT Build 7:07bc440836b3 1316 {
Azure.IoT Build 7:07bc440836b3 1317 result = IOTHUB_CLIENT_INVALID_ARG;
Azure.IoT Build 7:07bc440836b3 1318 LogError("Invalid option (%s) passed to uAMQP transport SetOption()\r\n", option);
Azure.IoT Build 7:07bc440836b3 1319 }
Azure.IoT Build 7:07bc440836b3 1320 }
AzureIoTClient 4:57e049bce51e 1321
AzureIoTClient 4:57e049bce51e 1322 return result;
AzureIoTClient 4:57e049bce51e 1323 }
AzureIoTClient 4:57e049bce51e 1324
Azure.IoT Build 7:07bc440836b3 1325 static TRANSPORT_PROVIDER thisTransportProvider = {
Azure.IoT Build 7:07bc440836b3 1326 IoTHubTransportAMQP_SetOption,
Azure.IoT Build 7:07bc440836b3 1327 IoTHubTransportAMQP_Create,
Azure.IoT Build 7:07bc440836b3 1328 IoTHubTransportAMQP_Destroy,
Azure.IoT Build 7:07bc440836b3 1329 IoTHubTransportAMQP_Subscribe,
Azure.IoT Build 7:07bc440836b3 1330 IoTHubTransportAMQP_Unsubscribe,
Azure.IoT Build 7:07bc440836b3 1331 IoTHubTransportAMQP_DoWork,
Azure.IoT Build 7:07bc440836b3 1332 IoTHubTransportAMQP_GetSendStatus
AzureIoTClient 4:57e049bce51e 1333 };
AzureIoTClient 4:57e049bce51e 1334
AzureIoTClient 4:57e049bce51e 1335 extern const void* AMQP_Protocol(void)
AzureIoTClient 4:57e049bce51e 1336 {
Azure.IoT Build 7:07bc440836b3 1337 return &thisTransportProvider;
AzureIoTClient 4:57e049bce51e 1338 }