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