Microsoft Azure IoTHub client AMQP transport

Dependents:   sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp iothub_client_sample_amqp ... more

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

Committer:
Azure.IoT Build
Date:
Fri Jul 01 10:42:04 2016 -0700
Revision:
18:239d162e3607
Parent:
17:597443dc65a4
Child:
19:ea016664011a
1.0.10

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