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:
AzureIoTClient
Date:
Sun Apr 24 16:37:38 2016 -0700
Revision:
13:a4af7c301e02
Parent:
12:841a4c36bd36
Child:
14:8e8e42008807
1.0.5

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