Microsoft Azure IoTHub client AMQP transport

Dependents:   sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp iothub_client_sample_amqp ... more

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

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