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:
Mon Jul 18 16:44:19 2016 -0700
Revision:
19:ea016664011a
Parent:
18:239d162e3607
Child:
20:8dec76e7ba34
1.0.11

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 18:239d162e3607 14 #include "azure_c_shared_utility/xlogging.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
AzureIoTClient 19:ea016664011a 64 typedef enum AMQP_TRANSPORT_CREDENTIAL_TYPE_TAG
AzureIoTClient 19:ea016664011a 65 {
AzureIoTClient 19:ea016664011a 66 CREDENTIAL_NOT_BUILD,
AzureIoTClient 19:ea016664011a 67 X509,
AzureIoTClient 19:ea016664011a 68 DEVICE_KEY,
AzureIoTClient 19:ea016664011a 69 DEVICE_SAS_TOKEN,
AzureIoTClient 19:ea016664011a 70 }AMQP_TRANSPORT_CREDENTIAL_TYPE;
AzureIoTClient 19:ea016664011a 71
AzureIoTClient 19:ea016664011a 72 typedef struct X509_CREDENTIAL_TAG
AzureIoTClient 19:ea016664011a 73 {
AzureIoTClient 19:ea016664011a 74 const char* x509certificate;
AzureIoTClient 19:ea016664011a 75 const char* x509privatekey;
AzureIoTClient 19:ea016664011a 76 }X509_CREDENTIAL;
AzureIoTClient 19:ea016664011a 77
AzureIoTClient 19:ea016664011a 78 typedef union AMQP_TRANSPORT_CREDENTIAL_UNION_TAG
AzureIoTClient 19:ea016664011a 79 {
AzureIoTClient 19:ea016664011a 80 // Key associated to the device to be used.
AzureIoTClient 19:ea016664011a 81 STRING_HANDLE deviceKey;
AzureIoTClient 19:ea016664011a 82
AzureIoTClient 19:ea016664011a 83 // SAS associated to the device to be used.
AzureIoTClient 19:ea016664011a 84 STRING_HANDLE deviceSasToken;
AzureIoTClient 19:ea016664011a 85
AzureIoTClient 19:ea016664011a 86 // X509
AzureIoTClient 19:ea016664011a 87 X509_CREDENTIAL x509credential;
AzureIoTClient 19:ea016664011a 88 }AMQP_TRANSPORT_CREDENTIAL_UNION;
AzureIoTClient 19:ea016664011a 89
AzureIoTClient 19:ea016664011a 90 typedef struct AMQP_TRANSPORT_CREDENTIAL_TAG
AzureIoTClient 19:ea016664011a 91 {
AzureIoTClient 19:ea016664011a 92 AMQP_TRANSPORT_CREDENTIAL_TYPE credentialType;
AzureIoTClient 19:ea016664011a 93 AMQP_TRANSPORT_CREDENTIAL_UNION credential;
AzureIoTClient 19:ea016664011a 94 }AMQP_TRANSPORT_CREDENTIAL;
AzureIoTClient 19:ea016664011a 95
Azure.IoT Build 7:07bc440836b3 96 typedef struct AMQP_TRANSPORT_STATE_TAG
Azure.IoT Build 7:07bc440836b3 97 {
Azure.IoT Build 10:75c5e0d8537d 98 // FQDN of the IoT Hub.
Azure.IoT Build 10:75c5e0d8537d 99 STRING_HANDLE iotHubHostFqdn;
Azure.IoT Build 10:75c5e0d8537d 100 // AMQP port of the IoT Hub.
Azure.IoT Build 10:75c5e0d8537d 101 int iotHubPort;
AzureIoTClient 19:ea016664011a 102 // contains the credentials to be used
AzureIoTClient 19:ea016664011a 103 AMQP_TRANSPORT_CREDENTIAL credential;
Azure.IoT Build 10:75c5e0d8537d 104 // Address to which the transport will connect to and send events.
Azure.IoT Build 10:75c5e0d8537d 105 STRING_HANDLE targetAddress;
Azure.IoT Build 10:75c5e0d8537d 106 // Address to which the transport will connect to and receive messages from.
Azure.IoT Build 10:75c5e0d8537d 107 STRING_HANDLE messageReceiveAddress;
Azure.IoT Build 10:75c5e0d8537d 108 // A component of the SAS token. Currently this must be an empty string.
Azure.IoT Build 10:75c5e0d8537d 109 STRING_HANDLE sasTokenKeyName;
Azure.IoT Build 10:75c5e0d8537d 110 // Internal parameter that identifies the current logical device within the service.
Azure.IoT Build 10:75c5e0d8537d 111 STRING_HANDLE devicesPath;
Azure.IoT Build 10:75c5e0d8537d 112 // How long a SAS token created by the transport is valid, in milliseconds.
Azure.IoT Build 10:75c5e0d8537d 113 size_t sas_token_lifetime;
Azure.IoT Build 10:75c5e0d8537d 114 // Maximum period of time for the transport to wait before refreshing the SAS token it created previously, in milliseconds.
Azure.IoT Build 10:75c5e0d8537d 115 size_t sas_token_refresh_time;
Azure.IoT Build 10:75c5e0d8537d 116 // Maximum time the transport waits for uAMQP cbs_put_token() to complete before marking it a failure, in milliseconds.
Azure.IoT Build 10:75c5e0d8537d 117 size_t cbs_request_timeout;
Azure.IoT Build 10:75c5e0d8537d 118 // Maximum time for the connection establishment/retry logic should wait for a connection to succeed, in milliseconds.
Azure.IoT Build 10:75c5e0d8537d 119 size_t connection_timeout;
Azure.IoT Build 10:75c5e0d8537d 120 // Saved reference to the IoTHub LL Client.
Azure.IoT Build 10:75c5e0d8537d 121 IOTHUB_CLIENT_LL_HANDLE iothub_client_handle;
Azure.IoT Build 11:62d7b956e76e 122
Azure.IoT Build 10:75c5e0d8537d 123 // TSL I/O transport.
Azure.IoT Build 10:75c5e0d8537d 124 XIO_HANDLE tls_io;
Azure.IoT Build 10:75c5e0d8537d 125 // Pointer to the function that creates the TLS I/O (internal use only).
Azure.IoT Build 10:75c5e0d8537d 126 TLS_IO_TRANSPORT_PROVIDER tls_io_transport_provider;
Azure.IoT Build 10:75c5e0d8537d 127 // AMQP SASL I/O transport created on top of the TLS I/O layer.
Azure.IoT Build 10:75c5e0d8537d 128 XIO_HANDLE sasl_io;
Azure.IoT Build 10:75c5e0d8537d 129 // AMQP SASL I/O mechanism to be used.
Azure.IoT Build 10:75c5e0d8537d 130 SASL_MECHANISM_HANDLE sasl_mechanism;
Azure.IoT Build 10:75c5e0d8537d 131 // AMQP connection.
Azure.IoT Build 10:75c5e0d8537d 132 CONNECTION_HANDLE connection;
Azure.IoT Build 10:75c5e0d8537d 133 // Current AMQP connection state;
Azure.IoT Build 10:75c5e0d8537d 134 AMQP_MANAGEMENT_STATE connection_state;
Azure.IoT Build 10:75c5e0d8537d 135 // Last time the AMQP connection establishment was initiated.
Azure.IoT Build 10:75c5e0d8537d 136 size_t connection_establish_time;
Azure.IoT Build 10:75c5e0d8537d 137 // AMQP session.
Azure.IoT Build 10:75c5e0d8537d 138 SESSION_HANDLE session;
Azure.IoT Build 10:75c5e0d8537d 139 // AMQP link used by the event sender.
Azure.IoT Build 10:75c5e0d8537d 140 LINK_HANDLE sender_link;
Azure.IoT Build 10:75c5e0d8537d 141 // uAMQP event sender.
Azure.IoT Build 10:75c5e0d8537d 142 MESSAGE_SENDER_HANDLE message_sender;
Azure.IoT Build 10:75c5e0d8537d 143 // Internal flag that controls if messages should be received or not.
Azure.IoT Build 10:75c5e0d8537d 144 bool receive_messages;
Azure.IoT Build 10:75c5e0d8537d 145 // AMQP link used by the message receiver.
Azure.IoT Build 10:75c5e0d8537d 146 LINK_HANDLE receiver_link;
Azure.IoT Build 10:75c5e0d8537d 147 // uAMQP message receiver.
Azure.IoT Build 10:75c5e0d8537d 148 MESSAGE_RECEIVER_HANDLE message_receiver;
Azure.IoT Build 10:75c5e0d8537d 149 // List with events still pending to be sent. It is provided by the upper layer.
Azure.IoT Build 10:75c5e0d8537d 150 PDLIST_ENTRY waitingToSend;
Azure.IoT Build 10:75c5e0d8537d 151 // Internal list with the items currently being processed/sent through uAMQP.
Azure.IoT Build 10:75c5e0d8537d 152 DLIST_ENTRY inProgress;
Azure.IoT Build 10:75c5e0d8537d 153 // Connection instance with the Azure IoT CBS.
Azure.IoT Build 10:75c5e0d8537d 154 CBS_HANDLE cbs;
Azure.IoT Build 10:75c5e0d8537d 155 // Current state of the CBS connection.
Azure.IoT Build 10:75c5e0d8537d 156 CBS_STATE cbs_state;
Azure.IoT Build 10:75c5e0d8537d 157 // Time when the current SAS token was created, in seconds since epoch.
Azure.IoT Build 10:75c5e0d8537d 158 size_t current_sas_token_create_time;
Azure.IoT Build 10:75c5e0d8537d 159 // Mark if device is registered in transport (only one device per transport).
Azure.IoT Build 10:75c5e0d8537d 160 bool isRegistered;
AzureIoTClient 16:a49121e2300b 161 // Turns logging on and off
AzureIoTClient 16:a49121e2300b 162 bool is_trace_on;
Azure.IoT Build 7:07bc440836b3 163 } AMQP_TRANSPORT_INSTANCE;
Azure.IoT Build 7:07bc440836b3 164
AzureIoTClient 4:57e049bce51e 165
AzureIoTClient 4:57e049bce51e 166
Azure.IoT Build 7:07bc440836b3 167 // Auxiliary functions
AzureIoTClient 4:57e049bce51e 168
Azure.IoT Build 7:07bc440836b3 169 static STRING_HANDLE concat3Params(const char* prefix, const char* infix, const char* suffix)
AzureIoTClient 4:57e049bce51e 170 {
Azure.IoT Build 7:07bc440836b3 171 STRING_HANDLE result = NULL;
Azure.IoT Build 10:75c5e0d8537d 172 char* concat;
Azure.IoT Build 7:07bc440836b3 173 size_t totalLength = strlen(prefix) + strlen(infix) + strlen(suffix) + 1; // One extra for \0.
AzureIoTClient 5:8d58d20699dd 174
Azure.IoT Build 10:75c5e0d8537d 175 if ((concat = (char*)malloc(totalLength)) != NULL)
AzureIoTClient 5:8d58d20699dd 176 {
Azure.IoT Build 10:75c5e0d8537d 177 (void)strcpy(concat, prefix);
Azure.IoT Build 10:75c5e0d8537d 178 (void)strcat(concat, infix);
Azure.IoT Build 10:75c5e0d8537d 179 (void)strcat(concat, suffix);
Azure.IoT Build 10:75c5e0d8537d 180 result = STRING_construct(concat);
Azure.IoT Build 7:07bc440836b3 181 free(concat);
AzureIoTClient 5:8d58d20699dd 182 }
Azure.IoT Build 10:75c5e0d8537d 183 else
Azure.IoT Build 10:75c5e0d8537d 184 {
Azure.IoT Build 10:75c5e0d8537d 185 result = NULL;
Azure.IoT Build 10:75c5e0d8537d 186 }
AzureIoTClient 5:8d58d20699dd 187
AzureIoTClient 4:57e049bce51e 188 return result;
AzureIoTClient 4:57e049bce51e 189 }
AzureIoTClient 4:57e049bce51e 190
Azure.IoT Build 10:75c5e0d8537d 191 static size_t getSecondsSinceEpoch(void)
AzureIoTClient 4:57e049bce51e 192 {
Azure.IoT Build 10:75c5e0d8537d 193 return (size_t)(difftime(get_time(NULL), (time_t)0));
AzureIoTClient 4:57e049bce51e 194 }
AzureIoTClient 4:57e049bce51e 195
Azure.IoT Build 12:841a4c36bd36 196 static void trackEventInProgress(IOTHUB_MESSAGE_LIST* message, AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 197 {
Azure.IoT Build 12:841a4c36bd36 198 DList_RemoveEntryList(&message->entry);
Azure.IoT Build 12:841a4c36bd36 199 DList_InsertTailList(&transport_state->inProgress, &message->entry);
AzureIoTClient 4:57e049bce51e 200 }
AzureIoTClient 4:57e049bce51e 201
Azure.IoT Build 7:07bc440836b3 202 static IOTHUB_MESSAGE_LIST* getNextEventToSend(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 203 {
Azure.IoT Build 10:75c5e0d8537d 204 IOTHUB_MESSAGE_LIST* message;
Azure.IoT Build 7:07bc440836b3 205
Azure.IoT Build 7:07bc440836b3 206 if (!DList_IsListEmpty(transport_state->waitingToSend))
AzureIoTClient 4:57e049bce51e 207 {
Azure.IoT Build 7:07bc440836b3 208 PDLIST_ENTRY list_entry = transport_state->waitingToSend->Flink;
Azure.IoT Build 7:07bc440836b3 209 message = containingRecord(list_entry, IOTHUB_MESSAGE_LIST, entry);
AzureIoTClient 4:57e049bce51e 210 }
Azure.IoT Build 10:75c5e0d8537d 211 else
Azure.IoT Build 10:75c5e0d8537d 212 {
Azure.IoT Build 10:75c5e0d8537d 213 message = NULL;
Azure.IoT Build 10:75c5e0d8537d 214 }
Azure.IoT Build 7:07bc440836b3 215
Azure.IoT Build 7:07bc440836b3 216 return message;
Azure.IoT Build 7:07bc440836b3 217 }
Azure.IoT Build 7:07bc440836b3 218
Azure.IoT Build 12:841a4c36bd36 219 static int isEventInInProgressList(IOTHUB_MESSAGE_LIST* message)
Azure.IoT Build 7:07bc440836b3 220 {
Azure.IoT Build 12:841a4c36bd36 221 return !DList_IsListEmpty(&message->entry);
AzureIoTClient 4:57e049bce51e 222 }
AzureIoTClient 4:57e049bce51e 223
Azure.IoT Build 12:841a4c36bd36 224 static void removeEventFromInProgressList(IOTHUB_MESSAGE_LIST* message)
AzureIoTClient 4:57e049bce51e 225 {
Azure.IoT Build 12:841a4c36bd36 226 DList_RemoveEntryList(&message->entry);
Azure.IoT Build 12:841a4c36bd36 227 DList_InitializeListHead(&message->entry);
AzureIoTClient 4:57e049bce51e 228 }
AzureIoTClient 4:57e049bce51e 229
Azure.IoT Build 12:841a4c36bd36 230 static void rollEventBackToWaitList(IOTHUB_MESSAGE_LIST* message, AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 231 {
Azure.IoT Build 12:841a4c36bd36 232 removeEventFromInProgressList(message);
AzureIoTClient 16:a49121e2300b 233 DList_InsertTailList(transport_state->waitingToSend, &message->entry);
Azure.IoT Build 7:07bc440836b3 234 }
Azure.IoT Build 7:07bc440836b3 235
Azure.IoT Build 7:07bc440836b3 236 static void rollEventsBackToWaitList(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 237 {
Azure.IoT Build 7:07bc440836b3 238 PDLIST_ENTRY entry = transport_state->inProgress.Blink;
Azure.IoT Build 7:07bc440836b3 239
Azure.IoT Build 7:07bc440836b3 240 while (entry != &transport_state->inProgress)
AzureIoTClient 4:57e049bce51e 241 {
AzureIoTClient 16:a49121e2300b 242 IOTHUB_MESSAGE_LIST* message = containingRecord(entry, IOTHUB_MESSAGE_LIST, entry);
Azure.IoT Build 7:07bc440836b3 243 entry = entry->Blink;
Azure.IoT Build 12:841a4c36bd36 244 rollEventBackToWaitList(message, transport_state);
AzureIoTClient 4:57e049bce51e 245 }
AzureIoTClient 4:57e049bce51e 246 }
AzureIoTClient 4:57e049bce51e 247
AzureIoTClient 14:8e8e42008807 248
AzureIoTClient 14:8e8e42008807 249 static int addPropertiesTouAMQPMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, MESSAGE_HANDLE uamqp_message)
AzureIoTClient 14:8e8e42008807 250 {
AzureIoTClient 16:a49121e2300b 251 int result;
AzureIoTClient 16:a49121e2300b 252 MAP_HANDLE properties_map;
AzureIoTClient 16:a49121e2300b 253 const char* const* propertyKeys;
AzureIoTClient 16:a49121e2300b 254 const char* const* propertyValues;
AzureIoTClient 16:a49121e2300b 255 size_t propertyCount;
AzureIoTClient 14:8e8e42008807 256
AzureIoTClient 19:ea016664011a 257 /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_007: [The IoTHub message properties shall be obtained by calling IoTHubMessage_Properties.] */
AzureIoTClient 16:a49121e2300b 258 properties_map = IoTHubMessage_Properties(iothub_message_handle);
AzureIoTClient 16:a49121e2300b 259 if (properties_map == NULL)
AzureIoTClient 16:a49121e2300b 260 {
AzureIoTClient 19:ea016664011a 261 /* Codes_SRS_IOTHUBTRANSPORTAMQP_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 16:a49121e2300b 262 LogError("Failed to get property map from IoTHub message.");
AzureIoTClient 16:a49121e2300b 263 result = __LINE__;
AzureIoTClient 16:a49121e2300b 264 }
AzureIoTClient 19:ea016664011a 265 /* Codes_SRS_IOTHUBTRANSPORTAMQP_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.] */
AzureIoTClient 16:a49121e2300b 266 else if (Map_GetInternals(properties_map, &propertyKeys, &propertyValues, &propertyCount) != MAP_OK)
AzureIoTClient 16:a49121e2300b 267 {
AzureIoTClient 19:ea016664011a 268 /* Codes_SRS_IOTHUBTRANSPORTAMQP_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 16:a49121e2300b 269 LogError("Failed to get the internals of the property map.");
AzureIoTClient 16:a49121e2300b 270 result = __LINE__;
AzureIoTClient 16:a49121e2300b 271 }
AzureIoTClient 16:a49121e2300b 272 else
AzureIoTClient 16:a49121e2300b 273 {
AzureIoTClient 19:ea016664011a 274 /* Codes_SRS_IOTHUBTRANSPORTAMQP_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.] */
AzureIoTClient 16:a49121e2300b 275 if (propertyCount != 0)
AzureIoTClient 16:a49121e2300b 276 {
AzureIoTClient 16:a49121e2300b 277 size_t i;
AzureIoTClient 19:ea016664011a 278 /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_009: [The uAMQP map shall be created by calling amqpvalue_create_map.] */
AzureIoTClient 16:a49121e2300b 279 AMQP_VALUE uamqp_map = amqpvalue_create_map();
AzureIoTClient 16:a49121e2300b 280 if (uamqp_map == NULL)
AzureIoTClient 16:a49121e2300b 281 {
AzureIoTClient 19:ea016664011a 282 /* Codes_SRS_IOTHUBTRANSPORTAMQP_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 16:a49121e2300b 283 LogError("Failed to create uAMQP map for the properties.");
AzureIoTClient 16:a49121e2300b 284 result = __LINE__;
AzureIoTClient 16:a49121e2300b 285 }
AzureIoTClient 16:a49121e2300b 286 else
AzureIoTClient 16:a49121e2300b 287 {
AzureIoTClient 16:a49121e2300b 288 for (i = 0; i < propertyCount; i++)
AzureIoTClient 16:a49121e2300b 289 {
AzureIoTClient 19:ea016664011a 290 /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_010: [A key uAMQP value shall be created by using amqpvalue_create_string.] */
AzureIoTClient 16:a49121e2300b 291 AMQP_VALUE map_key_value = amqpvalue_create_string(propertyKeys[i]);
AzureIoTClient 16:a49121e2300b 292 if (map_key_value == NULL)
AzureIoTClient 16:a49121e2300b 293 {
AzureIoTClient 19:ea016664011a 294 /* Codes_SRS_IOTHUBTRANSPORTAMQP_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 16:a49121e2300b 295 LogError("Failed to create uAMQP property key value.");
AzureIoTClient 16:a49121e2300b 296 break;
AzureIoTClient 16:a49121e2300b 297 }
AzureIoTClient 14:8e8e42008807 298
AzureIoTClient 19:ea016664011a 299 /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_011: [A value uAMQP value shall be created by using amqpvalue_create_string.] */
AzureIoTClient 16:a49121e2300b 300 AMQP_VALUE map_value_value = amqpvalue_create_string(propertyValues[i]);
AzureIoTClient 16:a49121e2300b 301 if (map_value_value == NULL)
AzureIoTClient 16:a49121e2300b 302 {
AzureIoTClient 16:a49121e2300b 303 amqpvalue_destroy(map_key_value);
AzureIoTClient 19:ea016664011a 304 /* Codes_SRS_IOTHUBTRANSPORTAMQP_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 16:a49121e2300b 305 LogError("Failed to create uAMQP property key value.");
AzureIoTClient 16:a49121e2300b 306 break;
AzureIoTClient 16:a49121e2300b 307 }
AzureIoTClient 14:8e8e42008807 308
AzureIoTClient 19:ea016664011a 309 /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_008: [All properties shall be transferred to a uAMQP map.] */
AzureIoTClient 19:ea016664011a 310 /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_012: [The key/value pair for the property shall be set into the uAMQP property map by calling amqpvalue_map_set_value.] */
AzureIoTClient 16:a49121e2300b 311 if (amqpvalue_set_map_value(uamqp_map, map_key_value, map_value_value) != 0)
AzureIoTClient 16:a49121e2300b 312 {
AzureIoTClient 16:a49121e2300b 313 amqpvalue_destroy(map_key_value);
AzureIoTClient 16:a49121e2300b 314 amqpvalue_destroy(map_value_value);
AzureIoTClient 19:ea016664011a 315 /* Codes_SRS_IOTHUBTRANSPORTAMQP_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 16:a49121e2300b 316 LogError("Failed to create uAMQP property key value.");
AzureIoTClient 16:a49121e2300b 317 break;
AzureIoTClient 16:a49121e2300b 318 }
AzureIoTClient 14:8e8e42008807 319
AzureIoTClient 16:a49121e2300b 320 amqpvalue_destroy(map_key_value);
AzureIoTClient 16:a49121e2300b 321 amqpvalue_destroy(map_value_value);
AzureIoTClient 16:a49121e2300b 322 }
AzureIoTClient 14:8e8e42008807 323
AzureIoTClient 16:a49121e2300b 324 if (i < propertyCount)
AzureIoTClient 16:a49121e2300b 325 {
AzureIoTClient 16:a49121e2300b 326 result = __LINE__;
AzureIoTClient 16:a49121e2300b 327 }
AzureIoTClient 16:a49121e2300b 328 else
AzureIoTClient 16:a49121e2300b 329 {
AzureIoTClient 19:ea016664011a 330 /* Codes_SRS_IOTHUBTRANSPORTAMQP_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.] */
AzureIoTClient 16:a49121e2300b 331 if (message_set_application_properties(uamqp_message, uamqp_map) != 0)
AzureIoTClient 16:a49121e2300b 332 {
AzureIoTClient 19:ea016664011a 333 /* Codes_SRS_IOTHUBTRANSPORTAMQP_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 16:a49121e2300b 334 LogError("Failed to transfer the message properties to the uAMQP message.");
AzureIoTClient 16:a49121e2300b 335 result = __LINE__;
AzureIoTClient 16:a49121e2300b 336 }
AzureIoTClient 16:a49121e2300b 337 else
AzureIoTClient 16:a49121e2300b 338 {
AzureIoTClient 16:a49121e2300b 339 result = 0;
AzureIoTClient 16:a49121e2300b 340 }
AzureIoTClient 16:a49121e2300b 341 }
AzureIoTClient 14:8e8e42008807 342
AzureIoTClient 16:a49121e2300b 343 amqpvalue_destroy(uamqp_map);
AzureIoTClient 16:a49121e2300b 344 }
AzureIoTClient 16:a49121e2300b 345 }
AzureIoTClient 16:a49121e2300b 346 else
AzureIoTClient 16:a49121e2300b 347 {
AzureIoTClient 16:a49121e2300b 348 result = 0;
AzureIoTClient 16:a49121e2300b 349 }
AzureIoTClient 16:a49121e2300b 350 }
AzureIoTClient 14:8e8e42008807 351
AzureIoTClient 16:a49121e2300b 352 return result;
AzureIoTClient 14:8e8e42008807 353 }
AzureIoTClient 14:8e8e42008807 354
AzureIoTClient 14:8e8e42008807 355 static int readPropertiesFromuAMQPMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, MESSAGE_HANDLE uamqp_message)
AzureIoTClient 14:8e8e42008807 356 {
AzureIoTClient 16:a49121e2300b 357 int return_value;
AzureIoTClient 16:a49121e2300b 358 PROPERTIES_HANDLE uamqp_message_properties;
AzureIoTClient 16:a49121e2300b 359 AMQP_VALUE uamqp_message_property;
AzureIoTClient 16:a49121e2300b 360 const char* uamqp_message_property_value;
AzureIoTClient 16:a49121e2300b 361 int api_call_result;
AzureIoTClient 14:8e8e42008807 362
AzureIoTClient 16:a49121e2300b 363 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_155: [uAMQP message properties shall be retrieved using message_get_properties.] */
AzureIoTClient 16:a49121e2300b 364 if ((api_call_result = message_get_properties(uamqp_message, &uamqp_message_properties)) != 0)
AzureIoTClient 16:a49121e2300b 365 {
AzureIoTClient 19:ea016664011a 366 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_156: [If message_get_properties fails, the error shall be notified and ‘on_message_received' shall continue.] */
AzureIoTClient 16:a49121e2300b 367 LogError("Failed to get property properties map from uAMQP message (error code %d).", api_call_result);
AzureIoTClient 16:a49121e2300b 368 return_value = __LINE__;
AzureIoTClient 16:a49121e2300b 369 }
AzureIoTClient 16:a49121e2300b 370 else
AzureIoTClient 16:a49121e2300b 371 {
AzureIoTClient 16:a49121e2300b 372 return_value = 0; // Properties 'message-id' and 'correlation-id' are optional according to the AMQP 1.0 spec.
AzureIoTClient 16:a49121e2300b 373
AzureIoTClient 16:a49121e2300b 374 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_157: [The message-id property shall be read from the uAMQP message by calling properties_get_message_id.] */
AzureIoTClient 16:a49121e2300b 375 if ((api_call_result = properties_get_message_id(uamqp_message_properties, &uamqp_message_property)) != 0)
AzureIoTClient 16:a49121e2300b 376 {
AzureIoTClient 19:ea016664011a 377 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_158: [If properties_get_message_id fails, the error shall be notified and ‘on_message_received' shall continue.] */
AzureIoTClient 16:a49121e2300b 378 LogInfo("Failed to get value of uAMQP message 'message-id' property (%d).", api_call_result);
AzureIoTClient 16:a49121e2300b 379 return_value = __LINE__;
AzureIoTClient 16:a49121e2300b 380 }
AzureIoTClient 16:a49121e2300b 381 else if (amqpvalue_get_type(uamqp_message_property) != AMQP_TYPE_NULL)
AzureIoTClient 16:a49121e2300b 382 {
AzureIoTClient 16:a49121e2300b 383 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_159: [The message-id value shall be retrieved from the AMQP_VALUE as char* by calling amqpvalue_get_string.] */
AzureIoTClient 16:a49121e2300b 384 if ((api_call_result = amqpvalue_get_string(uamqp_message_property, &uamqp_message_property_value)) != 0)
AzureIoTClient 16:a49121e2300b 385 {
AzureIoTClient 19:ea016664011a 386 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_160: [If amqpvalue_get_string fails, the error shall be notified and ‘on_message_received' shall continue.] */
AzureIoTClient 16:a49121e2300b 387 LogError("Failed to get value of uAMQP message 'message-id' property (%d).", api_call_result);
AzureIoTClient 16:a49121e2300b 388 return_value = __LINE__;
AzureIoTClient 16:a49121e2300b 389 }
AzureIoTClient 16:a49121e2300b 390 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_161: [The message-id property shall be set on the IOTHUB_MESSAGE_HANDLE by calling IoTHubMessage_SetMessageId, passing the value read from the uAMQP message.] */
AzureIoTClient 16:a49121e2300b 391 else if (IoTHubMessage_SetMessageId(iothub_message_handle, uamqp_message_property_value) != IOTHUB_MESSAGE_OK)
AzureIoTClient 16:a49121e2300b 392 {
AzureIoTClient 19:ea016664011a 393 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_162: [If IoTHubMessage_SetMessageId fails, the error shall be notified and ‘on_message_received' shall continue.] */
AzureIoTClient 16:a49121e2300b 394 LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'message-id' property.");
AzureIoTClient 16:a49121e2300b 395 return_value = __LINE__;
AzureIoTClient 16:a49121e2300b 396 }
AzureIoTClient 16:a49121e2300b 397 }
AzureIoTClient 14:8e8e42008807 398
AzureIoTClient 16:a49121e2300b 399 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_163: [The correlation-id property shall be read from the uAMQP message by calling properties_get_correlation_id.] */
AzureIoTClient 16:a49121e2300b 400 if ((api_call_result = properties_get_correlation_id(uamqp_message_properties, &uamqp_message_property)) != 0)
AzureIoTClient 16:a49121e2300b 401 {
AzureIoTClient 19:ea016664011a 402 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_164: [If properties_get_correlation_id fails, the error shall be notified and ‘on_message_received' shall continue.] */
AzureIoTClient 16:a49121e2300b 403 LogError("Failed to get value of uAMQP message 'correlation-id' property (%d).", api_call_result);
AzureIoTClient 16:a49121e2300b 404 return_value = __LINE__;
AzureIoTClient 16:a49121e2300b 405 }
AzureIoTClient 16:a49121e2300b 406 else if (amqpvalue_get_type(uamqp_message_property) != AMQP_TYPE_NULL)
AzureIoTClient 16:a49121e2300b 407 {
AzureIoTClient 16:a49121e2300b 408 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_165: [The correlation-id value shall be retrieved from the AMQP_VALUE as char* by calling amqpvalue_get_string.] */
AzureIoTClient 16:a49121e2300b 409 if ((api_call_result = amqpvalue_get_string(uamqp_message_property, &uamqp_message_property_value)) != 0)
AzureIoTClient 16:a49121e2300b 410 {
AzureIoTClient 19:ea016664011a 411 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_166: [If amqpvalue_get_string fails, the error shall be notified and ‘on_message_received' shall continue.] */
AzureIoTClient 16:a49121e2300b 412 LogError("Failed to get value of uAMQP message 'correlation-id' property (%d).", api_call_result);
AzureIoTClient 16:a49121e2300b 413 return_value = __LINE__;
AzureIoTClient 16:a49121e2300b 414 }
AzureIoTClient 16:a49121e2300b 415 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_167: [The correlation-id property shall be set on the IOTHUB_MESSAGE_HANDLE by calling IoTHubMessage_SetCorrelationId, passing the value read from the uAMQP message.] */
AzureIoTClient 16:a49121e2300b 416 else if (IoTHubMessage_SetCorrelationId(iothub_message_handle, uamqp_message_property_value) != IOTHUB_MESSAGE_OK)
AzureIoTClient 16:a49121e2300b 417 {
AzureIoTClient 19:ea016664011a 418 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_168: [If IoTHubMessage_SetCorrelationId fails, the error shall be notified and ‘on_message_received' shall continue.] */
AzureIoTClient 16:a49121e2300b 419 LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'correlation-id' property.");
AzureIoTClient 16:a49121e2300b 420 return_value = __LINE__;
AzureIoTClient 16:a49121e2300b 421 }
AzureIoTClient 16:a49121e2300b 422 }
AzureIoTClient 14:8e8e42008807 423 properties_destroy(uamqp_message_properties);
AzureIoTClient 16:a49121e2300b 424 }
AzureIoTClient 14:8e8e42008807 425
AzureIoTClient 16:a49121e2300b 426 return return_value;
AzureIoTClient 14:8e8e42008807 427 }
AzureIoTClient 14:8e8e42008807 428
AzureIoTClient 14:8e8e42008807 429 static int readApplicationPropertiesFromuAMQPMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, MESSAGE_HANDLE uamqp_message)
AzureIoTClient 14:8e8e42008807 430 {
AzureIoTClient 16:a49121e2300b 431 int result;
AzureIoTClient 16:a49121e2300b 432 AMQP_VALUE uamqp_app_properties;
AzureIoTClient 16:a49121e2300b 433 uint32_t property_count;
AzureIoTClient 16:a49121e2300b 434 MAP_HANDLE iothub_message_properties_map;
AzureIoTClient 14:8e8e42008807 435
AzureIoTClient 16:a49121e2300b 436 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_170: [The IOTHUB_MESSAGE_HANDLE properties shall be retrieved using IoTHubMessage_Properties.]
AzureIoTClient 16:a49121e2300b 437 if ((iothub_message_properties_map = IoTHubMessage_Properties(iothub_message_handle)) == NULL)
AzureIoTClient 16:a49121e2300b 438 {
AzureIoTClient 19:ea016664011a 439 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_186: [If IoTHubMessage_Properties fails, the error shall be notified and ‘on_message_received' shall continue.]
AzureIoTClient 16:a49121e2300b 440 LogError("Failed to get property map from IoTHub message.");
AzureIoTClient 16:a49121e2300b 441 result = __LINE__;
AzureIoTClient 16:a49121e2300b 442 }
AzureIoTClient 16:a49121e2300b 443 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_171: [uAMQP message application properties shall be retrieved using message_get_application_properties.]
AzureIoTClient 16:a49121e2300b 444 else if ((result = message_get_application_properties(uamqp_message, &uamqp_app_properties)) != 0)
AzureIoTClient 16:a49121e2300b 445 {
AzureIoTClient 19:ea016664011a 446 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_172: [If message_get_application_properties fails, the error shall be notified and ‘on_message_received' shall continue.]
AzureIoTClient 16:a49121e2300b 447 LogError("Failed reading the incoming uAMQP message properties (return code %d).", result);
AzureIoTClient 16:a49121e2300b 448 result = __LINE__;
AzureIoTClient 16:a49121e2300b 449 }
AzureIoTClient 19:ea016664011a 450 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_187: [If message_get_application_properties succeeds but returns a NULL application properties map (there are no properties), ‘on_message_received' shall continue normally.]
AzureIoTClient 16:a49121e2300b 451 else if (uamqp_app_properties == NULL)
AzureIoTClient 16:a49121e2300b 452 {
AzureIoTClient 16:a49121e2300b 453 result = 0;
AzureIoTClient 16:a49121e2300b 454 }
AzureIoTClient 16:a49121e2300b 455 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_173: [The actual uAMQP message application properties should be extracted from the result of message_get_application_properties using amqpvalue_get_inplace_described_value.]
AzureIoTClient 16:a49121e2300b 456 else if ((uamqp_app_properties = amqpvalue_get_inplace_described_value(uamqp_app_properties)) == NULL)
AzureIoTClient 16:a49121e2300b 457 {
AzureIoTClient 19:ea016664011a 458 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_174: [If amqpvalue_get_inplace_described_value fails, the error shall be notified and ‘on_message_received' shall continue.]
AzureIoTClient 16:a49121e2300b 459 LogError("Failed getting the map of uAMQP message application properties (return code %d).", result);
AzureIoTClient 16:a49121e2300b 460 result = __LINE__;
AzureIoTClient 16:a49121e2300b 461 }
AzureIoTClient 16:a49121e2300b 462 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_175: [The number of items in the uAMQP message application properties shall be obtained using amqpvalue_get_map_pair_count.]
AzureIoTClient 16:a49121e2300b 463 else if ((result = amqpvalue_get_map_pair_count(uamqp_app_properties, &property_count)) != 0)
AzureIoTClient 16:a49121e2300b 464 {
AzureIoTClient 19:ea016664011a 465 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_176: [If amqpvalue_get_map_pair_count fails, the error shall be notified and ‘on_message_received' shall continue.]
AzureIoTClient 16:a49121e2300b 466 LogError("Failed reading the number of values in the uAMQP property map (return code %d).", result);
AzureIoTClient 16:a49121e2300b 467 result = __LINE__;
AzureIoTClient 16:a49121e2300b 468 }
AzureIoTClient 16:a49121e2300b 469 else
AzureIoTClient 16:a49121e2300b 470 {
AzureIoTClient 19:ea016664011a 471 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_177: [‘on_message_received' shall iterate through each uAMQP application property and add it on IOTHUB_MESSAGE_HANDLE properties.]
AzureIoTClient 19:ea016664011a 472 uint32_t i;
AzureIoTClient 16:a49121e2300b 473 for (i = 0; i < property_count; i++)
AzureIoTClient 16:a49121e2300b 474 {
AzureIoTClient 16:a49121e2300b 475 AMQP_VALUE map_key_name;
AzureIoTClient 16:a49121e2300b 476 AMQP_VALUE map_key_value;
AzureIoTClient 16:a49121e2300b 477 const char *key_name;
AzureIoTClient 16:a49121e2300b 478 const char* key_value;
AzureIoTClient 14:8e8e42008807 479
AzureIoTClient 16:a49121e2300b 480 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_178: [The uAMQP application property name and value shall be obtained using amqpvalue_get_map_key_value_pair.]
AzureIoTClient 16:a49121e2300b 481 if ((result = amqpvalue_get_map_key_value_pair(uamqp_app_properties, i, &map_key_name, &map_key_value)) != 0)
AzureIoTClient 16:a49121e2300b 482 {
AzureIoTClient 19:ea016664011a 483 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_179: [If amqpvalue_get_map_key_value_pair fails, the error shall be notified and ‘on_message_received' shall continue.]
AzureIoTClient 16:a49121e2300b 484 LogError("Failed reading the key/value pair from the uAMQP property map (return code %d).", result);
AzureIoTClient 16:a49121e2300b 485 result = __LINE__;
AzureIoTClient 16:a49121e2300b 486 break;
AzureIoTClient 16:a49121e2300b 487 }
AzureIoTClient 16:a49121e2300b 488 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_180: [The uAMQP application property name shall be extracted as string using amqpvalue_get_string.]
AzureIoTClient 16:a49121e2300b 489 else if ((result = amqpvalue_get_string(map_key_name, &key_name)) != 0)
AzureIoTClient 16:a49121e2300b 490 {
AzureIoTClient 19:ea016664011a 491 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_181: [If amqpvalue_get_string fails, the error shall be notified and ‘on_message_received' shall continue.]
AzureIoTClient 16:a49121e2300b 492 LogError("Failed parsing the uAMQP property name (return code %d).", result);
AzureIoTClient 16:a49121e2300b 493 result = __LINE__;
AzureIoTClient 16:a49121e2300b 494 break;
AzureIoTClient 16:a49121e2300b 495 }
AzureIoTClient 16:a49121e2300b 496 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_182: [The uAMQP application property value shall be extracted as string using amqpvalue_get_string.]
AzureIoTClient 16:a49121e2300b 497 else if ((result = amqpvalue_get_string(map_key_value, &key_value)) != 0)
AzureIoTClient 16:a49121e2300b 498 {
AzureIoTClient 19:ea016664011a 499 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_183: [If amqpvalue_get_string fails, the error shall be notified and ‘on_message_received' shall continue.]
AzureIoTClient 16:a49121e2300b 500 LogError("Failed parsing the uAMQP property value (return code %d).", result);
AzureIoTClient 16:a49121e2300b 501 result = __LINE__;
AzureIoTClient 16:a49121e2300b 502 break;
AzureIoTClient 16:a49121e2300b 503 }
AzureIoTClient 16:a49121e2300b 504 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_184: [The application property name and value shall be added to IOTHUB_MESSAGE_HANDLE properties using Map_AddOrUpdate.]
AzureIoTClient 16:a49121e2300b 505 else if (Map_AddOrUpdate(iothub_message_properties_map, key_name, key_value) != MAP_OK)
AzureIoTClient 16:a49121e2300b 506 {
AzureIoTClient 19:ea016664011a 507 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_185: [If Map_AddOrUpdate fails, the error shall be notified and ‘on_message_received' shall continue.]
AzureIoTClient 16:a49121e2300b 508 LogError("Failed to add/update IoTHub message property map.");
AzureIoTClient 16:a49121e2300b 509 result = __LINE__;
AzureIoTClient 16:a49121e2300b 510 break;
AzureIoTClient 16:a49121e2300b 511 }
AzureIoTClient 16:a49121e2300b 512 }
AzureIoTClient 16:a49121e2300b 513 }
AzureIoTClient 14:8e8e42008807 514
AzureIoTClient 16:a49121e2300b 515 return result;
AzureIoTClient 14:8e8e42008807 516 }
AzureIoTClient 14:8e8e42008807 517
Azure.IoT Build 10:75c5e0d8537d 518 static void on_message_send_complete(void* context, MESSAGE_SEND_RESULT send_result)
AzureIoTClient 4:57e049bce51e 519 {
AzureIoTClient 16:a49121e2300b 520 IOTHUB_MESSAGE_LIST* message = (IOTHUB_MESSAGE_LIST*)context;
Azure.IoT Build 10:75c5e0d8537d 521
Azure.IoT Build 10:75c5e0d8537d 522 IOTHUB_CLIENT_RESULT iot_hub_send_result;
Azure.IoT Build 10:75c5e0d8537d 523
Azure.IoT Build 10:75c5e0d8537d 524 // 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 525 if (send_result == MESSAGE_SEND_OK)
AzureIoTClient 4:57e049bce51e 526 {
Azure.IoT Build 10:75c5e0d8537d 527 iot_hub_send_result = IOTHUB_CLIENT_CONFIRMATION_OK;
Azure.IoT Build 10:75c5e0d8537d 528 }
Azure.IoT Build 10:75c5e0d8537d 529 // 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 530 else
Azure.IoT Build 10:75c5e0d8537d 531 {
Azure.IoT Build 10:75c5e0d8537d 532 iot_hub_send_result = IOTHUB_CLIENT_CONFIRMATION_ERROR;
Azure.IoT Build 10:75c5e0d8537d 533 }
Azure.IoT Build 7:07bc440836b3 534
Azure.IoT Build 10:75c5e0d8537d 535 // 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 536 if (message->callback != NULL)
Azure.IoT Build 10:75c5e0d8537d 537 {
Azure.IoT Build 12:841a4c36bd36 538 message->callback(iot_hub_send_result, message->context);
Azure.IoT Build 10:75c5e0d8537d 539 }
AzureIoTClient 4:57e049bce51e 540
AzureIoTClient 16:a49121e2300b 541 // 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]
AzureIoTClient 16:a49121e2300b 542 if (isEventInInProgressList(message))
AzureIoTClient 16:a49121e2300b 543 {
AzureIoTClient 16:a49121e2300b 544 removeEventFromInProgressList(message);
AzureIoTClient 16:a49121e2300b 545 }
Azure.IoT Build 12:841a4c36bd36 546
Azure.IoT Build 10:75c5e0d8537d 547 // 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 548 IoTHubMessage_Destroy(message->messageHandle);
AzureIoTClient 4:57e049bce51e 549
AzureIoTClient 16:a49121e2300b 550 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_152: [The callback 'on_message_send_complete' shall destroy the IOTHUB_MESSAGE_LIST instance]
Azure.IoT Build 12:841a4c36bd36 551 free(message);
AzureIoTClient 4:57e049bce51e 552 }
AzureIoTClient 4:57e049bce51e 553
Azure.IoT Build 10:75c5e0d8537d 554 static void on_put_token_complete(void* context, CBS_OPERATION_RESULT operation_result, unsigned int status_code, const char* status_description)
AzureIoTClient 4:57e049bce51e 555 {
Azure.IoT Build 7:07bc440836b3 556 AMQP_TRANSPORT_INSTANCE* transportState = (AMQP_TRANSPORT_INSTANCE*)context;
Azure.IoT Build 7:07bc440836b3 557
Azure.IoT Build 12:841a4c36bd36 558 if (operation_result == CBS_OPERATION_RESULT_OK)
AzureIoTClient 4:57e049bce51e 559 {
Azure.IoT Build 7:07bc440836b3 560 transportState->cbs_state = CBS_STATE_AUTHENTICATED;
Azure.IoT Build 7:07bc440836b3 561 }
AzureIoTClient 19:ea016664011a 562 else
AzureIoTClient 19:ea016664011a 563 {
AzureIoTClient 19:ea016664011a 564 LogError("CBS reported status %u error: %s", status_code, status_description);
AzureIoTClient 19:ea016664011a 565 }
Azure.IoT Build 7:07bc440836b3 566 }
Azure.IoT Build 7:07bc440836b3 567
Azure.IoT Build 10:75c5e0d8537d 568 static AMQP_VALUE on_message_received(const void* context, MESSAGE_HANDLE message)
Azure.IoT Build 7:07bc440836b3 569 {
Azure.IoT Build 7:07bc440836b3 570 AMQP_VALUE result = NULL;
Azure.IoT Build 7:07bc440836b3 571
Azure.IoT Build 10:75c5e0d8537d 572 // 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 573 IOTHUB_MESSAGE_HANDLE iothub_message = NULL;
Azure.IoT Build 7:07bc440836b3 574 MESSAGE_BODY_TYPE body_type;
Azure.IoT Build 11:62d7b956e76e 575
Azure.IoT Build 7:07bc440836b3 576 if (message_get_body_type(message, &body_type) != 0)
Azure.IoT Build 7:07bc440836b3 577 {
AzureIoTClient 13:a4af7c301e02 578 LogError("Failed to get the type of the message received by the transport.");
Azure.IoT Build 7:07bc440836b3 579 }
Azure.IoT Build 11:62d7b956e76e 580 else
Azure.IoT Build 7:07bc440836b3 581 {
Azure.IoT Build 7:07bc440836b3 582 if (body_type == MESSAGE_BODY_TYPE_DATA)
AzureIoTClient 4:57e049bce51e 583 {
Azure.IoT Build 7:07bc440836b3 584 BINARY_DATA binary_data;
Azure.IoT Build 7:07bc440836b3 585 if (message_get_body_amqp_data(message, 0, &binary_data) != 0)
Azure.IoT Build 7:07bc440836b3 586 {
AzureIoTClient 13:a4af7c301e02 587 LogError("Failed to get the body of the message received by the transport.");
Azure.IoT Build 7:07bc440836b3 588 }
Azure.IoT Build 7:07bc440836b3 589 else
Azure.IoT Build 7:07bc440836b3 590 {
Azure.IoT Build 7:07bc440836b3 591 iothub_message = IoTHubMessage_CreateFromByteArray(binary_data.bytes, binary_data.length);
Azure.IoT Build 7:07bc440836b3 592 }
AzureIoTClient 4:57e049bce51e 593 }
Azure.IoT Build 7:07bc440836b3 594 }
Azure.IoT Build 11:62d7b956e76e 595
Azure.IoT Build 7:07bc440836b3 596 if (iothub_message == NULL)
Azure.IoT Build 7:07bc440836b3 597 {
AzureIoTClient 13:a4af7c301e02 598 LogError("Transport failed processing the message received.");
AzureIoTClient 14:8e8e42008807 599
AzureIoTClient 16:a49121e2300b 600 result = messaging_delivery_rejected("Rejected due to failure reading AMQP message", "Failed reading message body");
Azure.IoT Build 7:07bc440836b3 601 }
AzureIoTClient 16:a49121e2300b 602 else
Azure.IoT Build 7:07bc440836b3 603 {
AzureIoTClient 19:ea016664011a 604 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_153: [The callback ‘on_message_received' shall read the message-id property from the uAMQP message and set it on the IoT Hub Message if the property is defined.] */
AzureIoTClient 19:ea016664011a 605 /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_154: [The callback ‘on_message_received' shall read the correlation-id property from the uAMQP message and set it on the IoT Hub Message if the property is defined.] */
AzureIoTClient 16:a49121e2300b 606 if (readPropertiesFromuAMQPMessage(iothub_message, message) != 0)
AzureIoTClient 16:a49121e2300b 607 {
AzureIoTClient 16:a49121e2300b 608 LogError("Transport failed reading properties of the message received.");
AzureIoTClient 16:a49121e2300b 609 }
AzureIoTClient 14:8e8e42008807 610
AzureIoTClient 19:ea016664011a 611 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_169: [The callback ‘on_message_received' shall read the application properties from the uAMQP message and set it on the IoT Hub Message if any are provided.]
AzureIoTClient 16:a49121e2300b 612 if (readApplicationPropertiesFromuAMQPMessage(iothub_message, message) != 0)
AzureIoTClient 16:a49121e2300b 613 {
AzureIoTClient 19:ea016664011a 614 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_188: [If ‘on_message_received' fails reading the application properties from the uAMQP message, it shall NOT call IoTHubClient_LL_MessageCallback and shall reject the message.]
AzureIoTClient 16:a49121e2300b 615 LogError("Transport failed reading application properties of the message received.");
AzureIoTClient 16:a49121e2300b 616
AzureIoTClient 16:a49121e2300b 617 result = messaging_delivery_rejected("Rejected due to failure reading AMQP message", "Failed reading application properties");
AzureIoTClient 16:a49121e2300b 618 }
AzureIoTClient 16:a49121e2300b 619 else
AzureIoTClient 16:a49121e2300b 620 {
AzureIoTClient 16:a49121e2300b 621 IOTHUBMESSAGE_DISPOSITION_RESULT disposition_result;
AzureIoTClient 14:8e8e42008807 622
Azure.IoT Build 7:07bc440836b3 623 disposition_result = IoTHubClient_LL_MessageCallback((IOTHUB_CLIENT_LL_HANDLE)context, iothub_message);
Azure.IoT Build 7:07bc440836b3 624
Azure.IoT Build 10:75c5e0d8537d 625 // 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 626 if (disposition_result == IOTHUBMESSAGE_ACCEPTED)
AzureIoTClient 5:8d58d20699dd 627 {
Azure.IoT Build 7:07bc440836b3 628 result = messaging_delivery_accepted();
Azure.IoT Build 7:07bc440836b3 629 }
Azure.IoT Build 10:75c5e0d8537d 630 // 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 631 else if (disposition_result == IOTHUBMESSAGE_ABANDONED)
Azure.IoT Build 7:07bc440836b3 632 {
Azure.IoT Build 7:07bc440836b3 633 result = messaging_delivery_released();
AzureIoTClient 5:8d58d20699dd 634 }
Azure.IoT Build 10:75c5e0d8537d 635 // 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 636 else if (disposition_result == IOTHUBMESSAGE_REJECTED)
AzureIoTClient 4:57e049bce51e 637 {
Azure.IoT Build 7:07bc440836b3 638 result = messaging_delivery_rejected("Rejected by application", "Rejected by application");
AzureIoTClient 4:57e049bce51e 639 }
AzureIoTClient 16:a49121e2300b 640 }
AzureIoTClient 14:8e8e42008807 641
Azure.IoT Build 11:62d7b956e76e 642 IoTHubMessage_Destroy(iothub_message);
Azure.IoT Build 7:07bc440836b3 643 }
Azure.IoT Build 7:07bc440836b3 644
Azure.IoT Build 7:07bc440836b3 645 return result;
Azure.IoT Build 7:07bc440836b3 646 }
Azure.IoT Build 7:07bc440836b3 647
Azure.IoT Build 11:62d7b956e76e 648 static XIO_HANDLE getTLSIOTransport(const char* fqdn, int port)
Azure.IoT Build 7:07bc440836b3 649 {
AzureIoTClient 19:ea016664011a 650 TLSIO_CONFIG tls_io_config;
AzureIoTClient 19:ea016664011a 651 tls_io_config.hostname = fqdn;
AzureIoTClient 19:ea016664011a 652 tls_io_config.port = port;
Azure.IoT Build 10:75c5e0d8537d 653 const IO_INTERFACE_DESCRIPTION* io_interface_description = platform_get_default_tlsio();
Azure.IoT Build 18:239d162e3607 654 return xio_create(io_interface_description, &tls_io_config);
Azure.IoT Build 7:07bc440836b3 655 }
Azure.IoT Build 7:07bc440836b3 656
Azure.IoT Build 7:07bc440836b3 657 static void destroyConnection(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 658 {
Azure.IoT Build 10:75c5e0d8537d 659 if (transport_state->cbs != NULL)
Azure.IoT Build 7:07bc440836b3 660 {
Azure.IoT Build 10:75c5e0d8537d 661 cbs_destroy(transport_state->cbs);
Azure.IoT Build 10:75c5e0d8537d 662 transport_state->cbs = NULL;
Azure.IoT Build 10:75c5e0d8537d 663 }
Azure.IoT Build 7:07bc440836b3 664
Azure.IoT Build 10:75c5e0d8537d 665 if (transport_state->session != NULL)
Azure.IoT Build 10:75c5e0d8537d 666 {
Azure.IoT Build 10:75c5e0d8537d 667 session_destroy(transport_state->session);
Azure.IoT Build 10:75c5e0d8537d 668 transport_state->session = NULL;
Azure.IoT Build 10:75c5e0d8537d 669 }
Azure.IoT Build 7:07bc440836b3 670
Azure.IoT Build 10:75c5e0d8537d 671 if (transport_state->connection != NULL)
Azure.IoT Build 10:75c5e0d8537d 672 {
Azure.IoT Build 10:75c5e0d8537d 673 connection_destroy(transport_state->connection);
Azure.IoT Build 10:75c5e0d8537d 674 transport_state->connection = NULL;
Azure.IoT Build 10:75c5e0d8537d 675 }
Azure.IoT Build 7:07bc440836b3 676
Azure.IoT Build 10:75c5e0d8537d 677 if (transport_state->sasl_io != NULL)
Azure.IoT Build 10:75c5e0d8537d 678 {
Azure.IoT Build 10:75c5e0d8537d 679 xio_destroy(transport_state->sasl_io);
Azure.IoT Build 10:75c5e0d8537d 680 transport_state->sasl_io = NULL;
Azure.IoT Build 10:75c5e0d8537d 681 }
Azure.IoT Build 7:07bc440836b3 682
Azure.IoT Build 10:75c5e0d8537d 683 if (transport_state->sasl_mechanism != NULL)
Azure.IoT Build 10:75c5e0d8537d 684 {
Azure.IoT Build 10:75c5e0d8537d 685 saslmechanism_destroy(transport_state->sasl_mechanism);
Azure.IoT Build 10:75c5e0d8537d 686 transport_state->sasl_mechanism = NULL;
Azure.IoT Build 10:75c5e0d8537d 687 }
Azure.IoT Build 7:07bc440836b3 688
Azure.IoT Build 10:75c5e0d8537d 689 if (transport_state->tls_io != NULL)
Azure.IoT Build 10:75c5e0d8537d 690 {
Azure.IoT Build 10:75c5e0d8537d 691 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_034: [IoTHubTransportAMQP_Destroy shall destroy the AMQP TLS I/O transport.]
Azure.IoT Build 10:75c5e0d8537d 692 xio_destroy(transport_state->tls_io);
Azure.IoT Build 10:75c5e0d8537d 693 transport_state->tls_io = NULL;
Azure.IoT Build 10:75c5e0d8537d 694 }
Azure.IoT Build 7:07bc440836b3 695 }
Azure.IoT Build 7:07bc440836b3 696
Azure.IoT Build 7:07bc440836b3 697 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 698 {
Azure.IoT Build 10:75c5e0d8537d 699 (void)previous_amqp_management_state;
Azure.IoT Build 10:75c5e0d8537d 700 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)context;
Azure.IoT Build 11:62d7b956e76e 701
Azure.IoT Build 10:75c5e0d8537d 702 if (transport_state != NULL)
Azure.IoT Build 7:07bc440836b3 703 {
Azure.IoT Build 7:07bc440836b3 704 transport_state->connection_state = new_amqp_management_state;
Azure.IoT Build 7:07bc440836b3 705 }
Azure.IoT Build 7:07bc440836b3 706 }
Azure.IoT Build 7:07bc440836b3 707
AzureIoTClient 13:a4af7c301e02 708 static void on_connection_io_error(void* context)
AzureIoTClient 13:a4af7c301e02 709 {
AzureIoTClient 16:a49121e2300b 710 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)context;
AzureIoTClient 13:a4af7c301e02 711
AzureIoTClient 16:a49121e2300b 712 if (transport_state != NULL)
AzureIoTClient 16:a49121e2300b 713 {
AzureIoTClient 16:a49121e2300b 714 transport_state->connection_state = AMQP_MANAGEMENT_STATE_ERROR;
AzureIoTClient 16:a49121e2300b 715 }
AzureIoTClient 13:a4af7c301e02 716 }
AzureIoTClient 13:a4af7c301e02 717
Azure.IoT Build 7:07bc440836b3 718 static int establishConnection(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 719 {
Azure.IoT Build 7:07bc440836b3 720 int result;
Azure.IoT Build 7:07bc440836b3 721
Azure.IoT Build 7:07bc440836b3 722 // 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 723 if (transport_state->tls_io == NULL &&
Azure.IoT Build 11:62d7b956e76e 724 (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 725 {
Azure.IoT Build 7:07bc440836b3 726 // 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 727 result = RESULT_FAILURE;
AzureIoTClient 13:a4af7c301e02 728 LogError("Failed to obtain a TLS I/O transport layer.");
Azure.IoT Build 7:07bc440836b3 729 }
Azure.IoT Build 10:75c5e0d8537d 730 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_056: [IoTHubTransportAMQP_DoWork shall create the SASL mechanism using AMQP's saslmechanism_create() API]
Azure.IoT Build 7:07bc440836b3 731 else if ((transport_state->sasl_mechanism = saslmechanism_create(saslmssbcbs_get_interface(), NULL)) == NULL)
Azure.IoT Build 7:07bc440836b3 732 {
Azure.IoT Build 7:07bc440836b3 733 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_057: [If saslmechanism_create() fails, IoTHubTransportAMQP_DoWork shall fail and return immediately]
Azure.IoT Build 7:07bc440836b3 734 result = RESULT_FAILURE;
AzureIoTClient 13:a4af7c301e02 735 LogError("Failed to create a SASL mechanism.");
Azure.IoT Build 7:07bc440836b3 736 }
Azure.IoT Build 7:07bc440836b3 737 else
Azure.IoT Build 7:07bc440836b3 738 {
Azure.IoT Build 7:07bc440836b3 739 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_060: [IoTHubTransportAMQP_DoWork shall create the SASL I / O layer using the xio_create() C Shared Utility API]
AzureIoTClient 19:ea016664011a 740 SASLCLIENTIO_CONFIG sasl_client_config;
AzureIoTClient 19:ea016664011a 741 sasl_client_config.sasl_mechanism = transport_state->sasl_mechanism;
AzureIoTClient 19:ea016664011a 742 sasl_client_config.underlying_io = transport_state->tls_io;
Azure.IoT Build 18:239d162e3607 743 if ((transport_state->sasl_io = xio_create(saslclientio_get_interface_description(), &sasl_client_config)) == NULL)
AzureIoTClient 4:57e049bce51e 744 {
Azure.IoT Build 7:07bc440836b3 745 // 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 746 result = RESULT_FAILURE;
AzureIoTClient 13:a4af7c301e02 747 LogError("Failed to create a SASL I/O layer.");
AzureIoTClient 4:57e049bce51e 748 }
AzureIoTClient 13:a4af7c301e02 749 // 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)]
Azure.IoT Build 18:239d162e3607 750 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)
AzureIoTClient 4:57e049bce51e 751 {
AzureIoTClient 13:a4af7c301e02 752 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_063: [If connection_create2() fails, IoTHubTransportAMQP_DoWork shall fail and return immediately.]
Azure.IoT Build 7:07bc440836b3 753 result = RESULT_FAILURE;
AzureIoTClient 13:a4af7c301e02 754 LogError("Failed to create the AMQP connection.");
Azure.IoT Build 7:07bc440836b3 755 }
Azure.IoT Build 7:07bc440836b3 756 // 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 757 else if ((transport_state->session = session_create(transport_state->connection, NULL, NULL)) == NULL)
Azure.IoT Build 7:07bc440836b3 758 {
Azure.IoT Build 7:07bc440836b3 759 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_138 : [If session_create() fails, IoTHubTransportAMQP_DoWork shall fail and return immediately]
Azure.IoT Build 7:07bc440836b3 760 result = RESULT_FAILURE;
AzureIoTClient 13:a4af7c301e02 761 LogError("Failed to create the AMQP session.");
AzureIoTClient 4:57e049bce51e 762 }
AzureIoTClient 4:57e049bce51e 763 else
AzureIoTClient 4:57e049bce51e 764 {
Azure.IoT Build 10:75c5e0d8537d 765 // 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 766 if (session_set_incoming_window(transport_state->session, (uint32_t)DEFAULT_INCOMING_WINDOW_SIZE) != 0)
Azure.IoT Build 7:07bc440836b3 767 {
AzureIoTClient 13:a4af7c301e02 768 LogError("Failed to set the AMQP incoming window size.");
Azure.IoT Build 7:07bc440836b3 769 }
Azure.IoT Build 7:07bc440836b3 770
Azure.IoT Build 10:75c5e0d8537d 771 // 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 772 if (session_set_outgoing_window(transport_state->session, DEFAULT_OUTGOING_WINDOW_SIZE) != 0)
Azure.IoT Build 7:07bc440836b3 773 {
AzureIoTClient 13:a4af7c301e02 774 LogError("Failed to set the AMQP outgoing window size.");
Azure.IoT Build 7:07bc440836b3 775 }
Azure.IoT Build 7:07bc440836b3 776
Azure.IoT Build 7:07bc440836b3 777 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_066: [IoTHubTransportAMQP_DoWork shall establish the CBS connection using the cbs_create() AMQP API]
Azure.IoT Build 7:07bc440836b3 778 if ((transport_state->cbs = cbs_create(transport_state->session, on_amqp_management_state_changed, NULL)) == NULL)
AzureIoTClient 4:57e049bce51e 779 {
Azure.IoT Build 7:07bc440836b3 780 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_067: [If cbs_create() fails, IoTHubTransportAMQP_DoWork shall fail and return immediately]
Azure.IoT Build 7:07bc440836b3 781 result = RESULT_FAILURE;
AzureIoTClient 13:a4af7c301e02 782 LogError("Failed to create the CBS connection.");
Azure.IoT Build 7:07bc440836b3 783 }
Azure.IoT Build 7:07bc440836b3 784 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_139: [IoTHubTransportAMQP_DoWork shall open the CBS connection using the cbs_open() AMQP API]
Azure.IoT Build 10:75c5e0d8537d 785 else if (cbs_open(transport_state->cbs) != 0)
Azure.IoT Build 7:07bc440836b3 786 {
Azure.IoT Build 7:07bc440836b3 787 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_140: [If cbs_open() fails, IoTHubTransportAMQP_DoWork shall fail and return immediately]
Azure.IoT Build 7:07bc440836b3 788 result = RESULT_FAILURE;
AzureIoTClient 13:a4af7c301e02 789 LogError("Failed to open the connection with CBS.");
Azure.IoT Build 7:07bc440836b3 790 }
Azure.IoT Build 7:07bc440836b3 791 else
Azure.IoT Build 7:07bc440836b3 792 {
Azure.IoT Build 7:07bc440836b3 793 transport_state->connection_establish_time = getSecondsSinceEpoch();
Azure.IoT Build 7:07bc440836b3 794 transport_state->cbs_state = CBS_STATE_IDLE;
AzureIoTClient 16:a49121e2300b 795 connection_set_trace(transport_state->connection, transport_state->is_trace_on);
AzureIoTClient 19:ea016664011a 796 (void)xio_setoption(transport_state->sasl_io, "logtrace", &transport_state->is_trace_on);
Azure.IoT Build 7:07bc440836b3 797 result = RESULT_OK;
AzureIoTClient 4:57e049bce51e 798 }
AzureIoTClient 4:57e049bce51e 799 }
AzureIoTClient 4:57e049bce51e 800 }
Azure.IoT Build 7:07bc440836b3 801
Azure.IoT Build 7:07bc440836b3 802 if (result == RESULT_FAILURE)
Azure.IoT Build 7:07bc440836b3 803 {
Azure.IoT Build 7:07bc440836b3 804 destroyConnection(transport_state);
Azure.IoT Build 7:07bc440836b3 805 }
Azure.IoT Build 7:07bc440836b3 806
Azure.IoT Build 7:07bc440836b3 807 return result;
AzureIoTClient 4:57e049bce51e 808 }
AzureIoTClient 4:57e049bce51e 809
AzureIoTClient 19:ea016664011a 810 static int handSASTokenToCbs(AMQP_TRANSPORT_INSTANCE* transport_state, STRING_HANDLE sasToken, size_t sas_token_create_time)
AzureIoTClient 19:ea016664011a 811 {
AzureIoTClient 19:ea016664011a 812 int result;
AzureIoTClient 19:ea016664011a 813 if (cbs_put_token(transport_state->cbs, CBS_AUDIENCE, STRING_c_str(transport_state->devicesPath), STRING_c_str(sasToken), on_put_token_complete, transport_state) != RESULT_OK)
AzureIoTClient 19:ea016664011a 814 {
AzureIoTClient 19:ea016664011a 815 LogError("Failed applying new SAS token to CBS.");
AzureIoTClient 19:ea016664011a 816 result = __LINE__;
AzureIoTClient 19:ea016664011a 817 }
AzureIoTClient 19:ea016664011a 818 else
AzureIoTClient 19:ea016664011a 819 {
AzureIoTClient 19:ea016664011a 820 transport_state->cbs_state = CBS_STATE_AUTH_IN_PROGRESS;
AzureIoTClient 19:ea016664011a 821 transport_state->current_sas_token_create_time = sas_token_create_time;
AzureIoTClient 19:ea016664011a 822 result = RESULT_OK;
AzureIoTClient 19:ea016664011a 823 }
AzureIoTClient 19:ea016664011a 824 return result;
AzureIoTClient 19:ea016664011a 825 }
AzureIoTClient 19:ea016664011a 826
Azure.IoT Build 7:07bc440836b3 827 static int startAuthentication(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 828 {
Azure.IoT Build 10:75c5e0d8537d 829 int result;
Azure.IoT Build 7:07bc440836b3 830
Azure.IoT Build 7:07bc440836b3 831 size_t sas_token_create_time = getSecondsSinceEpoch(); // I.e.: NOW, in seconds since epoch.
Azure.IoT Build 11:62d7b956e76e 832
Azure.IoT Build 11:62d7b956e76e 833 // 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 834 size_t new_expiry_time = sas_token_create_time + (transport_state->sas_token_lifetime / 1000);
Azure.IoT Build 7:07bc440836b3 835
AzureIoTClient 16:a49121e2300b 836 STRING_HANDLE newSASToken;
AzureIoTClient 14:8e8e42008807 837
AzureIoTClient 19:ea016664011a 838 switch (transport_state->credential.credentialType)
Azure.IoT Build 7:07bc440836b3 839 {
AzureIoTClient 19:ea016664011a 840 default:
AzureIoTClient 19:ea016664011a 841 {
AzureIoTClient 19:ea016664011a 842 result = __LINE__;
AzureIoTClient 19:ea016664011a 843 LogError("internal error, unexpected enum value transport_state->credential.credentialType=%d", transport_state->credential.credentialType);
AzureIoTClient 19:ea016664011a 844 break;
AzureIoTClient 19:ea016664011a 845 }
AzureIoTClient 19:ea016664011a 846 case DEVICE_KEY:
AzureIoTClient 19:ea016664011a 847 {
AzureIoTClient 19:ea016664011a 848 newSASToken = SASToken_Create(transport_state->credential.credential.deviceKey, transport_state->devicesPath, transport_state->sasTokenKeyName, new_expiry_time);
AzureIoTClient 19:ea016664011a 849 if (newSASToken == NULL)
AzureIoTClient 19:ea016664011a 850 {
AzureIoTClient 19:ea016664011a 851 LogError("Could not generate a new SAS token for the CBS.");
AzureIoTClient 19:ea016664011a 852 result = RESULT_FAILURE;
AzureIoTClient 19:ea016664011a 853 }
AzureIoTClient 19:ea016664011a 854 else
AzureIoTClient 19:ea016664011a 855 {
AzureIoTClient 19:ea016664011a 856 if (handSASTokenToCbs(transport_state, newSASToken, sas_token_create_time) != 0)
AzureIoTClient 19:ea016664011a 857 {
AzureIoTClient 19:ea016664011a 858 LogError("unable to handSASTokenToCbs");
AzureIoTClient 19:ea016664011a 859 result = RESULT_FAILURE;
AzureIoTClient 19:ea016664011a 860 }
AzureIoTClient 19:ea016664011a 861 else
AzureIoTClient 19:ea016664011a 862 {
AzureIoTClient 19:ea016664011a 863 result = RESULT_OK;
AzureIoTClient 19:ea016664011a 864 }
AzureIoTClient 19:ea016664011a 865
AzureIoTClient 19:ea016664011a 866 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_145: [Each new SAS token created shall be deleted from memory immediately after sending it to CBS]
AzureIoTClient 19:ea016664011a 867 STRING_delete(newSASToken);
AzureIoTClient 19:ea016664011a 868 }
AzureIoTClient 19:ea016664011a 869 break;
AzureIoTClient 19:ea016664011a 870 }
AzureIoTClient 19:ea016664011a 871 case DEVICE_SAS_TOKEN:
AzureIoTClient 19:ea016664011a 872 {
AzureIoTClient 19:ea016664011a 873 newSASToken = STRING_clone(transport_state->credential.credential.deviceSasToken);
AzureIoTClient 19:ea016664011a 874 if (newSASToken == NULL)
AzureIoTClient 19:ea016664011a 875 {
AzureIoTClient 19:ea016664011a 876 LogError("Could not generate a new SAS token for the CBS.");
AzureIoTClient 19:ea016664011a 877 result = RESULT_FAILURE;
AzureIoTClient 19:ea016664011a 878 }
AzureIoTClient 19:ea016664011a 879 else
AzureIoTClient 19:ea016664011a 880 {
AzureIoTClient 19:ea016664011a 881 if (handSASTokenToCbs(transport_state, newSASToken, sas_token_create_time) != 0)
AzureIoTClient 19:ea016664011a 882 {
AzureIoTClient 19:ea016664011a 883 LogError("unable to handSASTokenToCbs");
AzureIoTClient 19:ea016664011a 884 result = RESULT_FAILURE;
AzureIoTClient 19:ea016664011a 885 }
AzureIoTClient 19:ea016664011a 886 else
AzureIoTClient 19:ea016664011a 887 {
AzureIoTClient 19:ea016664011a 888 result = RESULT_OK;
AzureIoTClient 19:ea016664011a 889 }
AzureIoTClient 19:ea016664011a 890
AzureIoTClient 19:ea016664011a 891 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_145: [Each new SAS token created shall be deleted from memory immediately after sending it to CBS]
AzureIoTClient 19:ea016664011a 892 STRING_delete(newSASToken);
AzureIoTClient 19:ea016664011a 893 }
AzureIoTClient 19:ea016664011a 894 break;
AzureIoTClient 19:ea016664011a 895 }
AzureIoTClient 4:57e049bce51e 896 }
AzureIoTClient 4:57e049bce51e 897 return result;
AzureIoTClient 4:57e049bce51e 898 }
AzureIoTClient 4:57e049bce51e 899
Azure.IoT Build 7:07bc440836b3 900 static int verifyAuthenticationTimeout(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 901 {
Azure.IoT Build 7:07bc440836b3 902 return ((getSecondsSinceEpoch() - transport_state->current_sas_token_create_time) * 1000 >= transport_state->cbs_request_timeout) ? RESULT_TIMEOUT : RESULT_OK;
Azure.IoT Build 7:07bc440836b3 903 }
AzureIoTClient 4:57e049bce51e 904
Azure.IoT Build 7:07bc440836b3 905 static void attachDeviceClientTypeToLink(LINK_HANDLE link)
Azure.IoT Build 7:07bc440836b3 906 {
Azure.IoT Build 10:75c5e0d8537d 907 fields attach_properties;
Azure.IoT Build 10:75c5e0d8537d 908 AMQP_VALUE deviceClientTypeKeyName;
Azure.IoT Build 10:75c5e0d8537d 909 AMQP_VALUE deviceClientTypeValue;
Azure.IoT Build 7:07bc440836b3 910 int result;
Azure.IoT Build 7:07bc440836b3 911
Azure.IoT Build 7:07bc440836b3 912 //
Azure.IoT Build 7:07bc440836b3 913 // Attempt to add the device client type string to the attach properties.
Azure.IoT Build 7:07bc440836b3 914 // If this doesn't happen, well, this isn't that important. We can operate
Azure.IoT Build 7:07bc440836b3 915 // without this property. It's worth noting that even though we are going
Azure.IoT Build 7:07bc440836b3 916 // on, the reasons any of these operations fail don't bode well for the
Azure.IoT Build 7:07bc440836b3 917 // actual upcoming attach.
Azure.IoT Build 7:07bc440836b3 918 //
Azure.IoT Build 7:07bc440836b3 919
Azure.IoT Build 7:07bc440836b3 920 // 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 921
Azure.IoT Build 7:07bc440836b3 922 if ((attach_properties = amqpvalue_create_map()) == NULL)
AzureIoTClient 4:57e049bce51e 923 {
AzureIoTClient 13:a4af7c301e02 924 LogError("Failed to create the map for device client type.");
AzureIoTClient 4:57e049bce51e 925 }
Azure.IoT Build 10:75c5e0d8537d 926 else
Azure.IoT Build 7:07bc440836b3 927 {
Azure.IoT Build 10:75c5e0d8537d 928 if ((deviceClientTypeKeyName = amqpvalue_create_symbol("com.microsoft:client-version")) == NULL)
Azure.IoT Build 10:75c5e0d8537d 929 {
AzureIoTClient 13:a4af7c301e02 930 LogError("Failed to create the key name for the device client type.");
Azure.IoT Build 10:75c5e0d8537d 931 }
Azure.IoT Build 10:75c5e0d8537d 932 else
Azure.IoT Build 10:75c5e0d8537d 933 {
Azure.IoT Build 10:75c5e0d8537d 934 if ((deviceClientTypeValue = amqpvalue_create_string(CLIENT_DEVICE_TYPE_PREFIX CLIENT_DEVICE_BACKSLASH IOTHUB_SDK_VERSION)) == NULL)
Azure.IoT Build 10:75c5e0d8537d 935 {
AzureIoTClient 13:a4af7c301e02 936 LogError("Failed to create the key value for the device client type.");
Azure.IoT Build 10:75c5e0d8537d 937 }
Azure.IoT Build 10:75c5e0d8537d 938 else
Azure.IoT Build 10:75c5e0d8537d 939 {
Azure.IoT Build 10:75c5e0d8537d 940 if ((result = amqpvalue_set_map_value(attach_properties, deviceClientTypeKeyName, deviceClientTypeValue)) != 0)
Azure.IoT Build 10:75c5e0d8537d 941 {
AzureIoTClient 13:a4af7c301e02 942 LogError("Failed to set the property map for the device client type. Error code is: %d", result);
Azure.IoT Build 10:75c5e0d8537d 943 }
Azure.IoT Build 10:75c5e0d8537d 944 else if ((result = link_set_attach_properties(link, attach_properties)) != 0)
Azure.IoT Build 10:75c5e0d8537d 945 {
AzureIoTClient 13:a4af7c301e02 946 LogError("Unable to attach the device client type to the link properties. Error code is: %d", result);
Azure.IoT Build 10:75c5e0d8537d 947 }
Azure.IoT Build 10:75c5e0d8537d 948
Azure.IoT Build 10:75c5e0d8537d 949 amqpvalue_destroy(deviceClientTypeValue);
Azure.IoT Build 10:75c5e0d8537d 950 }
Azure.IoT Build 10:75c5e0d8537d 951
Azure.IoT Build 10:75c5e0d8537d 952 amqpvalue_destroy(deviceClientTypeKeyName);
Azure.IoT Build 10:75c5e0d8537d 953 }
Azure.IoT Build 10:75c5e0d8537d 954
Azure.IoT Build 10:75c5e0d8537d 955 amqpvalue_destroy(attach_properties);
AzureIoTClient 4:57e049bce51e 956 }
Azure.IoT Build 7:07bc440836b3 957 }
Azure.IoT Build 7:07bc440836b3 958
Azure.IoT Build 10:75c5e0d8537d 959 static void destroyEventSender(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 960 {
Azure.IoT Build 7:07bc440836b3 961 if (transport_state->message_sender != NULL)
Azure.IoT Build 7:07bc440836b3 962 {
Azure.IoT Build 7:07bc440836b3 963 messagesender_destroy(transport_state->message_sender);
Azure.IoT Build 7:07bc440836b3 964 transport_state->message_sender = NULL;
Azure.IoT Build 7:07bc440836b3 965
Azure.IoT Build 7:07bc440836b3 966 link_destroy(transport_state->sender_link);
Azure.IoT Build 7:07bc440836b3 967 transport_state->sender_link = NULL;
AzureIoTClient 4:57e049bce51e 968 }
AzureIoTClient 4:57e049bce51e 969 }
AzureIoTClient 4:57e049bce51e 970
AzureIoTClient 13:a4af7c301e02 971 void on_event_sender_state_changed(void* context, MESSAGE_SENDER_STATE new_state, MESSAGE_SENDER_STATE previous_state)
AzureIoTClient 13:a4af7c301e02 972 {
AzureIoTClient 19:ea016664011a 973 (void)context;
AzureIoTClient 19:ea016664011a 974 (void)new_state;
AzureIoTClient 19:ea016664011a 975 (void)previous_state;
AzureIoTClient 13:a4af7c301e02 976 }
AzureIoTClient 13:a4af7c301e02 977
Azure.IoT Build 7:07bc440836b3 978 static int createEventSender(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 979 {
Azure.IoT Build 7:07bc440836b3 980 int result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 981
Azure.IoT Build 7:07bc440836b3 982 if (transport_state->message_sender == NULL)
AzureIoTClient 4:57e049bce51e 983 {
Azure.IoT Build 7:07bc440836b3 984 AMQP_VALUE source = NULL;
Azure.IoT Build 7:07bc440836b3 985 AMQP_VALUE target = NULL;
Azure.IoT Build 7:07bc440836b3 986
Azure.IoT Build 10:75c5e0d8537d 987 // 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 988 if ((source = messaging_create_source(MESSAGE_SENDER_SOURCE_ADDRESS)) == NULL)
AzureIoTClient 4:57e049bce51e 989 {
AzureIoTClient 13:a4af7c301e02 990 LogError("Failed creating AMQP messaging source attribute.");
AzureIoTClient 4:57e049bce51e 991 }
Azure.IoT Build 7:07bc440836b3 992 else if ((target = messaging_create_target(STRING_c_str(transport_state->targetAddress))) == NULL)
AzureIoTClient 4:57e049bce51e 993 {
AzureIoTClient 13:a4af7c301e02 994 LogError("Failed creating AMQP messaging target attribute.");
Azure.IoT Build 7:07bc440836b3 995 }
Azure.IoT Build 7:07bc440836b3 996 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 997 {
Azure.IoT Build 7:07bc440836b3 998 // 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 999 LogError("Failed creating AMQP link for message sender.");
AzureIoTClient 4:57e049bce51e 1000 }
AzureIoTClient 4:57e049bce51e 1001 else
AzureIoTClient 4:57e049bce51e 1002 {
Azure.IoT Build 10:75c5e0d8537d 1003 // 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 1004 if (link_set_max_message_size(transport_state->sender_link, MESSAGE_SENDER_MAX_LINK_SIZE) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1005 {
AzureIoTClient 13:a4af7c301e02 1006 LogError("Failed setting AMQP link max message size.");
Azure.IoT Build 7:07bc440836b3 1007 }
Azure.IoT Build 7:07bc440836b3 1008
Azure.IoT Build 7:07bc440836b3 1009 attachDeviceClientTypeToLink(transport_state->sender_link);
Azure.IoT Build 7:07bc440836b3 1010
Azure.IoT Build 7:07bc440836b3 1011 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_070: [IoTHubTransportAMQP_DoWork shall create the AMQP message sender using messagesender_create() AMQP API]
Azure.IoT Build 18:239d162e3607 1012 if ((transport_state->message_sender = messagesender_create(transport_state->sender_link, on_event_sender_state_changed, (void*)transport_state)) == NULL)
Azure.IoT Build 7:07bc440836b3 1013 {
Azure.IoT Build 7:07bc440836b3 1014 // 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 1015 LogError("Could not allocate AMQP message sender");
Azure.IoT Build 7:07bc440836b3 1016 }
Azure.IoT Build 7:07bc440836b3 1017 else
Azure.IoT Build 7:07bc440836b3 1018 {
Azure.IoT Build 7:07bc440836b3 1019 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_072: [IoTHubTransportAMQP_DoWork shall open the AMQP message sender using messagesender_open() AMQP API]
Azure.IoT Build 7:07bc440836b3 1020 if (messagesender_open(transport_state->message_sender) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1021 {
Azure.IoT Build 7:07bc440836b3 1022 // 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 1023 LogError("Failed opening the AMQP message sender.");
Azure.IoT Build 7:07bc440836b3 1024 }
Azure.IoT Build 7:07bc440836b3 1025 else
Azure.IoT Build 7:07bc440836b3 1026 {
Azure.IoT Build 7:07bc440836b3 1027 result = RESULT_OK;
Azure.IoT Build 7:07bc440836b3 1028 }
Azure.IoT Build 7:07bc440836b3 1029 }
AzureIoTClient 4:57e049bce51e 1030 }
Azure.IoT Build 7:07bc440836b3 1031
Azure.IoT Build 7:07bc440836b3 1032 if (source != NULL)
Azure.IoT Build 7:07bc440836b3 1033 amqpvalue_destroy(source);
Azure.IoT Build 7:07bc440836b3 1034 if (target != NULL)
Azure.IoT Build 7:07bc440836b3 1035 amqpvalue_destroy(target);
AzureIoTClient 4:57e049bce51e 1036 }
Azure.IoT Build 11:62d7b956e76e 1037
Azure.IoT Build 7:07bc440836b3 1038 return result;
AzureIoTClient 4:57e049bce51e 1039 }
Azure.IoT Build 7:07bc440836b3 1040
Azure.IoT Build 7:07bc440836b3 1041 static int destroyMessageReceiver(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 1042 {
Azure.IoT Build 7:07bc440836b3 1043 int result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 1044
Azure.IoT Build 7:07bc440836b3 1045 if (transport_state->message_receiver != NULL)
AzureIoTClient 4:57e049bce51e 1046 {
Azure.IoT Build 7:07bc440836b3 1047 if (messagereceiver_close(transport_state->message_receiver) != RESULT_OK)
AzureIoTClient 4:57e049bce51e 1048 {
AzureIoTClient 13:a4af7c301e02 1049 LogError("Failed closing the AMQP message receiver.");
Azure.IoT Build 7:07bc440836b3 1050 }
Azure.IoT Build 7:07bc440836b3 1051
Azure.IoT Build 7:07bc440836b3 1052 messagereceiver_destroy(transport_state->message_receiver);
Azure.IoT Build 7:07bc440836b3 1053
Azure.IoT Build 7:07bc440836b3 1054 transport_state->message_receiver = NULL;
Azure.IoT Build 7:07bc440836b3 1055
Azure.IoT Build 7:07bc440836b3 1056 link_destroy(transport_state->receiver_link);
Azure.IoT Build 7:07bc440836b3 1057
Azure.IoT Build 7:07bc440836b3 1058 transport_state->receiver_link = NULL;
Azure.IoT Build 7:07bc440836b3 1059
Azure.IoT Build 7:07bc440836b3 1060 result = RESULT_OK;
Azure.IoT Build 7:07bc440836b3 1061 }
Azure.IoT Build 7:07bc440836b3 1062
Azure.IoT Build 7:07bc440836b3 1063 return result;
Azure.IoT Build 7:07bc440836b3 1064 }
Azure.IoT Build 7:07bc440836b3 1065
Azure.IoT Build 7:07bc440836b3 1066 static int createMessageReceiver(AMQP_TRANSPORT_INSTANCE* transport_state, IOTHUB_CLIENT_LL_HANDLE iothub_client_handle)
Azure.IoT Build 7:07bc440836b3 1067 {
Azure.IoT Build 7:07bc440836b3 1068 int result = RESULT_FAILURE;
Azure.IoT Build 7:07bc440836b3 1069
AzureIoTClient 14:8e8e42008807 1070 if (transport_state->message_receiver == NULL)
Azure.IoT Build 7:07bc440836b3 1071 {
Azure.IoT Build 7:07bc440836b3 1072 AMQP_VALUE source = NULL;
Azure.IoT Build 7:07bc440836b3 1073 AMQP_VALUE target = NULL;
Azure.IoT Build 7:07bc440836b3 1074
Azure.IoT Build 10:75c5e0d8537d 1075 // 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 1076 if ((source = messaging_create_source(STRING_c_str(transport_state->messageReceiveAddress))) == NULL)
Azure.IoT Build 7:07bc440836b3 1077 {
AzureIoTClient 13:a4af7c301e02 1078 LogError("Failed creating AMQP message receiver source attribute.");
Azure.IoT Build 7:07bc440836b3 1079 }
Azure.IoT Build 7:07bc440836b3 1080 else if ((target = messaging_create_target(MESSAGE_RECEIVER_TARGET_ADDRESS)) == NULL)
Azure.IoT Build 7:07bc440836b3 1081 {
AzureIoTClient 13:a4af7c301e02 1082 LogError("Failed creating AMQP message receiver target attribute.");
Azure.IoT Build 7:07bc440836b3 1083 }
Azure.IoT Build 7:07bc440836b3 1084 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 1085 {
Azure.IoT Build 7:07bc440836b3 1086 // 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 1087 LogError("Failed creating AMQP link for message receiver.");
Azure.IoT Build 7:07bc440836b3 1088 }
Azure.IoT Build 7:07bc440836b3 1089 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_076: [IoTHubTransportAMQP_DoWork shall set the receiver link settle mode as receiver_settle_mode_first]
Azure.IoT Build 7:07bc440836b3 1090 else if (link_set_rcv_settle_mode(transport_state->receiver_link, receiver_settle_mode_first) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1091 {
Azure.IoT Build 7:07bc440836b3 1092 // 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 1093 LogError("Failed setting AMQP link settle mode for message receiver.");
AzureIoTClient 4:57e049bce51e 1094 }
AzureIoTClient 4:57e049bce51e 1095 else
AzureIoTClient 4:57e049bce51e 1096 {
Azure.IoT Build 10:75c5e0d8537d 1097 // 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 1098 if (link_set_max_message_size(transport_state->receiver_link, MESSAGE_RECEIVER_MAX_LINK_SIZE) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1099 {
AzureIoTClient 13:a4af7c301e02 1100 LogError("Failed setting AMQP link max message size for message receiver.");
Azure.IoT Build 7:07bc440836b3 1101 }
Azure.IoT Build 7:07bc440836b3 1102
Azure.IoT Build 7:07bc440836b3 1103 attachDeviceClientTypeToLink(transport_state->receiver_link);
AzureIoTClient 4:57e049bce51e 1104
Azure.IoT Build 7:07bc440836b3 1105 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_077: [IoTHubTransportAMQP_DoWork shall create the AMQP message receiver using messagereceiver_create() AMQP API]
Azure.IoT Build 7:07bc440836b3 1106 if ((transport_state->message_receiver = messagereceiver_create(transport_state->receiver_link, NULL, NULL)) == NULL)
Azure.IoT Build 7:07bc440836b3 1107 {
Azure.IoT Build 7:07bc440836b3 1108 // 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 1109 LogError("Could not allocate AMQP message receiver.");
Azure.IoT Build 7:07bc440836b3 1110 }
Azure.IoT Build 7:07bc440836b3 1111 else
AzureIoTClient 4:57e049bce51e 1112 {
Azure.IoT Build 7:07bc440836b3 1113 // 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 1114 // 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 1115 if (messagereceiver_open(transport_state->message_receiver, on_message_received, (const void*)iothub_client_handle) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1116 {
Azure.IoT Build 7:07bc440836b3 1117 // 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 1118 LogError("Failed opening the AMQP message receiver.");
Azure.IoT Build 7:07bc440836b3 1119 }
Azure.IoT Build 7:07bc440836b3 1120 else
Azure.IoT Build 7:07bc440836b3 1121 {
Azure.IoT Build 7:07bc440836b3 1122 result = RESULT_OK;
Azure.IoT Build 7:07bc440836b3 1123 }
AzureIoTClient 4:57e049bce51e 1124 }
AzureIoTClient 4:57e049bce51e 1125 }
Azure.IoT Build 7:07bc440836b3 1126
Azure.IoT Build 7:07bc440836b3 1127 if (source != NULL)
Azure.IoT Build 7:07bc440836b3 1128 amqpvalue_destroy(source);
Azure.IoT Build 7:07bc440836b3 1129 if (target != NULL)
Azure.IoT Build 7:07bc440836b3 1130 amqpvalue_destroy(target);
AzureIoTClient 4:57e049bce51e 1131 }
Azure.IoT Build 7:07bc440836b3 1132
Azure.IoT Build 7:07bc440836b3 1133 return result;
AzureIoTClient 4:57e049bce51e 1134 }
AzureIoTClient 4:57e049bce51e 1135
Azure.IoT Build 7:07bc440836b3 1136 static int sendPendingEvents(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 4:57e049bce51e 1137 {
Azure.IoT Build 7:07bc440836b3 1138 int result = RESULT_OK;
Azure.IoT Build 10:75c5e0d8537d 1139 IOTHUB_MESSAGE_LIST* message;
Azure.IoT Build 7:07bc440836b3 1140
Azure.IoT Build 7:07bc440836b3 1141 while ((message = getNextEventToSend(transport_state)) != NULL)
AzureIoTClient 4:57e049bce51e 1142 {
Azure.IoT Build 7:07bc440836b3 1143 result = RESULT_FAILURE;
Azure.IoT Build 11:62d7b956e76e 1144
Azure.IoT Build 7:07bc440836b3 1145 IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(message->messageHandle);
AzureIoTClient 19:ea016664011a 1146 const unsigned char* messageContent = NULL;
AzureIoTClient 19:ea016664011a 1147 size_t messageContentSize = 0;
Azure.IoT Build 12:841a4c36bd36 1148 MESSAGE_HANDLE amqp_message = NULL;
Azure.IoT Build 7:07bc440836b3 1149 bool is_message_error = false;
Azure.IoT Build 7:07bc440836b3 1150
Azure.IoT Build 10:75c5e0d8537d 1151 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_086: [IoTHubTransportAMQP_DoWork shall move queued events to an "in-progress" list right before processing them for sending]
AzureIoTClient 16:a49121e2300b 1152 trackEventInProgress(message, transport_state);
Azure.IoT Build 12:841a4c36bd36 1153
Azure.IoT Build 7:07bc440836b3 1154 // 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 1155 if (contentType == IOTHUBMESSAGE_BYTEARRAY &&
Azure.IoT Build 7:07bc440836b3 1156 IoTHubMessage_GetByteArray(message->messageHandle, &messageContent, &messageContentSize) != IOTHUB_MESSAGE_OK)
AzureIoTClient 4:57e049bce51e 1157 {
AzureIoTClient 13:a4af7c301e02 1158 LogError("Failed getting the BYTE array representation of the event content to be sent.");
Azure.IoT Build 7:07bc440836b3 1159 is_message_error = true;
Azure.IoT Build 7:07bc440836b3 1160 }
Azure.IoT Build 7:07bc440836b3 1161 // 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 1162 // 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 1163 else if (contentType == IOTHUBMESSAGE_STRING &&
AzureIoTClient 19:ea016664011a 1164 ((messageContent = (const unsigned char*)IoTHubMessage_GetString(message->messageHandle)) == NULL))
Azure.IoT Build 7:07bc440836b3 1165 {
AzureIoTClient 13:a4af7c301e02 1166 LogError("Failed getting the STRING representation of the event content to be sent.");
Azure.IoT Build 7:07bc440836b3 1167 is_message_error = true;
AzureIoTClient 4:57e049bce51e 1168 }
Azure.IoT Build 7:07bc440836b3 1169 // 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 1170 else if (contentType == IOTHUBMESSAGE_UNKNOWN)
AzureIoTClient 4:57e049bce51e 1171 {
AzureIoTClient 13:a4af7c301e02 1172 LogError("Cannot send events with content type IOTHUBMESSAGE_UNKNOWN.");
Azure.IoT Build 7:07bc440836b3 1173 is_message_error = true;
Azure.IoT Build 7:07bc440836b3 1174 }
Azure.IoT Build 10:75c5e0d8537d 1175 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_093: [IoTHubTransportAMQP_DoWork shall create an amqp message using message_create() uAMQP API]
Azure.IoT Build 7:07bc440836b3 1176 else if ((amqp_message = message_create()) == NULL)
Azure.IoT Build 7:07bc440836b3 1177 {
AzureIoTClient 13:a4af7c301e02 1178 LogError("Failed allocating the AMQP message for sending the event.");
AzureIoTClient 4:57e049bce51e 1179 }
AzureIoTClient 4:57e049bce51e 1180 else
AzureIoTClient 4:57e049bce51e 1181 {
Azure.IoT Build 10:75c5e0d8537d 1182 BINARY_DATA binary_data;
Azure.IoT Build 10:75c5e0d8537d 1183
Azure.IoT Build 10:75c5e0d8537d 1184 if (contentType == IOTHUBMESSAGE_STRING)
Azure.IoT Build 10:75c5e0d8537d 1185 {
AzureIoTClient 19:ea016664011a 1186 messageContentSize = strlen((const char*)messageContent);
Azure.IoT Build 10:75c5e0d8537d 1187 }
Azure.IoT Build 10:75c5e0d8537d 1188
Azure.IoT Build 10:75c5e0d8537d 1189 binary_data.bytes = messageContent;
Azure.IoT Build 10:75c5e0d8537d 1190 binary_data.length = messageContentSize;
Azure.IoT Build 11:62d7b956e76e 1191
Azure.IoT Build 10:75c5e0d8537d 1192 // 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 1193 if (message_add_body_amqp_data(amqp_message, binary_data) != RESULT_OK)
AzureIoTClient 4:57e049bce51e 1194 {
AzureIoTClient 13:a4af7c301e02 1195 LogError("Failed setting the body of the AMQP message.");
AzureIoTClient 4:57e049bce51e 1196 }
Azure.IoT Build 7:07bc440836b3 1197 else
AzureIoTClient 4:57e049bce51e 1198 {
Azure.IoT Build 10:75c5e0d8537d 1199 if (addPropertiesTouAMQPMessage(message->messageHandle, amqp_message) != 0)
Azure.IoT Build 7:07bc440836b3 1200 {
AzureIoTClient 19:ea016664011a 1201 /* Codes_SRS_IOTHUBTRANSPORTAMQP_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 1202 is_message_error = true;
Azure.IoT Build 7:07bc440836b3 1203 }
Azure.IoT Build 7:07bc440836b3 1204 else
Azure.IoT Build 7:07bc440836b3 1205 {
Azure.IoT Build 10:75c5e0d8537d 1206 // 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 1207 if (messagesender_send(transport_state->message_sender, amqp_message, on_message_send_complete, message) != RESULT_OK)
Azure.IoT Build 10:75c5e0d8537d 1208 {
AzureIoTClient 13:a4af7c301e02 1209 LogError("Failed sending the AMQP message.");
Azure.IoT Build 10:75c5e0d8537d 1210 }
Azure.IoT Build 10:75c5e0d8537d 1211 else
Azure.IoT Build 10:75c5e0d8537d 1212 {
Azure.IoT Build 10:75c5e0d8537d 1213 result = RESULT_OK;
Azure.IoT Build 10:75c5e0d8537d 1214 }
Azure.IoT Build 7:07bc440836b3 1215 }
AzureIoTClient 4:57e049bce51e 1216 }
Azure.IoT Build 7:07bc440836b3 1217 }
Azure.IoT Build 7:07bc440836b3 1218
Azure.IoT Build 7:07bc440836b3 1219 if (amqp_message != NULL)
Azure.IoT Build 7:07bc440836b3 1220 {
Azure.IoT Build 7:07bc440836b3 1221 // It can be destroyed because AMQP keeps a clone of the message.
Azure.IoT Build 7:07bc440836b3 1222 message_destroy(amqp_message);
Azure.IoT Build 7:07bc440836b3 1223 }
Azure.IoT Build 7:07bc440836b3 1224
Azure.IoT Build 7:07bc440836b3 1225 if (result != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1226 {
Azure.IoT Build 12:841a4c36bd36 1227 // 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 1228 // 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 1229 if (is_message_error)
AzureIoTClient 5:8d58d20699dd 1230 {
Azure.IoT Build 12:841a4c36bd36 1231 on_message_send_complete(message, MESSAGE_SEND_ERROR);
AzureIoTClient 5:8d58d20699dd 1232 }
AzureIoTClient 4:57e049bce51e 1233 else
AzureIoTClient 4:57e049bce51e 1234 {
Azure.IoT Build 12:841a4c36bd36 1235 // 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 1236 // 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 1237 // 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 1238 rollEventBackToWaitList(message, transport_state);
Azure.IoT Build 12:841a4c36bd36 1239 break;
AzureIoTClient 4:57e049bce51e 1240 }
AzureIoTClient 4:57e049bce51e 1241 }
AzureIoTClient 4:57e049bce51e 1242 }
Azure.IoT Build 7:07bc440836b3 1243
Azure.IoT Build 7:07bc440836b3 1244 return result;
Azure.IoT Build 7:07bc440836b3 1245 }
Azure.IoT Build 7:07bc440836b3 1246
Azure.IoT Build 7:07bc440836b3 1247 static bool isSasTokenRefreshRequired(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 1248 {
AzureIoTClient 19:ea016664011a 1249 if (transport_state->credential.credentialType == DEVICE_SAS_TOKEN)
AzureIoTClient 16:a49121e2300b 1250 {
AzureIoTClient 16:a49121e2300b 1251 return false;
AzureIoTClient 16:a49121e2300b 1252 }
AzureIoTClient 16:a49121e2300b 1253 else
AzureIoTClient 16:a49121e2300b 1254 {
Azure.IoT Build 7:07bc440836b3 1255 return ((getSecondsSinceEpoch() - transport_state->current_sas_token_create_time) >= (transport_state->sas_token_refresh_time / 1000)) ? true : false;
Azure.IoT Build 7:07bc440836b3 1256 }
AzureIoTClient 14:8e8e42008807 1257 }
Azure.IoT Build 7:07bc440836b3 1258
Azure.IoT Build 7:07bc440836b3 1259 static void prepareForConnectionRetry(AMQP_TRANSPORT_INSTANCE* transport_state)
Azure.IoT Build 7:07bc440836b3 1260 {
AzureIoTClient 16:a49121e2300b 1261 destroyMessageReceiver(transport_state);
AzureIoTClient 16:a49121e2300b 1262 destroyEventSender(transport_state);
Azure.IoT Build 7:07bc440836b3 1263 destroyConnection(transport_state);
AzureIoTClient 16:a49121e2300b 1264 transport_state->connection_state = AMQP_MANAGEMENT_STATE_IDLE;
Azure.IoT Build 7:07bc440836b3 1265 rollEventsBackToWaitList(transport_state);
AzureIoTClient 4:57e049bce51e 1266 }
AzureIoTClient 4:57e049bce51e 1267
Azure.IoT Build 7:07bc440836b3 1268
AzureIoTClient 19:ea016664011a 1269 static void credential_destroy(AMQP_TRANSPORT_INSTANCE* transport_state)
AzureIoTClient 19:ea016664011a 1270 {
AzureIoTClient 19:ea016664011a 1271 switch (transport_state->credential.credentialType)
AzureIoTClient 19:ea016664011a 1272 {
AzureIoTClient 19:ea016664011a 1273 default:
AzureIoTClient 19:ea016664011a 1274 {
AzureIoTClient 19:ea016664011a 1275 LogError("internal error: unexpected enum value transport_state->credential.credentialType=%d", transport_state->credential.credentialType);
AzureIoTClient 19:ea016664011a 1276 break;
AzureIoTClient 19:ea016664011a 1277 }
AzureIoTClient 19:ea016664011a 1278 case (CREDENTIAL_NOT_BUILD):
AzureIoTClient 19:ea016664011a 1279 {
AzureIoTClient 19:ea016664011a 1280 /*nothing to do*/
AzureIoTClient 19:ea016664011a 1281 break;
AzureIoTClient 19:ea016664011a 1282 }
AzureIoTClient 19:ea016664011a 1283 case(X509):
AzureIoTClient 19:ea016664011a 1284 {
AzureIoTClient 19:ea016664011a 1285 /*nothing to do here, x509certificate and x509privatekey are both NULL*/
AzureIoTClient 19:ea016664011a 1286 break;
AzureIoTClient 19:ea016664011a 1287 }
AzureIoTClient 19:ea016664011a 1288 case(DEVICE_KEY):
AzureIoTClient 19:ea016664011a 1289 {
AzureIoTClient 19:ea016664011a 1290 STRING_delete(transport_state->credential.credential.deviceKey);
AzureIoTClient 19:ea016664011a 1291 break;
AzureIoTClient 19:ea016664011a 1292 }
AzureIoTClient 19:ea016664011a 1293 case(DEVICE_SAS_TOKEN):
AzureIoTClient 19:ea016664011a 1294 {
AzureIoTClient 19:ea016664011a 1295 STRING_delete(transport_state->credential.credential.deviceSasToken);
AzureIoTClient 19:ea016664011a 1296 break;
AzureIoTClient 19:ea016664011a 1297 }
AzureIoTClient 19:ea016664011a 1298 }
AzureIoTClient 19:ea016664011a 1299 }
AzureIoTClient 19:ea016664011a 1300
Azure.IoT Build 7:07bc440836b3 1301 // API functions
Azure.IoT Build 7:07bc440836b3 1302
Azure.IoT Build 11:62d7b956e76e 1303 static TRANSPORT_LL_HANDLE IoTHubTransportAMQP_Create(const IOTHUBTRANSPORT_CONFIG* config)
AzureIoTClient 4:57e049bce51e 1304 {
Azure.IoT Build 7:07bc440836b3 1305 AMQP_TRANSPORT_INSTANCE* transport_state = NULL;
Azure.IoT Build 10:75c5e0d8537d 1306 size_t deviceIdLength;
AzureIoTClient 4:57e049bce51e 1307
Azure.IoT Build 7:07bc440836b3 1308 // 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 1309 if (config == NULL || config->upperConfig == NULL || config->waitingToSend == NULL)
Azure.IoT Build 7:07bc440836b3 1310 {
AzureIoTClient 13:a4af7c301e02 1311 LogError("IoTHub AMQP client transport null configuration parameter.");
Azure.IoT Build 7:07bc440836b3 1312 }
Azure.IoT Build 7:07bc440836b3 1313 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_006: [IoTHubTransportAMQP_Create shall fail and return NULL if any fields of the config structure are NULL.]
AzureIoTClient 14:8e8e42008807 1314 // Codes_SRS_IOTHUBTRANSPORTAMQP_03_001: [IoTHubTransportAMQP_Create shall fail and return NULL if both deviceKey & deviceSasToken fields are NOT NULL.]
Azure.IoT Build 7:07bc440836b3 1315 else if (config->upperConfig->protocol == NULL)
Azure.IoT Build 7:07bc440836b3 1316 {
AzureIoTClient 13:a4af7c301e02 1317 LogError("Invalid configuration (NULL protocol detected)");
Azure.IoT Build 7:07bc440836b3 1318 }
Azure.IoT Build 7:07bc440836b3 1319 else if (config->upperConfig->deviceId == NULL)
Azure.IoT Build 7:07bc440836b3 1320 {
AzureIoTClient 13:a4af7c301e02 1321 LogError("Invalid configuration (NULL deviceId detected)");
Azure.IoT Build 7:07bc440836b3 1322 }
AzureIoTClient 14:8e8e42008807 1323 else if (config->upperConfig->deviceKey != NULL && config->upperConfig->deviceSasToken != NULL)
AzureIoTClient 14:8e8e42008807 1324 {
AzureIoTClient 14:8e8e42008807 1325 LogError("Invalid configuration (Both deviceKey and deviceSasToken are defined)");
Azure.IoT Build 7:07bc440836b3 1326 }
Azure.IoT Build 7:07bc440836b3 1327 else if (config->upperConfig->iotHubName == NULL)
Azure.IoT Build 7:07bc440836b3 1328 {
AzureIoTClient 13:a4af7c301e02 1329 LogError("Invalid configuration (NULL iotHubName detected)");
AzureIoTClient 4:57e049bce51e 1330 }
Azure.IoT Build 7:07bc440836b3 1331 else if (config->upperConfig->iotHubSuffix == NULL)
Azure.IoT Build 7:07bc440836b3 1332 {
AzureIoTClient 13:a4af7c301e02 1333 LogError("Invalid configuration (NULL iotHubSuffix detected)");
Azure.IoT Build 7:07bc440836b3 1334 }
Azure.IoT Build 7:07bc440836b3 1335 else if (!config->waitingToSend)
AzureIoTClient 4:57e049bce51e 1336 {
AzureIoTClient 13:a4af7c301e02 1337 LogError("Invalid configuration (NULL waitingToSend list detected)");
Azure.IoT Build 7:07bc440836b3 1338 }
Azure.IoT Build 7:07bc440836b3 1339 // 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 1340 else if ((deviceIdLength = strlen(config->upperConfig->deviceId)) == 0 ||
Azure.IoT Build 7:07bc440836b3 1341 (strlen(config->upperConfig->iotHubName) == 0) ||
Azure.IoT Build 7:07bc440836b3 1342 (strlen(config->upperConfig->iotHubSuffix) == 0))
Azure.IoT Build 7:07bc440836b3 1343 {
AzureIoTClient 16:a49121e2300b 1344 LogError("Zero-length config parameter (deviceId, iotHubName or iotHubSuffix)");
Azure.IoT Build 7:07bc440836b3 1345 }
AzureIoTClient 16:a49121e2300b 1346 else if ((config->upperConfig->deviceKey != NULL) && (strlen(config->upperConfig->deviceKey) == 0))
AzureIoTClient 16:a49121e2300b 1347 {
AzureIoTClient 16:a49121e2300b 1348 LogError("Zero-length config parameter (deviceKey)");
AzureIoTClient 16:a49121e2300b 1349 }
AzureIoTClient 16:a49121e2300b 1350 else if ((config->upperConfig->deviceSasToken != NULL) && (strlen(config->upperConfig->deviceSasToken) == 0))
AzureIoTClient 16:a49121e2300b 1351 {
AzureIoTClient 16:a49121e2300b 1352 LogError("Zero-length config parameter (deviceSasToken)");
AzureIoTClient 16:a49121e2300b 1353 }
Azure.IoT Build 7:07bc440836b3 1354 // 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 1355 else if (deviceIdLength > 128U)
Azure.IoT Build 7:07bc440836b3 1356 {
AzureIoTClient 13:a4af7c301e02 1357 LogError("deviceId is too long");
Azure.IoT Build 7:07bc440836b3 1358 }
Azure.IoT Build 7:07bc440836b3 1359 // 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 1360 else if ((strlen(config->upperConfig->iotHubName) + strlen(config->upperConfig->iotHubSuffix)) > (RFC1035_MAX_FQDN_LENGTH - 1))
Azure.IoT Build 7:07bc440836b3 1361 {
AzureIoTClient 13:a4af7c301e02 1362 LogError("The lengths of iotHubName and iotHubSuffix together exceed the maximum FQDN length allowed (RFC 1035)");
AzureIoTClient 4:57e049bce51e 1363 }
AzureIoTClient 4:57e049bce51e 1364 else
AzureIoTClient 4:57e049bce51e 1365 {
Azure.IoT Build 10:75c5e0d8537d 1366 // 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 1367 transport_state = (AMQP_TRANSPORT_INSTANCE*)malloc(sizeof(AMQP_TRANSPORT_INSTANCE));
AzureIoTClient 4:57e049bce51e 1368
Azure.IoT Build 7:07bc440836b3 1369 if (transport_state == NULL)
AzureIoTClient 4:57e049bce51e 1370 {
AzureIoTClient 13:a4af7c301e02 1371 LogError("Could not allocate AMQP transport state");
AzureIoTClient 4:57e049bce51e 1372 }
AzureIoTClient 4:57e049bce51e 1373 else
AzureIoTClient 4:57e049bce51e 1374 {
AzureIoTClient 19:ea016664011a 1375 bool cleanup_required = false;
AzureIoTClient 19:ea016664011a 1376
Azure.IoT Build 7:07bc440836b3 1377 transport_state->iotHubHostFqdn = NULL;
Azure.IoT Build 7:07bc440836b3 1378 transport_state->iotHubPort = DEFAULT_IOTHUB_AMQP_PORT;
Azure.IoT Build 7:07bc440836b3 1379 transport_state->devicesPath = NULL;
Azure.IoT Build 7:07bc440836b3 1380 transport_state->messageReceiveAddress = NULL;
Azure.IoT Build 7:07bc440836b3 1381 transport_state->sasTokenKeyName = NULL;
Azure.IoT Build 7:07bc440836b3 1382 transport_state->targetAddress = NULL;
Azure.IoT Build 7:07bc440836b3 1383 transport_state->waitingToSend = config->waitingToSend;
Azure.IoT Build 7:07bc440836b3 1384
Azure.IoT Build 7:07bc440836b3 1385 transport_state->cbs = NULL;
Azure.IoT Build 7:07bc440836b3 1386 transport_state->cbs_state = CBS_STATE_IDLE;
Azure.IoT Build 7:07bc440836b3 1387 transport_state->current_sas_token_create_time = 0;
Azure.IoT Build 7:07bc440836b3 1388 transport_state->connection = NULL;
Azure.IoT Build 7:07bc440836b3 1389 transport_state->connection_state = AMQP_MANAGEMENT_STATE_IDLE;
Azure.IoT Build 7:07bc440836b3 1390 transport_state->connection_establish_time = 0;
Azure.IoT Build 7:07bc440836b3 1391 transport_state->iothub_client_handle = NULL;
Azure.IoT Build 7:07bc440836b3 1392 transport_state->receive_messages = false;
Azure.IoT Build 7:07bc440836b3 1393 transport_state->message_receiver = NULL;
Azure.IoT Build 7:07bc440836b3 1394 transport_state->message_sender = NULL;
Azure.IoT Build 7:07bc440836b3 1395 transport_state->receiver_link = NULL;
Azure.IoT Build 7:07bc440836b3 1396 transport_state->sasl_io = NULL;
Azure.IoT Build 7:07bc440836b3 1397 transport_state->sasl_mechanism = NULL;
Azure.IoT Build 7:07bc440836b3 1398 transport_state->sender_link = NULL;
Azure.IoT Build 7:07bc440836b3 1399 transport_state->session = NULL;
Azure.IoT Build 7:07bc440836b3 1400 transport_state->tls_io = NULL;
Azure.IoT Build 10:75c5e0d8537d 1401 transport_state->tls_io_transport_provider = getTLSIOTransport;
Azure.IoT Build 10:75c5e0d8537d 1402 transport_state->isRegistered = false;
AzureIoTClient 16:a49121e2300b 1403 transport_state->is_trace_on = false;
Azure.IoT Build 7:07bc440836b3 1404
Azure.IoT Build 7:07bc440836b3 1405 transport_state->waitingToSend = config->waitingToSend;
Azure.IoT Build 7:07bc440836b3 1406 DList_InitializeListHead(&transport_state->inProgress);
Azure.IoT Build 7:07bc440836b3 1407
AzureIoTClient 19:ea016664011a 1408 transport_state->credential.credentialType = CREDENTIAL_NOT_BUILD;
AzureIoTClient 19:ea016664011a 1409
Azure.IoT Build 7:07bc440836b3 1410 // 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 1411 if ((transport_state->iotHubHostFqdn = concat3Params(config->upperConfig->iotHubName, ".", config->upperConfig->iotHubSuffix)) == NULL)
AzureIoTClient 4:57e049bce51e 1412 {
AzureIoTClient 13:a4af7c301e02 1413 LogError("Failed to set transport_state->iotHubHostFqdn.");
Azure.IoT Build 7:07bc440836b3 1414 cleanup_required = true;
AzureIoTClient 4:57e049bce51e 1415 }
Azure.IoT Build 10:75c5e0d8537d 1416 // 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 1417 else if ((transport_state->devicesPath = concat3Params(STRING_c_str(transport_state->iotHubHostFqdn), "/devices/", config->upperConfig->deviceId)) == NULL)
AzureIoTClient 4:57e049bce51e 1418 {
Azure.IoT Build 7:07bc440836b3 1419 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_013: [If creating devicesPath fails for any reason then IoTHubTransportAMQP_Create shall fail and return NULL.]
AzureIoTClient 13:a4af7c301e02 1420 LogError("Failed to allocate transport_state->devicesPath.");
Azure.IoT Build 7:07bc440836b3 1421 cleanup_required = true;
Azure.IoT Build 7:07bc440836b3 1422 }
Azure.IoT Build 7:07bc440836b3 1423 // 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 1424 else if ((transport_state->targetAddress = concat3Params("amqps://", STRING_c_str(transport_state->devicesPath), "/messages/events")) == NULL)
Azure.IoT Build 7:07bc440836b3 1425 {
Azure.IoT Build 7:07bc440836b3 1426 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_015: [If creating the targetAddress fails for any reason then IoTHubTransportAMQP_Create shall fail and return NULL.]
AzureIoTClient 13:a4af7c301e02 1427 LogError("Failed to allocate transport_state->targetAddress.");
Azure.IoT Build 7:07bc440836b3 1428 cleanup_required = true;
Azure.IoT Build 7:07bc440836b3 1429 }
Azure.IoT Build 7:07bc440836b3 1430 // 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 1431 else if ((transport_state->messageReceiveAddress = concat3Params("amqps://", STRING_c_str(transport_state->devicesPath), "/messages/devicebound")) == NULL)
Azure.IoT Build 7:07bc440836b3 1432 {
Azure.IoT Build 7:07bc440836b3 1433 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_054: [If creating the messageReceiveAddress fails for any reason then IoTHubTransportAMQP_Create shall fail and return NULL.]
AzureIoTClient 13:a4af7c301e02 1434 LogError("Failed to allocate transport_state->messageReceiveAddress.");
Azure.IoT Build 7:07bc440836b3 1435 cleanup_required = true;
Azure.IoT Build 7:07bc440836b3 1436 }
Azure.IoT Build 7:07bc440836b3 1437 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_016: [IoTHubTransportAMQP_Create shall initialize handle->sasTokenKeyName with a zero-length STRING_HANDLE instance.]
Azure.IoT Build 7:07bc440836b3 1438 else if ((transport_state->sasTokenKeyName = STRING_new()) == NULL)
Azure.IoT Build 7:07bc440836b3 1439 {
Azure.IoT Build 7:07bc440836b3 1440 // 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 1441 LogError("Failed to allocate transport_state->sasTokenKeyName.");
Azure.IoT Build 7:07bc440836b3 1442 cleanup_required = true;
Azure.IoT Build 7:07bc440836b3 1443 }
AzureIoTClient 19:ea016664011a 1444 else
Azure.IoT Build 7:07bc440836b3 1445 {
AzureIoTClient 19:ea016664011a 1446
AzureIoTClient 19:ea016664011a 1447 if (config->upperConfig->deviceSasToken != NULL)
AzureIoTClient 19:ea016664011a 1448 {
AzureIoTClient 19:ea016664011a 1449 if (config->upperConfig->deviceKey != NULL)
AzureIoTClient 19:ea016664011a 1450 {
AzureIoTClient 19:ea016664011a 1451 LogError("invalid configuration, both deviceSasToken AND deviceKey specified");
AzureIoTClient 19:ea016664011a 1452 cleanup_required = true;
AzureIoTClient 19:ea016664011a 1453 }
AzureIoTClient 19:ea016664011a 1454 else
AzureIoTClient 19:ea016664011a 1455 {
AzureIoTClient 19:ea016664011a 1456 /*only SAS token specified*/
AzureIoTClient 19:ea016664011a 1457 transport_state->credential.credential.deviceSasToken = STRING_construct(config->upperConfig->deviceSasToken);
AzureIoTClient 19:ea016664011a 1458 if (transport_state->credential.credential.deviceSasToken == NULL)
AzureIoTClient 19:ea016664011a 1459 {
AzureIoTClient 19:ea016664011a 1460 LogError("unable to STRING_construct for deviceSasToken");
AzureIoTClient 19:ea016664011a 1461 cleanup_required = true;
AzureIoTClient 19:ea016664011a 1462 }
AzureIoTClient 19:ea016664011a 1463 else
AzureIoTClient 19:ea016664011a 1464 {
AzureIoTClient 19:ea016664011a 1465 transport_state->credential.credentialType = DEVICE_SAS_TOKEN;
AzureIoTClient 19:ea016664011a 1466 }
AzureIoTClient 19:ea016664011a 1467 }
AzureIoTClient 19:ea016664011a 1468 }
AzureIoTClient 19:ea016664011a 1469 else
AzureIoTClient 19:ea016664011a 1470 {
AzureIoTClient 19:ea016664011a 1471 /*when deviceSasToken == NULL*/
AzureIoTClient 19:ea016664011a 1472 if (config->upperConfig->deviceKey != NULL)
AzureIoTClient 19:ea016664011a 1473 {
AzureIoTClient 19:ea016664011a 1474 /*it is device key*/
AzureIoTClient 19:ea016664011a 1475
AzureIoTClient 19:ea016664011a 1476 transport_state->credential.credential.deviceKey = STRING_construct(config->upperConfig->deviceKey);
AzureIoTClient 19:ea016664011a 1477 if (transport_state->credential.credential.deviceKey == NULL)
AzureIoTClient 19:ea016664011a 1478 {
AzureIoTClient 19:ea016664011a 1479 LogError("unable to STRING_construct for a deviceKey");
AzureIoTClient 19:ea016664011a 1480 cleanup_required = true;
AzureIoTClient 19:ea016664011a 1481 }
AzureIoTClient 19:ea016664011a 1482 else
AzureIoTClient 19:ea016664011a 1483 {
AzureIoTClient 19:ea016664011a 1484 transport_state->credential.credentialType = DEVICE_KEY;
AzureIoTClient 19:ea016664011a 1485 }
AzureIoTClient 19:ea016664011a 1486 }
AzureIoTClient 19:ea016664011a 1487 else
AzureIoTClient 19:ea016664011a 1488 {
AzureIoTClient 19:ea016664011a 1489 /*Codes_SRS_IOTHUBTRANSPORTAMQP_02_003: [ IoTHubTransportAMQP_Register shall assume a x509 authentication mechanism when both deviceKey and deviceSasToken are NULL. ]*/
AzureIoTClient 19:ea016664011a 1490 /*when both SAS token AND devicekey are NULL*/
AzureIoTClient 19:ea016664011a 1491 transport_state->credential.credentialType = X509;
AzureIoTClient 19:ea016664011a 1492 transport_state->credential.credential.x509credential.x509certificate = NULL;
AzureIoTClient 19:ea016664011a 1493 transport_state->credential.credential.x509credential.x509privatekey = NULL;
AzureIoTClient 19:ea016664011a 1494 }
AzureIoTClient 19:ea016664011a 1495 }
AzureIoTClient 19:ea016664011a 1496
AzureIoTClient 19:ea016664011a 1497 if(transport_state->credential.credentialType != CREDENTIAL_NOT_BUILD )
AzureIoTClient 19:ea016664011a 1498 {
AzureIoTClient 19:ea016664011a 1499 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_020: [IoTHubTransportAMQP_Create shall set parameter transport_state->sas_token_lifetime with the default value of 3600000 (milliseconds).]
AzureIoTClient 19:ea016664011a 1500 transport_state->sas_token_lifetime = DEFAULT_SAS_TOKEN_LIFETIME_MS;
AzureIoTClient 19:ea016664011a 1501
AzureIoTClient 19:ea016664011a 1502 // 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).]
AzureIoTClient 19:ea016664011a 1503 transport_state->sas_token_refresh_time = transport_state->sas_token_lifetime / 2;
AzureIoTClient 19:ea016664011a 1504
AzureIoTClient 19:ea016664011a 1505 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_129 : [IoTHubTransportAMQP_Create shall set parameter transport_state->cbs_request_timeout with the default value of 30000 (milliseconds).]
AzureIoTClient 19:ea016664011a 1506 transport_state->cbs_request_timeout = DEFAULT_CBS_REQUEST_TIMEOUT_MS;
AzureIoTClient 19:ea016664011a 1507 }
Azure.IoT Build 7:07bc440836b3 1508 }
AzureIoTClient 19:ea016664011a 1509
AzureIoTClient 19:ea016664011a 1510 if (cleanup_required)
Azure.IoT Build 7:07bc440836b3 1511 {
AzureIoTClient 19:ea016664011a 1512 credential_destroy(transport_state);
AzureIoTClient 19:ea016664011a 1513 if (transport_state->sasTokenKeyName != NULL)
AzureIoTClient 19:ea016664011a 1514 STRING_delete(transport_state->sasTokenKeyName);
AzureIoTClient 19:ea016664011a 1515 if (transport_state->targetAddress != NULL)
AzureIoTClient 19:ea016664011a 1516 STRING_delete(transport_state->targetAddress);
AzureIoTClient 19:ea016664011a 1517 if (transport_state->messageReceiveAddress != NULL)
AzureIoTClient 19:ea016664011a 1518 STRING_delete(transport_state->messageReceiveAddress);
AzureIoTClient 19:ea016664011a 1519 if (transport_state->devicesPath != NULL)
AzureIoTClient 19:ea016664011a 1520 STRING_delete(transport_state->devicesPath);
AzureIoTClient 19:ea016664011a 1521 if (transport_state->iotHubHostFqdn != NULL)
AzureIoTClient 19:ea016664011a 1522 STRING_delete(transport_state->iotHubHostFqdn);
Azure.IoT Build 7:07bc440836b3 1523
AzureIoTClient 19:ea016664011a 1524 free(transport_state);
AzureIoTClient 19:ea016664011a 1525 transport_state = NULL;
AzureIoTClient 4:57e049bce51e 1526 }
AzureIoTClient 4:57e049bce51e 1527 }
AzureIoTClient 4:57e049bce51e 1528 }
Azure.IoT Build 7:07bc440836b3 1529
Azure.IoT Build 7:07bc440836b3 1530 // 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 1531 return transport_state;
AzureIoTClient 4:57e049bce51e 1532 }
AzureIoTClient 4:57e049bce51e 1533
Azure.IoT Build 11:62d7b956e76e 1534 static void IoTHubTransportAMQP_Destroy(TRANSPORT_LL_HANDLE handle)
AzureIoTClient 4:57e049bce51e 1535 {
Azure.IoT Build 7:07bc440836b3 1536 if (handle != NULL)
Azure.IoT Build 7:07bc440836b3 1537 {
Azure.IoT Build 7:07bc440836b3 1538 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
Azure.IoT Build 11:62d7b956e76e 1539
Azure.IoT Build 7:07bc440836b3 1540 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_024: [IoTHubTransportAMQP_Destroy shall destroy the AMQP message_sender.]
Azure.IoT Build 7:07bc440836b3 1541 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_029 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP link.]
Azure.IoT Build 7:07bc440836b3 1542 destroyEventSender(transport_state);
Azure.IoT Build 7:07bc440836b3 1543
Azure.IoT Build 7:07bc440836b3 1544 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_025: [IoTHubTransportAMQP_Destroy shall destroy the AMQP message_receiver.]
Azure.IoT Build 7:07bc440836b3 1545 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_029 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP link.]
Azure.IoT Build 7:07bc440836b3 1546 destroyMessageReceiver(transport_state);
Azure.IoT Build 7:07bc440836b3 1547
Azure.IoT Build 7:07bc440836b3 1548 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_027 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP cbs instance]
Azure.IoT Build 7:07bc440836b3 1549 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_030 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP session.]
Azure.IoT Build 7:07bc440836b3 1550 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_031 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP connection.]
Azure.IoT Build 7:07bc440836b3 1551 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_032 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP SASL I / O transport.]
Azure.IoT Build 7:07bc440836b3 1552 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_033 : [IoTHubTransportAMQP_Destroy shall destroy the AMQP SASL mechanism.]
Azure.IoT Build 7:07bc440836b3 1553 destroyConnection(transport_state);
Azure.IoT Build 7:07bc440836b3 1554
Azure.IoT Build 7:07bc440836b3 1555 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_035 : [IoTHubTransportAMQP_Destroy shall delete its internally - set parameters(deviceKey, targetAddress, devicesPath, sasTokenKeyName).]
Azure.IoT Build 7:07bc440836b3 1556 STRING_delete(transport_state->targetAddress);
Azure.IoT Build 7:07bc440836b3 1557 STRING_delete(transport_state->messageReceiveAddress);
Azure.IoT Build 7:07bc440836b3 1558 STRING_delete(transport_state->sasTokenKeyName);
AzureIoTClient 19:ea016664011a 1559 credential_destroy(transport_state);
Azure.IoT Build 7:07bc440836b3 1560 STRING_delete(transport_state->devicesPath);
Azure.IoT Build 7:07bc440836b3 1561 STRING_delete(transport_state->iotHubHostFqdn);
Azure.IoT Build 7:07bc440836b3 1562
Azure.IoT Build 7:07bc440836b3 1563 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_036 : [IoTHubTransportAMQP_Destroy shall return the remaining items in inProgress to waitingToSend list.]
Azure.IoT Build 7:07bc440836b3 1564 rollEventsBackToWaitList(transport_state);
Azure.IoT Build 7:07bc440836b3 1565
Azure.IoT Build 7:07bc440836b3 1566 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_150: [IoTHubTransportAMQP_Destroy shall destroy the transport instance]
Azure.IoT Build 7:07bc440836b3 1567 free(transport_state);
Azure.IoT Build 7:07bc440836b3 1568 }
Azure.IoT Build 7:07bc440836b3 1569 }
Azure.IoT Build 7:07bc440836b3 1570
Azure.IoT Build 11:62d7b956e76e 1571 static void IoTHubTransportAMQP_DoWork(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle)
Azure.IoT Build 7:07bc440836b3 1572 {
Azure.IoT Build 7:07bc440836b3 1573 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_051: [IoTHubTransportAMQP_DoWork shall fail and return immediately if the transport handle parameter is NULL]
AzureIoTClient 4:57e049bce51e 1574 if (handle == NULL)
AzureIoTClient 4:57e049bce51e 1575 {
AzureIoTClient 13:a4af7c301e02 1576 LogError("IoTHubClient DoWork failed: transport handle parameter is NULL.");
Azure.IoT Build 7:07bc440836b3 1577 }
Azure.IoT Build 7:07bc440836b3 1578 // Codes_[IoTHubTransportAMQP_DoWork shall fail and return immediately if the client handle parameter is NULL]
Azure.IoT Build 7:07bc440836b3 1579 else if (iotHubClientHandle == NULL)
Azure.IoT Build 7:07bc440836b3 1580 {
AzureIoTClient 13:a4af7c301e02 1581 LogError("IoTHubClient DoWork failed: client handle parameter is NULL.");
AzureIoTClient 4:57e049bce51e 1582 }
AzureIoTClient 4:57e049bce51e 1583 else
AzureIoTClient 4:57e049bce51e 1584 {
Azure.IoT Build 7:07bc440836b3 1585 bool trigger_connection_retry = false;
Azure.IoT Build 7:07bc440836b3 1586 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
Azure.IoT Build 7:07bc440836b3 1587
Azure.IoT Build 7:07bc440836b3 1588 // 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 1589 transport_state->iothub_client_handle = iotHubClientHandle;
Azure.IoT Build 7:07bc440836b3 1590
AzureIoTClient 16:a49121e2300b 1591 if (transport_state->connection != NULL &&
AzureIoTClient 16:a49121e2300b 1592 transport_state->connection_state == AMQP_MANAGEMENT_STATE_ERROR)
AzureIoTClient 16:a49121e2300b 1593 {
AzureIoTClient 16:a49121e2300b 1594 LogError("An error occured on AMQP connection. The connection will be restablished.");
AzureIoTClient 16:a49121e2300b 1595 trigger_connection_retry = true;
AzureIoTClient 16:a49121e2300b 1596 }
Azure.IoT Build 7:07bc440836b3 1597 // 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 1598 else if (transport_state->connection == NULL &&
Azure.IoT Build 7:07bc440836b3 1599 establishConnection(transport_state) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1600 {
AzureIoTClient 13:a4af7c301e02 1601 LogError("AMQP transport failed to establish connection with service.");
Azure.IoT Build 7:07bc440836b3 1602 trigger_connection_retry = true;
Azure.IoT Build 7:07bc440836b3 1603 }
Azure.IoT Build 7:07bc440836b3 1604 // 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 1605 // 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 1606 else if ((transport_state->cbs_state == CBS_STATE_IDLE || isSasTokenRefreshRequired(transport_state)) &&
Azure.IoT Build 11:62d7b956e76e 1607 startAuthentication(transport_state) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1608 {
Azure.IoT Build 7:07bc440836b3 1609 // 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 1610 LogError("Failed authenticating AMQP connection within CBS.");
Azure.IoT Build 7:07bc440836b3 1611 trigger_connection_retry = true;
Azure.IoT Build 7:07bc440836b3 1612 }
Azure.IoT Build 10:75c5e0d8537d 1613 // 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 1614 else if (transport_state->cbs_state == CBS_STATE_AUTH_IN_PROGRESS &&
Azure.IoT Build 11:62d7b956e76e 1615 verifyAuthenticationTimeout(transport_state) == RESULT_TIMEOUT)
Azure.IoT Build 7:07bc440836b3 1616 {
AzureIoTClient 13:a4af7c301e02 1617 LogError("AMQP transport authentication timed out.");
Azure.IoT Build 7:07bc440836b3 1618 trigger_connection_retry = true;
Azure.IoT Build 7:07bc440836b3 1619 }
Azure.IoT Build 7:07bc440836b3 1620 else if (transport_state->cbs_state == CBS_STATE_AUTHENTICATED)
Azure.IoT Build 7:07bc440836b3 1621 {
Azure.IoT Build 7:07bc440836b3 1622 // 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 1623 if (transport_state->receive_messages == true &&
Azure.IoT Build 7:07bc440836b3 1624 transport_state->message_receiver == NULL &&
Azure.IoT Build 7:07bc440836b3 1625 createMessageReceiver(transport_state, iotHubClientHandle) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1626 {
AzureIoTClient 13:a4af7c301e02 1627 LogError("Failed creating AMQP transport message receiver.");
Azure.IoT Build 7:07bc440836b3 1628 trigger_connection_retry = true;
Azure.IoT Build 7:07bc440836b3 1629 }
Azure.IoT Build 7:07bc440836b3 1630 // 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 1631 else if (transport_state->receive_messages == false &&
Azure.IoT Build 7:07bc440836b3 1632 transport_state->message_receiver != NULL &&
Azure.IoT Build 7:07bc440836b3 1633 destroyMessageReceiver(transport_state) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1634 {
AzureIoTClient 13:a4af7c301e02 1635 LogError("Failed destroying AMQP transport message receiver.");
Azure.IoT Build 7:07bc440836b3 1636 }
Azure.IoT Build 7:07bc440836b3 1637
Azure.IoT Build 7:07bc440836b3 1638 if (transport_state->message_sender == NULL &&
Azure.IoT Build 7:07bc440836b3 1639 createEventSender(transport_state) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1640 {
AzureIoTClient 13:a4af7c301e02 1641 LogError("Failed creating AMQP transport event sender.");
Azure.IoT Build 7:07bc440836b3 1642 trigger_connection_retry = true;
Azure.IoT Build 7:07bc440836b3 1643 }
Azure.IoT Build 7:07bc440836b3 1644 else if (sendPendingEvents(transport_state) != RESULT_OK)
Azure.IoT Build 7:07bc440836b3 1645 {
AzureIoTClient 13:a4af7c301e02 1646 LogError("AMQP transport failed sending events.");
Azure.IoT Build 7:07bc440836b3 1647 }
Azure.IoT Build 7:07bc440836b3 1648 }
Azure.IoT Build 7:07bc440836b3 1649
Azure.IoT Build 7:07bc440836b3 1650 if (trigger_connection_retry)
Azure.IoT Build 7:07bc440836b3 1651 {
Azure.IoT Build 7:07bc440836b3 1652 prepareForConnectionRetry(transport_state);
Azure.IoT Build 7:07bc440836b3 1653 }
Azure.IoT Build 7:07bc440836b3 1654 else
Azure.IoT Build 7:07bc440836b3 1655 {
Azure.IoT Build 7:07bc440836b3 1656 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_103: [IoTHubTransportAMQP_DoWork shall invoke connection_dowork() on AMQP for triggering sending and receiving messages]
Azure.IoT Build 7:07bc440836b3 1657 connection_dowork(transport_state->connection);
Azure.IoT Build 7:07bc440836b3 1658 }
Azure.IoT Build 7:07bc440836b3 1659 }
Azure.IoT Build 7:07bc440836b3 1660 }
Azure.IoT Build 7:07bc440836b3 1661
AzureIoTClient 14:8e8e42008807 1662 static int IoTHubTransportAMQP_Subscribe(TRANSPORT_LL_HANDLE handle)
Azure.IoT Build 7:07bc440836b3 1663 {
Azure.IoT Build 7:07bc440836b3 1664 int result;
Azure.IoT Build 11:62d7b956e76e 1665
Azure.IoT Build 7:07bc440836b3 1666 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_037: [IoTHubTransportAMQP_Subscribe shall fail if the transport handle parameter received is NULL.]
Azure.IoT Build 7:07bc440836b3 1667 if (handle == NULL)
Azure.IoT Build 7:07bc440836b3 1668 {
AzureIoTClient 13:a4af7c301e02 1669 LogError("Invalid handle to IoTHubClient AMQP transport.");
Azure.IoT Build 7:07bc440836b3 1670 result = __LINE__;
Azure.IoT Build 7:07bc440836b3 1671 }
Azure.IoT Build 7:07bc440836b3 1672 else
Azure.IoT Build 7:07bc440836b3 1673 {
Azure.IoT Build 7:07bc440836b3 1674 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_038: [IoTHubTransportAMQP_Subscribe shall set transport_handle->receive_messages to true and return success code.]
Azure.IoT Build 7:07bc440836b3 1675 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
Azure.IoT Build 7:07bc440836b3 1676 transport_state->receive_messages = true;
AzureIoTClient 4:57e049bce51e 1677 result = 0;
AzureIoTClient 4:57e049bce51e 1678 }
Azure.IoT Build 7:07bc440836b3 1679
AzureIoTClient 4:57e049bce51e 1680 return result;
AzureIoTClient 4:57e049bce51e 1681 }
AzureIoTClient 4:57e049bce51e 1682
AzureIoTClient 14:8e8e42008807 1683 static void IoTHubTransportAMQP_Unsubscribe(TRANSPORT_LL_HANDLE handle)
AzureIoTClient 4:57e049bce51e 1684 {
Azure.IoT Build 7:07bc440836b3 1685 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_039: [IoTHubTransportAMQP_Unsubscribe shall fail if the transport handle parameter received is NULL.]
Azure.IoT Build 7:07bc440836b3 1686 if (handle == NULL)
AzureIoTClient 4:57e049bce51e 1687 {
AzureIoTClient 13:a4af7c301e02 1688 LogError("Invalid handle to IoTHubClient AMQP transport.");
Azure.IoT Build 7:07bc440836b3 1689 }
Azure.IoT Build 7:07bc440836b3 1690 else
Azure.IoT Build 7:07bc440836b3 1691 {
Azure.IoT Build 7:07bc440836b3 1692 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_040: [IoTHubTransportAMQP_Unsubscribe shall set transport_handle->receive_messages to false and return success code.]
Azure.IoT Build 7:07bc440836b3 1693 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
Azure.IoT Build 7:07bc440836b3 1694 transport_state->receive_messages = false;
AzureIoTClient 4:57e049bce51e 1695 }
AzureIoTClient 4:57e049bce51e 1696 }
AzureIoTClient 4:57e049bce51e 1697
Azure.IoT Build 10:75c5e0d8537d 1698 static IOTHUB_CLIENT_RESULT IoTHubTransportAMQP_GetSendStatus(IOTHUB_DEVICE_HANDLE handle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
AzureIoTClient 4:57e049bce51e 1699 {
AzureIoTClient 4:57e049bce51e 1700 IOTHUB_CLIENT_RESULT result;
AzureIoTClient 4:57e049bce51e 1701
Azure.IoT Build 7:07bc440836b3 1702 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_041: [IoTHubTransportAMQP_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.]
AzureIoTClient 4:57e049bce51e 1703 if (handle == NULL)
AzureIoTClient 4:57e049bce51e 1704 {
AzureIoTClient 4:57e049bce51e 1705 result = IOTHUB_CLIENT_INVALID_ARG;
AzureIoTClient 13:a4af7c301e02 1706 LogError("Invalid handle to IoTHubClient AMQP transport instance.");
AzureIoTClient 4:57e049bce51e 1707 }
AzureIoTClient 4:57e049bce51e 1708 else if (iotHubClientStatus == NULL)
AzureIoTClient 4:57e049bce51e 1709 {
AzureIoTClient 4:57e049bce51e 1710 result = IOTHUB_CLIENT_INVALID_ARG;
AzureIoTClient 13:a4af7c301e02 1711 LogError("Invalid pointer to output parameter IOTHUB_CLIENT_STATUS.");
AzureIoTClient 4:57e049bce51e 1712 }
AzureIoTClient 4:57e049bce51e 1713 else
AzureIoTClient 4:57e049bce51e 1714 {
Azure.IoT Build 7:07bc440836b3 1715 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
AzureIoTClient 4:57e049bce51e 1716
Azure.IoT Build 7:07bc440836b3 1717 // 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 1718 if (!DList_IsListEmpty(transport_state->waitingToSend) || !DList_IsListEmpty(&(transport_state->inProgress)))
AzureIoTClient 4:57e049bce51e 1719 {
AzureIoTClient 4:57e049bce51e 1720 *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_BUSY;
AzureIoTClient 4:57e049bce51e 1721 }
Azure.IoT Build 7:07bc440836b3 1722 // 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 1723 else
AzureIoTClient 4:57e049bce51e 1724 {
AzureIoTClient 4:57e049bce51e 1725 *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_IDLE;
AzureIoTClient 4:57e049bce51e 1726 }
AzureIoTClient 4:57e049bce51e 1727
AzureIoTClient 4:57e049bce51e 1728 result = IOTHUB_CLIENT_OK;
AzureIoTClient 4:57e049bce51e 1729 }
AzureIoTClient 4:57e049bce51e 1730
AzureIoTClient 4:57e049bce51e 1731 return result;
AzureIoTClient 4:57e049bce51e 1732 }
AzureIoTClient 4:57e049bce51e 1733
Azure.IoT Build 11:62d7b956e76e 1734 static IOTHUB_CLIENT_RESULT IoTHubTransportAMQP_SetOption(TRANSPORT_LL_HANDLE handle, const char* option, const void* value)
AzureIoTClient 4:57e049bce51e 1735 {
AzureIoTClient 4:57e049bce51e 1736 IOTHUB_CLIENT_RESULT result;
AzureIoTClient 4:57e049bce51e 1737
Azure.IoT Build 7:07bc440836b3 1738 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_044: [If handle parameter is NULL then IoTHubTransportAMQP_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]
Azure.IoT Build 7:07bc440836b3 1739 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_045: [If parameter optionName is NULL then IoTHubTransportAMQP_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]
Azure.IoT Build 7:07bc440836b3 1740 // Codes_SRS_IOTHUBTRANSPORTAMQP_09_046: [If parameter value is NULL then IoTHubTransportAMQP_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]
AzureIoTClient 5:8d58d20699dd 1741 if (
AzureIoTClient 5:8d58d20699dd 1742 (handle == NULL) ||
AzureIoTClient 5:8d58d20699dd 1743 (option == NULL) ||
AzureIoTClient 5:8d58d20699dd 1744 (value == NULL)
AzureIoTClient 5:8d58d20699dd 1745 )
AzureIoTClient 5:8d58d20699dd 1746 {
AzureIoTClient 5:8d58d20699dd 1747 result = IOTHUB_CLIENT_INVALID_ARG;
AzureIoTClient 13:a4af7c301e02 1748 LogError("Invalid parameter (NULL) passed to AMQP transport SetOption()");
AzureIoTClient 5:8d58d20699dd 1749 }
AzureIoTClient 5:8d58d20699dd 1750 else
AzureIoTClient 5:8d58d20699dd 1751 {
Azure.IoT Build 7:07bc440836b3 1752 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
AzureIoTClient 4:57e049bce51e 1753
Azure.IoT Build 10:75c5e0d8537d 1754 // 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 1755 if (strcmp("sas_token_lifetime", option) == 0)
Azure.IoT Build 10:75c5e0d8537d 1756 {
Azure.IoT Build 10:75c5e0d8537d 1757 transport_state->sas_token_lifetime = *((size_t*)value);
Azure.IoT Build 10:75c5e0d8537d 1758 result = IOTHUB_CLIENT_OK;
Azure.IoT Build 10:75c5e0d8537d 1759 }
Azure.IoT Build 10:75c5e0d8537d 1760 // 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 1761 else if (strcmp("sas_token_refresh_time", option) == 0)
Azure.IoT Build 10:75c5e0d8537d 1762 {
Azure.IoT Build 10:75c5e0d8537d 1763 transport_state->sas_token_refresh_time = *((size_t*)value);
Azure.IoT Build 10:75c5e0d8537d 1764 result = IOTHUB_CLIENT_OK;
Azure.IoT Build 10:75c5e0d8537d 1765 }
Azure.IoT Build 10:75c5e0d8537d 1766 // 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 1767 else if (strcmp("cbs_request_timeout", option) == 0)
Azure.IoT Build 10:75c5e0d8537d 1768 {
Azure.IoT Build 10:75c5e0d8537d 1769 transport_state->cbs_request_timeout = *((size_t*)value);
Azure.IoT Build 10:75c5e0d8537d 1770 result = IOTHUB_CLIENT_OK;
Azure.IoT Build 10:75c5e0d8537d 1771 }
AzureIoTClient 16:a49121e2300b 1772 else if (strcmp("logtrace", option) == 0)
AzureIoTClient 16:a49121e2300b 1773 {
AzureIoTClient 19:ea016664011a 1774 transport_state->is_trace_on = *((bool*)value);
AzureIoTClient 16:a49121e2300b 1775 if (transport_state->connection != NULL)
AzureIoTClient 16:a49121e2300b 1776 {
AzureIoTClient 16:a49121e2300b 1777 connection_set_trace(transport_state->connection, transport_state->is_trace_on);
AzureIoTClient 16:a49121e2300b 1778 }
AzureIoTClient 16:a49121e2300b 1779 result = IOTHUB_CLIENT_OK;
AzureIoTClient 16:a49121e2300b 1780 }
Azure.IoT Build 11:62d7b956e76e 1781 // 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 1782 else
Azure.IoT Build 10:75c5e0d8537d 1783 {
Azure.IoT Build 11:62d7b956e76e 1784 if (transport_state->tls_io == NULL &&
Azure.IoT Build 11:62d7b956e76e 1785 (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 1786 {
Azure.IoT Build 11:62d7b956e76e 1787 result = IOTHUB_CLIENT_ERROR;
AzureIoTClient 13:a4af7c301e02 1788 LogError("Failed to obtain a TLS I/O transport layer.");
Azure.IoT Build 11:62d7b956e76e 1789 }
Azure.IoT Build 11:62d7b956e76e 1790 else
Azure.IoT Build 11:62d7b956e76e 1791 {
AzureIoTClient 19:ea016664011a 1792 /* Codes_SRS_IOTHUBTRANSPORTAMQP_03_001: [If xio_setoption fails, IoTHubTransportAMQP_SetOption shall return IOTHUB_CLIENT_ERROR.] */
Azure.IoT Build 11:62d7b956e76e 1793 if (xio_setoption(transport_state->tls_io, option, value) == 0)
Azure.IoT Build 11:62d7b956e76e 1794 {
Azure.IoT Build 11:62d7b956e76e 1795 result = IOTHUB_CLIENT_OK;
Azure.IoT Build 11:62d7b956e76e 1796 }
Azure.IoT Build 11:62d7b956e76e 1797 else
Azure.IoT Build 11:62d7b956e76e 1798 {
Azure.IoT Build 11:62d7b956e76e 1799 result = IOTHUB_CLIENT_ERROR;
AzureIoTClient 13:a4af7c301e02 1800 LogError("Invalid option (%s) passed to uAMQP transport SetOption()", option);
Azure.IoT Build 11:62d7b956e76e 1801 }
Azure.IoT Build 11:62d7b956e76e 1802 }
Azure.IoT Build 10:75c5e0d8537d 1803 }
Azure.IoT Build 10:75c5e0d8537d 1804 }
AzureIoTClient 4:57e049bce51e 1805
AzureIoTClient 4:57e049bce51e 1806 return result;
AzureIoTClient 4:57e049bce51e 1807 }
AzureIoTClient 4:57e049bce51e 1808
AzureIoTClient 14:8e8e42008807 1809 static IOTHUB_DEVICE_HANDLE IoTHubTransportAMQP_Register(TRANSPORT_LL_HANDLE handle, const IOTHUB_DEVICE_CONFIG* device, IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, PDLIST_ENTRY waitingToSend)
Azure.IoT Build 10:75c5e0d8537d 1810 {
Azure.IoT Build 10:75c5e0d8537d 1811 IOTHUB_DEVICE_HANDLE result;
AzureIoTClient 19:ea016664011a 1812 // Codes_SRS_IOTHUBTRANSPORTAMQP_17_001: [IoTHubTransportAMQP_Register shall return NULL if device, or waitingToSend are NULL.]
AzureIoTClient 19:ea016664011a 1813 // Codes_SRS_IOTHUBTRANSPORTAMQP_17_005: [IoTHubTransportAMQP_Register shall return NULL if the TRANSPORT_LL_HANDLE is NULL.]
AzureIoTClient 16:a49121e2300b 1814 if ((handle == NULL) || (device == NULL) || (waitingToSend == NULL))
Azure.IoT Build 10:75c5e0d8537d 1815 {
AzureIoTClient 19:ea016664011a 1816 LogError("invalid parameter TRANSPORT_LL_HANDLE handle=%p, const IOTHUB_DEVICE_CONFIG* device=%p, IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle=%p, PDLIST_ENTRY waitingToSend=%p",
AzureIoTClient 19:ea016664011a 1817 handle, device, iotHubClientHandle, waitingToSend);
Azure.IoT Build 10:75c5e0d8537d 1818 result = NULL;
Azure.IoT Build 10:75c5e0d8537d 1819 }
Azure.IoT Build 10:75c5e0d8537d 1820 else
Azure.IoT Build 10:75c5e0d8537d 1821 {
Azure.IoT Build 10:75c5e0d8537d 1822 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle;
Azure.IoT Build 10:75c5e0d8537d 1823
AzureIoTClient 19:ea016664011a 1824 // Codes_SRS_IOTHUBTRANSPORTAMQP_03_002: [IoTHubTransportAMQP_Register shall return NULL if deviceId is NULL.**]
AzureIoTClient 19:ea016664011a 1825 if (device->deviceId == NULL)
AzureIoTClient 16:a49121e2300b 1826 {
AzureIoTClient 19:ea016664011a 1827 LogError("invalid parameter device->deviceId was NULL");
AzureIoTClient 16:a49121e2300b 1828 result = NULL;
AzureIoTClient 16:a49121e2300b 1829 }
AzureIoTClient 19:ea016664011a 1830 // Codes_SRS_IOTHUBTRANSPORTAMQP_03_003: [IoTHubTransportAMQP_Register shall return NULL if both deviceKey and deviceSasToken are not NULL.]
AzureIoTClient 16:a49121e2300b 1831 else if ( (device->deviceSasToken != NULL) && (device->deviceKey != NULL) )
AzureIoTClient 16:a49121e2300b 1832 {
AzureIoTClient 19:ea016664011a 1833 LogError("invalid parameter both device->deviceSasToken and device->deviceKey were NULL");
AzureIoTClient 16:a49121e2300b 1834 result = NULL;
AzureIoTClient 16:a49121e2300b 1835 }
AzureIoTClient 16:a49121e2300b 1836 else
AzureIoTClient 16:a49121e2300b 1837 {
AzureIoTClient 16:a49121e2300b 1838 STRING_HANDLE devicesPath = concat3Params(STRING_c_str(transport_state->iotHubHostFqdn), "/devices/", device->deviceId);
AzureIoTClient 19:ea016664011a 1839 if (devicesPath == NULL)
AzureIoTClient 19:ea016664011a 1840 {
AzureIoTClient 16:a49121e2300b 1841 LogError("Could not create devicesPath");
Azure.IoT Build 10:75c5e0d8537d 1842 result = NULL;
Azure.IoT Build 10:75c5e0d8537d 1843 }
Azure.IoT Build 10:75c5e0d8537d 1844 else
Azure.IoT Build 10:75c5e0d8537d 1845 {
AzureIoTClient 19:ea016664011a 1846 // Codes_SRS_IOTHUBTRANSPORTAMQP_17_002: [IoTHubTransportAMQP_Register shall return NULL if deviceId or deviceKey do not match the deviceId and deviceKey passed in during IoTHubTransportAMQP_Create.]
AzureIoTClient 19:ea016664011a 1847 if (strcmp(STRING_c_str(transport_state->devicesPath), STRING_c_str(devicesPath)) != 0)
Azure.IoT Build 10:75c5e0d8537d 1848 {
AzureIoTClient 19:ea016664011a 1849 LogError("Attemping to add new device to AMQP transport, not allowed.");
AzureIoTClient 19:ea016664011a 1850 result = NULL;
AzureIoTClient 19:ea016664011a 1851 }
AzureIoTClient 19:ea016664011a 1852 else if ((transport_state->credential.credentialType == DEVICE_KEY) && strcmp(STRING_c_str(transport_state->credential.credential.deviceKey), device->deviceKey) != 0)
AzureIoTClient 19:ea016664011a 1853 {
AzureIoTClient 19:ea016664011a 1854 LogError("Attemping to add new device to AMQP transport, not allowed.");
Azure.IoT Build 10:75c5e0d8537d 1855 result = NULL;
Azure.IoT Build 10:75c5e0d8537d 1856 }
Azure.IoT Build 10:75c5e0d8537d 1857 else
Azure.IoT Build 10:75c5e0d8537d 1858 {
AzureIoTClient 19:ea016664011a 1859 if (transport_state->isRegistered == true)
AzureIoTClient 19:ea016664011a 1860 {
AzureIoTClient 19:ea016664011a 1861 LogError("Transport already has device registered by id: [%s]", device->deviceId);
AzureIoTClient 19:ea016664011a 1862 result = NULL;
AzureIoTClient 19:ea016664011a 1863 }
AzureIoTClient 19:ea016664011a 1864 else
AzureIoTClient 19:ea016664011a 1865 {
AzureIoTClient 19:ea016664011a 1866 transport_state->isRegistered = true;
AzureIoTClient 19:ea016664011a 1867 // Codes_SRS_IOTHUBTRANSPORTAMQP_17_003: [IoTHubTransportAMQP_Register shall return the TRANSPORT_LL_HANDLE as the IOTHUB_DEVICE_HANDLE.]
AzureIoTClient 19:ea016664011a 1868 result = (IOTHUB_DEVICE_HANDLE)handle;
AzureIoTClient 19:ea016664011a 1869 }
Azure.IoT Build 10:75c5e0d8537d 1870 }
AzureIoTClient 19:ea016664011a 1871 STRING_delete(devicesPath);
Azure.IoT Build 10:75c5e0d8537d 1872 }
Azure.IoT Build 10:75c5e0d8537d 1873 }
Azure.IoT Build 10:75c5e0d8537d 1874 }
Azure.IoT Build 10:75c5e0d8537d 1875
Azure.IoT Build 10:75c5e0d8537d 1876 return result;
Azure.IoT Build 10:75c5e0d8537d 1877 }
Azure.IoT Build 10:75c5e0d8537d 1878
AzureIoTClient 19:ea016664011a 1879 // Codes_SRS_IOTHUBTRANSPORTAMQP_17_004: [IoTHubTransportAMQP_Unregister shall return.]
Azure.IoT Build 12:841a4c36bd36 1880 static void IoTHubTransportAMQP_Unregister(IOTHUB_DEVICE_HANDLE deviceHandle)
Azure.IoT Build 10:75c5e0d8537d 1881 {
Azure.IoT Build 10:75c5e0d8537d 1882 if (deviceHandle != NULL)
Azure.IoT Build 10:75c5e0d8537d 1883 {
Azure.IoT Build 10:75c5e0d8537d 1884 AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)deviceHandle;
Azure.IoT Build 10:75c5e0d8537d 1885
Azure.IoT Build 10:75c5e0d8537d 1886 transport_state->isRegistered = false;
Azure.IoT Build 10:75c5e0d8537d 1887 }
Azure.IoT Build 10:75c5e0d8537d 1888 }
Azure.IoT Build 10:75c5e0d8537d 1889
AzureIoTClient 17:597443dc65a4 1890 static STRING_HANDLE IoTHubTransportAMQP_GetHostname(TRANSPORT_LL_HANDLE handle)
AzureIoTClient 17:597443dc65a4 1891 {
AzureIoTClient 17:597443dc65a4 1892 STRING_HANDLE result;
AzureIoTClient 17:597443dc65a4 1893 /*Codes_SRS_IOTHUBTRANSPORTAMQP_02_001: [ If parameter handle is NULL then IoTHubTransportAMQP_GetHostname shall return NULL. ]*/
AzureIoTClient 17:597443dc65a4 1894 if (handle == NULL)
AzureIoTClient 17:597443dc65a4 1895 {
AzureIoTClient 17:597443dc65a4 1896 result = NULL;
AzureIoTClient 17:597443dc65a4 1897 }
AzureIoTClient 17:597443dc65a4 1898 else
AzureIoTClient 17:597443dc65a4 1899 {
AzureIoTClient 17:597443dc65a4 1900 /*Codes_SRS_IOTHUBTRANSPORTAMQP_02_002: [ Otherwise IoTHubTransportAMQP_GetHostname shall return a STRING_HANDLE for the hostname. ]*/
AzureIoTClient 17:597443dc65a4 1901 result = ((AMQP_TRANSPORT_INSTANCE*)(handle))->iotHubHostFqdn;
AzureIoTClient 17:597443dc65a4 1902 }
AzureIoTClient 17:597443dc65a4 1903 return result;
AzureIoTClient 17:597443dc65a4 1904 }
AzureIoTClient 17:597443dc65a4 1905
Azure.IoT Build 7:07bc440836b3 1906 static TRANSPORT_PROVIDER thisTransportProvider = {
AzureIoTClient 17:597443dc65a4 1907 IoTHubTransportAMQP_GetHostname,
Azure.IoT Build 11:62d7b956e76e 1908 IoTHubTransportAMQP_SetOption,
Azure.IoT Build 11:62d7b956e76e 1909 IoTHubTransportAMQP_Create,
Azure.IoT Build 11:62d7b956e76e 1910 IoTHubTransportAMQP_Destroy,
Azure.IoT Build 12:841a4c36bd36 1911 IoTHubTransportAMQP_Register,
Azure.IoT Build 12:841a4c36bd36 1912 IoTHubTransportAMQP_Unregister,
Azure.IoT Build 11:62d7b956e76e 1913 IoTHubTransportAMQP_Subscribe,
Azure.IoT Build 11:62d7b956e76e 1914 IoTHubTransportAMQP_Unsubscribe,
Azure.IoT Build 11:62d7b956e76e 1915 IoTHubTransportAMQP_DoWork,
Azure.IoT Build 7:07bc440836b3 1916 IoTHubTransportAMQP_GetSendStatus
AzureIoTClient 4:57e049bce51e 1917 };
AzureIoTClient 4:57e049bce51e 1918
AzureIoTClient 17:597443dc65a4 1919 extern const TRANSPORT_PROVIDER* AMQP_Protocol(void)
AzureIoTClient 4:57e049bce51e 1920 {
Azure.IoT Build 7:07bc440836b3 1921 return &thisTransportProvider;
AzureIoTClient 4:57e049bce51e 1922 }