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