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