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