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
iothubtransport_amqp_twin_messenger.c@57:56ac1346c70d, 2018-10-04 (annotated)
- Committer:
- AzureIoTClient
- Date:
- Thu Oct 04 09:14:47 2018 -0700
- Revision:
- 57:56ac1346c70d
- Parent:
- 56:8704100b3b54
1.2.10
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AzureIoTClient | 39:e98d5df6dc74 | 1 | // Copyright (c) Microsoft. All rights reserved. |
AzureIoTClient | 39:e98d5df6dc74 | 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
AzureIoTClient | 39:e98d5df6dc74 | 3 | |
AzureIoTClient | 39:e98d5df6dc74 | 4 | #include <stdlib.h> |
AzureIoTClient | 39:e98d5df6dc74 | 5 | #include <stdint.h> |
AzureIoTClient | 39:e98d5df6dc74 | 6 | #include <stdbool.h> |
AzureIoTClient | 39:e98d5df6dc74 | 7 | #include "azure_c_shared_utility/optimize_size.h" |
AzureIoTClient | 39:e98d5df6dc74 | 8 | #include "azure_c_shared_utility/crt_abstractions.h" |
AzureIoTClient | 39:e98d5df6dc74 | 9 | #include "azure_c_shared_utility/gballoc.h" |
AzureIoTClient | 56:8704100b3b54 | 10 | #include "azure_c_shared_utility/agenttime.h" |
AzureIoTClient | 39:e98d5df6dc74 | 11 | #include "azure_c_shared_utility/xlogging.h" |
AzureIoTClient | 39:e98d5df6dc74 | 12 | #include "azure_c_shared_utility/uniqueid.h" |
AzureIoTClient | 39:e98d5df6dc74 | 13 | #include "azure_c_shared_utility/singlylinkedlist.h" |
AzureIoTClient | 50:f3a92c6c6534 | 14 | #include "azure_uamqp_c/amqp_definitions_fields.h" |
AzureIoTClient | 39:e98d5df6dc74 | 15 | #include "azure_uamqp_c/messaging.h" |
AzureIoTClient | 53:e21e1e88460f | 16 | #include "internal/iothub_client_private.h" |
AzureIoTClient | 53:e21e1e88460f | 17 | #include "internal/iothubtransport_amqp_messenger.h" |
AzureIoTClient | 53:e21e1e88460f | 18 | #include "internal/iothubtransport_amqp_twin_messenger.h" |
AzureIoTClient | 39:e98d5df6dc74 | 19 | |
AzureIoTClient | 39:e98d5df6dc74 | 20 | DEFINE_ENUM_STRINGS(TWIN_MESSENGER_SEND_STATUS, TWIN_MESSENGER_SEND_STATUS_VALUES); |
AzureIoTClient | 39:e98d5df6dc74 | 21 | DEFINE_ENUM_STRINGS(TWIN_REPORT_STATE_RESULT, TWIN_REPORT_STATE_RESULT_VALUES); |
AzureIoTClient | 39:e98d5df6dc74 | 22 | DEFINE_ENUM_STRINGS(TWIN_REPORT_STATE_REASON, TWIN_REPORT_STATE_REASON_VALUES); |
AzureIoTClient | 39:e98d5df6dc74 | 23 | DEFINE_ENUM_STRINGS(TWIN_MESSENGER_STATE, TWIN_MESSENGER_STATE_VALUES); |
AzureIoTClient | 39:e98d5df6dc74 | 24 | DEFINE_ENUM_STRINGS(TWIN_UPDATE_TYPE, TWIN_UPDATE_TYPE_VALUES); |
AzureIoTClient | 39:e98d5df6dc74 | 25 | |
AzureIoTClient | 39:e98d5df6dc74 | 26 | |
AzureIoTClient | 39:e98d5df6dc74 | 27 | #define RESULT_OK 0 |
AzureIoTClient | 39:e98d5df6dc74 | 28 | #define INDEFINITE_TIME ((time_t)(-1)) |
AzureIoTClient | 39:e98d5df6dc74 | 29 | |
AzureIoTClient | 56:8704100b3b54 | 30 | #define CLIENT_VERSION_PROPERTY_NAME "com.microsoft:client-version" |
AzureIoTClient | 39:e98d5df6dc74 | 31 | #define UNIQUE_ID_BUFFER_SIZE 37 |
AzureIoTClient | 39:e98d5df6dc74 | 32 | |
AzureIoTClient | 39:e98d5df6dc74 | 33 | #define EMPTY_TWIN_BODY_DATA ((const unsigned char*)" ") |
AzureIoTClient | 39:e98d5df6dc74 | 34 | #define EMPTY_TWIN_BODY_SIZE 1 |
AzureIoTClient | 39:e98d5df6dc74 | 35 | |
AzureIoTClient | 56:8704100b3b54 | 36 | #define TWIN_MESSAGE_PROPERTY_OPERATION "operation" |
AzureIoTClient | 56:8704100b3b54 | 37 | #define TWIN_MESSAGE_PROPERTY_RESOURCE "resource" |
AzureIoTClient | 56:8704100b3b54 | 38 | #define TWIN_MESSAGE_PROPERTY_VERSION "version" |
AzureIoTClient | 56:8704100b3b54 | 39 | #define TWIN_MESSAGE_PROPERTY_STATUS "status" |
AzureIoTClient | 39:e98d5df6dc74 | 40 | |
AzureIoTClient | 56:8704100b3b54 | 41 | #define TWIN_RESOURCE_DESIRED "/notifications/twin/properties/desired" |
AzureIoTClient | 56:8704100b3b54 | 42 | #define TWIN_RESOURCE_REPORTED "/properties/reported" |
AzureIoTClient | 39:e98d5df6dc74 | 43 | |
AzureIoTClient | 56:8704100b3b54 | 44 | #define TWIN_CORRELATION_ID_PROPERTY_NAME "com.microsoft:channel-correlation-id" |
AzureIoTClient | 56:8704100b3b54 | 45 | #define TWIN_API_VERSION_PROPERTY_NAME "com.microsoft:api-version" |
AzureIoTClient | 56:8704100b3b54 | 46 | #define TWIN_CORRELATION_ID_PROPERTY_FORMAT "twin:%s" |
AzureIoTClient | 56:8704100b3b54 | 47 | #define TWIN_API_VERSION_NUMBER "2016-11-14" |
AzureIoTClient | 39:e98d5df6dc74 | 48 | |
AzureIoTClient | 56:8704100b3b54 | 49 | #define DEFAULT_MAX_TWIN_SUBSCRIPTION_ERROR_COUNT 3 |
AzureIoTClient | 56:8704100b3b54 | 50 | #define DEFAULT_TWIN_OPERATION_TIMEOUT_SECS 300.0 |
AzureIoTClient | 39:e98d5df6dc74 | 51 | |
AzureIoTClient | 56:8704100b3b54 | 52 | static char* DEFAULT_TWIN_SEND_LINK_SOURCE_NAME = "twin"; |
AzureIoTClient | 56:8704100b3b54 | 53 | static char* DEFAULT_TWIN_RECEIVE_LINK_TARGET_NAME = "twin"; |
AzureIoTClient | 39:e98d5df6dc74 | 54 | |
AzureIoTClient | 56:8704100b3b54 | 55 | static const char* TWIN_OPERATION_PATCH = "PATCH"; |
AzureIoTClient | 56:8704100b3b54 | 56 | static const char* TWIN_OPERATION_GET = "GET"; |
AzureIoTClient | 56:8704100b3b54 | 57 | static const char* TWIN_OPERATION_PUT = "PUT"; |
AzureIoTClient | 56:8704100b3b54 | 58 | static const char* TWIN_OPERATION_DELETE = "DELETE"; |
AzureIoTClient | 39:e98d5df6dc74 | 59 | |
AzureIoTClient | 39:e98d5df6dc74 | 60 | |
AzureIoTClient | 39:e98d5df6dc74 | 61 | #define TWIN_OPERATION_TYPE_STRINGS \ |
AzureIoTClient | 56:8704100b3b54 | 62 | TWIN_OPERATION_TYPE_PATCH, \ |
AzureIoTClient | 56:8704100b3b54 | 63 | TWIN_OPERATION_TYPE_GET, \ |
AzureIoTClient | 56:8704100b3b54 | 64 | TWIN_OPERATION_TYPE_PUT, \ |
AzureIoTClient | 56:8704100b3b54 | 65 | TWIN_OPERATION_TYPE_DELETE |
AzureIoTClient | 39:e98d5df6dc74 | 66 | |
AzureIoTClient | 39:e98d5df6dc74 | 67 | DEFINE_LOCAL_ENUM(TWIN_OPERATION_TYPE, TWIN_OPERATION_TYPE_STRINGS); |
AzureIoTClient | 39:e98d5df6dc74 | 68 | |
AzureIoTClient | 39:e98d5df6dc74 | 69 | #define TWIN_SUBSCRIPTION_STATE_STRINGS \ |
AzureIoTClient | 56:8704100b3b54 | 70 | TWIN_SUBSCRIPTION_STATE_NOT_SUBSCRIBED, \ |
AzureIoTClient | 56:8704100b3b54 | 71 | TWIN_SUBSCRIPTION_STATE_GET_COMPLETE_PROPERTIES, \ |
AzureIoTClient | 56:8704100b3b54 | 72 | TWIN_SUBSCRIPTION_STATE_GETTING_COMPLETE_PROPERTIES, \ |
AzureIoTClient | 56:8704100b3b54 | 73 | TWIN_SUBSCRIPTION_STATE_SUBSCRIBE_FOR_UPDATES, \ |
AzureIoTClient | 56:8704100b3b54 | 74 | TWIN_SUBSCRIPTION_STATE_SUBSCRIBING, \ |
AzureIoTClient | 56:8704100b3b54 | 75 | TWIN_SUBSCRIPTION_STATE_SUBSCRIBED, \ |
AzureIoTClient | 56:8704100b3b54 | 76 | TWIN_SUBSCRIPTION_STATE_UNSUBSCRIBE, \ |
AzureIoTClient | 56:8704100b3b54 | 77 | TWIN_SUBSCRIPTION_STATE_UNSUBSCRIBING |
AzureIoTClient | 39:e98d5df6dc74 | 78 | |
AzureIoTClient | 56:8704100b3b54 | 79 | // Suppress unused function warning for TWIN_SUBSCRIPTION_STATEstrings |
AzureIoTClient | 50:f3a92c6c6534 | 80 | #ifdef __APPLE__ |
AzureIoTClient | 50:f3a92c6c6534 | 81 | #pragma clang diagnostic push |
AzureIoTClient | 50:f3a92c6c6534 | 82 | #pragma clang diagnostic ignored "-Wunused-function" |
AzureIoTClient | 50:f3a92c6c6534 | 83 | #endif |
AzureIoTClient | 39:e98d5df6dc74 | 84 | DEFINE_LOCAL_ENUM(TWIN_SUBSCRIPTION_STATE, TWIN_SUBSCRIPTION_STATE_STRINGS); |
AzureIoTClient | 50:f3a92c6c6534 | 85 | #ifdef __APPLE__ |
AzureIoTClient | 50:f3a92c6c6534 | 86 | #pragma clang diagnostic pop |
AzureIoTClient | 50:f3a92c6c6534 | 87 | #endif |
AzureIoTClient | 39:e98d5df6dc74 | 88 | |
AzureIoTClient | 39:e98d5df6dc74 | 89 | typedef struct TWIN_MESSENGER_INSTANCE_TAG |
AzureIoTClient | 39:e98d5df6dc74 | 90 | { |
AzureIoTClient | 56:8704100b3b54 | 91 | char* client_version; |
AzureIoTClient | 56:8704100b3b54 | 92 | char* device_id; |
AzureIoTClient | 56:8704100b3b54 | 93 | char* module_id; |
AzureIoTClient | 56:8704100b3b54 | 94 | char* iothub_host_fqdn; |
AzureIoTClient | 39:e98d5df6dc74 | 95 | |
AzureIoTClient | 56:8704100b3b54 | 96 | TWIN_MESSENGER_STATE state; |
AzureIoTClient | 56:8704100b3b54 | 97 | |
AzureIoTClient | 56:8704100b3b54 | 98 | SINGLYLINKEDLIST_HANDLE pending_patches; |
AzureIoTClient | 56:8704100b3b54 | 99 | SINGLYLINKEDLIST_HANDLE operations; |
AzureIoTClient | 39:e98d5df6dc74 | 100 | |
AzureIoTClient | 56:8704100b3b54 | 101 | TWIN_MESSENGER_STATE_CHANGED_CALLBACK on_state_changed_callback; |
AzureIoTClient | 56:8704100b3b54 | 102 | void* on_state_changed_context; |
AzureIoTClient | 39:e98d5df6dc74 | 103 | |
AzureIoTClient | 56:8704100b3b54 | 104 | TWIN_SUBSCRIPTION_STATE subscription_state; |
AzureIoTClient | 56:8704100b3b54 | 105 | size_t subscription_error_count; |
AzureIoTClient | 56:8704100b3b54 | 106 | TWIN_STATE_UPDATE_CALLBACK on_message_received_callback; |
AzureIoTClient | 56:8704100b3b54 | 107 | void* on_message_received_context; |
AzureIoTClient | 39:e98d5df6dc74 | 108 | |
AzureIoTClient | 56:8704100b3b54 | 109 | AMQP_MESSENGER_HANDLE amqp_msgr; |
AzureIoTClient | 56:8704100b3b54 | 110 | AMQP_MESSENGER_STATE amqp_msgr_state; |
AzureIoTClient | 56:8704100b3b54 | 111 | bool amqp_msgr_is_subscribed; |
AzureIoTClient | 39:e98d5df6dc74 | 112 | } TWIN_MESSENGER_INSTANCE; |
AzureIoTClient | 39:e98d5df6dc74 | 113 | |
AzureIoTClient | 39:e98d5df6dc74 | 114 | typedef struct TWIN_PATCH_OPERATION_CONTEXT_TAG |
AzureIoTClient | 39:e98d5df6dc74 | 115 | { |
AzureIoTClient | 56:8704100b3b54 | 116 | CONSTBUFFER_HANDLE data; |
AzureIoTClient | 56:8704100b3b54 | 117 | TWIN_MESSENGER_REPORT_STATE_COMPLETE_CALLBACK on_report_state_complete_callback; |
AzureIoTClient | 56:8704100b3b54 | 118 | const void* on_report_state_complete_context; |
AzureIoTClient | 56:8704100b3b54 | 119 | time_t time_enqueued; |
AzureIoTClient | 39:e98d5df6dc74 | 120 | } TWIN_PATCH_OPERATION_CONTEXT; |
AzureIoTClient | 39:e98d5df6dc74 | 121 | |
AzureIoTClient | 39:e98d5df6dc74 | 122 | typedef struct TWIN_OPERATION_CONTEXT_TAG |
AzureIoTClient | 39:e98d5df6dc74 | 123 | { |
AzureIoTClient | 56:8704100b3b54 | 124 | TWIN_OPERATION_TYPE type; |
AzureIoTClient | 56:8704100b3b54 | 125 | TWIN_MESSENGER_INSTANCE* msgr; |
AzureIoTClient | 56:8704100b3b54 | 126 | char* correlation_id; |
AzureIoTClient | 56:8704100b3b54 | 127 | TWIN_MESSENGER_REPORT_STATE_COMPLETE_CALLBACK on_report_state_complete_callback; |
AzureIoTClient | 56:8704100b3b54 | 128 | const void* on_report_state_complete_context; |
AzureIoTClient | 56:8704100b3b54 | 129 | time_t time_sent; |
AzureIoTClient | 39:e98d5df6dc74 | 130 | } TWIN_OPERATION_CONTEXT; |
AzureIoTClient | 39:e98d5df6dc74 | 131 | |
AzureIoTClient | 39:e98d5df6dc74 | 132 | |
AzureIoTClient | 39:e98d5df6dc74 | 133 | |
AzureIoTClient | 39:e98d5df6dc74 | 134 | |
AzureIoTClient | 39:e98d5df6dc74 | 135 | static void update_state(TWIN_MESSENGER_INSTANCE* twin_msgr, TWIN_MESSENGER_STATE new_state) |
AzureIoTClient | 39:e98d5df6dc74 | 136 | { |
AzureIoTClient | 56:8704100b3b54 | 137 | if (new_state != twin_msgr->state) |
AzureIoTClient | 56:8704100b3b54 | 138 | { |
AzureIoTClient | 56:8704100b3b54 | 139 | TWIN_MESSENGER_STATE previous_state = twin_msgr->state; |
AzureIoTClient | 56:8704100b3b54 | 140 | twin_msgr->state = new_state; |
AzureIoTClient | 39:e98d5df6dc74 | 141 | |
AzureIoTClient | 56:8704100b3b54 | 142 | if (twin_msgr->on_state_changed_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 143 | { |
AzureIoTClient | 56:8704100b3b54 | 144 | twin_msgr->on_state_changed_callback(twin_msgr->on_state_changed_context, previous_state, new_state); |
AzureIoTClient | 56:8704100b3b54 | 145 | } |
AzureIoTClient | 56:8704100b3b54 | 146 | } |
AzureIoTClient | 39:e98d5df6dc74 | 147 | } |
AzureIoTClient | 39:e98d5df6dc74 | 148 | |
AzureIoTClient | 39:e98d5df6dc74 | 149 | //---------- AMQP Helper Functions ----------// |
AzureIoTClient | 39:e98d5df6dc74 | 150 | |
AzureIoTClient | 39:e98d5df6dc74 | 151 | static int set_message_correlation_id(MESSAGE_HANDLE message, const char* value) |
AzureIoTClient | 39:e98d5df6dc74 | 152 | { |
AzureIoTClient | 56:8704100b3b54 | 153 | int result; |
AzureIoTClient | 56:8704100b3b54 | 154 | PROPERTIES_HANDLE properties = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 155 | |
AzureIoTClient | 56:8704100b3b54 | 156 | if (message_get_properties(message, &properties) != 0) |
AzureIoTClient | 56:8704100b3b54 | 157 | { |
AzureIoTClient | 56:8704100b3b54 | 158 | LogError("Failed getting the AMQP message properties"); |
AzureIoTClient | 56:8704100b3b54 | 159 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 160 | } |
AzureIoTClient | 56:8704100b3b54 | 161 | else if (properties == NULL && (properties = properties_create()) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 162 | { |
AzureIoTClient | 56:8704100b3b54 | 163 | LogError("Failed creating properties for AMQP message"); |
AzureIoTClient | 56:8704100b3b54 | 164 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 165 | } |
AzureIoTClient | 56:8704100b3b54 | 166 | else |
AzureIoTClient | 56:8704100b3b54 | 167 | { |
AzureIoTClient | 56:8704100b3b54 | 168 | AMQP_VALUE amqp_value; |
AzureIoTClient | 39:e98d5df6dc74 | 169 | |
AzureIoTClient | 56:8704100b3b54 | 170 | if ((amqp_value = amqpvalue_create_string(value)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 171 | { |
AzureIoTClient | 56:8704100b3b54 | 172 | LogError("Failed creating AMQP value for correlation-id"); |
AzureIoTClient | 56:8704100b3b54 | 173 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 174 | } |
AzureIoTClient | 56:8704100b3b54 | 175 | else |
AzureIoTClient | 56:8704100b3b54 | 176 | { |
AzureIoTClient | 56:8704100b3b54 | 177 | if (properties_set_correlation_id(properties, amqp_value) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 178 | { |
AzureIoTClient | 56:8704100b3b54 | 179 | LogError("Failed setting the correlation id"); |
AzureIoTClient | 56:8704100b3b54 | 180 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 181 | } |
AzureIoTClient | 56:8704100b3b54 | 182 | else if (message_set_properties(message, properties) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 183 | { |
AzureIoTClient | 56:8704100b3b54 | 184 | LogError("Failed setting the AMQP message properties"); |
AzureIoTClient | 56:8704100b3b54 | 185 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 186 | } |
AzureIoTClient | 56:8704100b3b54 | 187 | else |
AzureIoTClient | 56:8704100b3b54 | 188 | { |
AzureIoTClient | 56:8704100b3b54 | 189 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 190 | } |
AzureIoTClient | 39:e98d5df6dc74 | 191 | |
AzureIoTClient | 56:8704100b3b54 | 192 | amqpvalue_destroy(amqp_value); |
AzureIoTClient | 56:8704100b3b54 | 193 | } |
AzureIoTClient | 39:e98d5df6dc74 | 194 | |
AzureIoTClient | 56:8704100b3b54 | 195 | properties_destroy(properties); |
AzureIoTClient | 56:8704100b3b54 | 196 | } |
AzureIoTClient | 39:e98d5df6dc74 | 197 | |
AzureIoTClient | 56:8704100b3b54 | 198 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 199 | } |
AzureIoTClient | 39:e98d5df6dc74 | 200 | |
AzureIoTClient | 39:e98d5df6dc74 | 201 | static int get_message_correlation_id(MESSAGE_HANDLE message, char** correlation_id) |
AzureIoTClient | 39:e98d5df6dc74 | 202 | { |
AzureIoTClient | 56:8704100b3b54 | 203 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 204 | |
AzureIoTClient | 56:8704100b3b54 | 205 | PROPERTIES_HANDLE properties; |
AzureIoTClient | 56:8704100b3b54 | 206 | AMQP_VALUE amqp_value; |
AzureIoTClient | 39:e98d5df6dc74 | 207 | |
AzureIoTClient | 56:8704100b3b54 | 208 | if (message_get_properties(message, &properties) != 0) |
AzureIoTClient | 56:8704100b3b54 | 209 | { |
AzureIoTClient | 56:8704100b3b54 | 210 | LogError("Failed getting AMQP message properties"); |
AzureIoTClient | 56:8704100b3b54 | 211 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 212 | } |
AzureIoTClient | 56:8704100b3b54 | 213 | else if (properties == NULL) |
AzureIoTClient | 56:8704100b3b54 | 214 | { |
AzureIoTClient | 56:8704100b3b54 | 215 | *correlation_id = NULL; |
AzureIoTClient | 56:8704100b3b54 | 216 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 217 | } |
AzureIoTClient | 56:8704100b3b54 | 218 | else |
AzureIoTClient | 56:8704100b3b54 | 219 | { |
AzureIoTClient | 56:8704100b3b54 | 220 | if (properties_get_correlation_id(properties, &amqp_value) != 0 || amqp_value == NULL) |
AzureIoTClient | 56:8704100b3b54 | 221 | { |
AzureIoTClient | 56:8704100b3b54 | 222 | *correlation_id = NULL; |
AzureIoTClient | 56:8704100b3b54 | 223 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 224 | } |
AzureIoTClient | 56:8704100b3b54 | 225 | else |
AzureIoTClient | 56:8704100b3b54 | 226 | { |
AzureIoTClient | 56:8704100b3b54 | 227 | const char* value; |
AzureIoTClient | 39:e98d5df6dc74 | 228 | |
AzureIoTClient | 56:8704100b3b54 | 229 | if (amqpvalue_get_string(amqp_value, &value) != 0) |
AzureIoTClient | 56:8704100b3b54 | 230 | { |
AzureIoTClient | 56:8704100b3b54 | 231 | LogError("Failed retrieving string from AMQP value"); |
AzureIoTClient | 56:8704100b3b54 | 232 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 233 | } |
AzureIoTClient | 56:8704100b3b54 | 234 | else if (mallocAndStrcpy_s(correlation_id, value) != 0) |
AzureIoTClient | 56:8704100b3b54 | 235 | { |
AzureIoTClient | 56:8704100b3b54 | 236 | LogError("Failed cloning correlation-id"); |
AzureIoTClient | 56:8704100b3b54 | 237 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 238 | } |
AzureIoTClient | 56:8704100b3b54 | 239 | else |
AzureIoTClient | 56:8704100b3b54 | 240 | { |
AzureIoTClient | 56:8704100b3b54 | 241 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 242 | } |
AzureIoTClient | 56:8704100b3b54 | 243 | } |
AzureIoTClient | 39:e98d5df6dc74 | 244 | |
AzureIoTClient | 56:8704100b3b54 | 245 | properties_destroy(properties); |
AzureIoTClient | 56:8704100b3b54 | 246 | } |
AzureIoTClient | 39:e98d5df6dc74 | 247 | |
AzureIoTClient | 56:8704100b3b54 | 248 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 249 | } |
AzureIoTClient | 39:e98d5df6dc74 | 250 | |
AzureIoTClient | 39:e98d5df6dc74 | 251 | static int add_map_item(AMQP_VALUE map, const char* name, const char* value) |
AzureIoTClient | 39:e98d5df6dc74 | 252 | { |
AzureIoTClient | 56:8704100b3b54 | 253 | int result; |
AzureIoTClient | 56:8704100b3b54 | 254 | AMQP_VALUE amqp_value_name; |
AzureIoTClient | 56:8704100b3b54 | 255 | |
AzureIoTClient | 56:8704100b3b54 | 256 | if ((amqp_value_name = amqpvalue_create_symbol(name)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 257 | { |
AzureIoTClient | 56:8704100b3b54 | 258 | LogError("Failed creating AMQP_VALUE for name"); |
AzureIoTClient | 56:8704100b3b54 | 259 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 260 | } |
AzureIoTClient | 56:8704100b3b54 | 261 | else |
AzureIoTClient | 56:8704100b3b54 | 262 | { |
AzureIoTClient | 56:8704100b3b54 | 263 | AMQP_VALUE amqp_value_value = NULL; |
AzureIoTClient | 39:e98d5df6dc74 | 264 | |
AzureIoTClient | 56:8704100b3b54 | 265 | if (value == NULL && (amqp_value_value = amqpvalue_create_null()) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 266 | { |
AzureIoTClient | 56:8704100b3b54 | 267 | LogError("Failed creating AMQP_VALUE for NULL value"); |
AzureIoTClient | 56:8704100b3b54 | 268 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 269 | } |
AzureIoTClient | 56:8704100b3b54 | 270 | else if (value != NULL && (amqp_value_value = amqpvalue_create_string(value)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 271 | { |
AzureIoTClient | 56:8704100b3b54 | 272 | LogError("Failed creating AMQP_VALUE for value"); |
AzureIoTClient | 56:8704100b3b54 | 273 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 274 | } |
AzureIoTClient | 56:8704100b3b54 | 275 | else |
AzureIoTClient | 56:8704100b3b54 | 276 | { |
AzureIoTClient | 56:8704100b3b54 | 277 | if (amqpvalue_set_map_value(map, amqp_value_name, amqp_value_value) != 0) |
AzureIoTClient | 56:8704100b3b54 | 278 | { |
AzureIoTClient | 56:8704100b3b54 | 279 | LogError("Failed adding key/value pair to map"); |
AzureIoTClient | 56:8704100b3b54 | 280 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 281 | } |
AzureIoTClient | 56:8704100b3b54 | 282 | else |
AzureIoTClient | 56:8704100b3b54 | 283 | { |
AzureIoTClient | 56:8704100b3b54 | 284 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 285 | } |
AzureIoTClient | 39:e98d5df6dc74 | 286 | |
AzureIoTClient | 56:8704100b3b54 | 287 | amqpvalue_destroy(amqp_value_value); |
AzureIoTClient | 56:8704100b3b54 | 288 | } |
AzureIoTClient | 39:e98d5df6dc74 | 289 | |
AzureIoTClient | 56:8704100b3b54 | 290 | amqpvalue_destroy(amqp_value_name); |
AzureIoTClient | 56:8704100b3b54 | 291 | } |
AzureIoTClient | 39:e98d5df6dc74 | 292 | |
AzureIoTClient | 56:8704100b3b54 | 293 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 294 | } |
AzureIoTClient | 39:e98d5df6dc74 | 295 | |
AzureIoTClient | 39:e98d5df6dc74 | 296 | static int add_amqp_message_annotation(MESSAGE_HANDLE message, AMQP_VALUE msg_annotations_map) |
AzureIoTClient | 39:e98d5df6dc74 | 297 | { |
AzureIoTClient | 56:8704100b3b54 | 298 | int result; |
AzureIoTClient | 56:8704100b3b54 | 299 | AMQP_VALUE msg_annotations; |
AzureIoTClient | 39:e98d5df6dc74 | 300 | |
AzureIoTClient | 56:8704100b3b54 | 301 | if ((msg_annotations = amqpvalue_create_message_annotations(msg_annotations_map)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 302 | { |
AzureIoTClient | 56:8704100b3b54 | 303 | LogError("Failed creating new AMQP message annotations"); |
AzureIoTClient | 56:8704100b3b54 | 304 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 305 | } |
AzureIoTClient | 56:8704100b3b54 | 306 | else |
AzureIoTClient | 56:8704100b3b54 | 307 | { |
AzureIoTClient | 56:8704100b3b54 | 308 | if (message_set_message_annotations(message, (annotations)msg_annotations) != 0) |
AzureIoTClient | 56:8704100b3b54 | 309 | { |
AzureIoTClient | 56:8704100b3b54 | 310 | LogError("Failed setting AMQP message annotations"); |
AzureIoTClient | 56:8704100b3b54 | 311 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 312 | } |
AzureIoTClient | 56:8704100b3b54 | 313 | else |
AzureIoTClient | 56:8704100b3b54 | 314 | { |
AzureIoTClient | 56:8704100b3b54 | 315 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 316 | } |
AzureIoTClient | 39:e98d5df6dc74 | 317 | |
AzureIoTClient | 56:8704100b3b54 | 318 | annotations_destroy(msg_annotations); |
AzureIoTClient | 56:8704100b3b54 | 319 | } |
AzureIoTClient | 39:e98d5df6dc74 | 320 | |
AzureIoTClient | 56:8704100b3b54 | 321 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 322 | } |
AzureIoTClient | 39:e98d5df6dc74 | 323 | |
AzureIoTClient | 39:e98d5df6dc74 | 324 | |
AzureIoTClient | 39:e98d5df6dc74 | 325 | //---------- TWIN Helpers ----------// |
AzureIoTClient | 39:e98d5df6dc74 | 326 | |
AzureIoTClient | 39:e98d5df6dc74 | 327 | static char* generate_unique_id() |
AzureIoTClient | 39:e98d5df6dc74 | 328 | { |
AzureIoTClient | 56:8704100b3b54 | 329 | char* result; |
AzureIoTClient | 39:e98d5df6dc74 | 330 | |
AzureIoTClient | 56:8704100b3b54 | 331 | if ((result = (char*)malloc(sizeof(char) * UNIQUE_ID_BUFFER_SIZE + 1)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 332 | { |
AzureIoTClient | 56:8704100b3b54 | 333 | LogError("Failed generating an unique tag (malloc failed)"); |
AzureIoTClient | 56:8704100b3b54 | 334 | } |
AzureIoTClient | 56:8704100b3b54 | 335 | else |
AzureIoTClient | 56:8704100b3b54 | 336 | { |
AzureIoTClient | 56:8704100b3b54 | 337 | memset(result, 0, sizeof(char) * UNIQUE_ID_BUFFER_SIZE + 1); |
AzureIoTClient | 39:e98d5df6dc74 | 338 | |
AzureIoTClient | 56:8704100b3b54 | 339 | if (UniqueId_Generate(result, UNIQUE_ID_BUFFER_SIZE) != UNIQUEID_OK) |
AzureIoTClient | 56:8704100b3b54 | 340 | { |
AzureIoTClient | 56:8704100b3b54 | 341 | LogError("Failed generating an unique tag (UniqueId_Generate failed)"); |
AzureIoTClient | 56:8704100b3b54 | 342 | free(result); |
AzureIoTClient | 56:8704100b3b54 | 343 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 344 | } |
AzureIoTClient | 56:8704100b3b54 | 345 | } |
AzureIoTClient | 39:e98d5df6dc74 | 346 | |
AzureIoTClient | 56:8704100b3b54 | 347 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 348 | } |
AzureIoTClient | 39:e98d5df6dc74 | 349 | |
AzureIoTClient | 39:e98d5df6dc74 | 350 | static char* generate_twin_correlation_id() |
AzureIoTClient | 39:e98d5df6dc74 | 351 | { |
AzureIoTClient | 56:8704100b3b54 | 352 | char* result; |
AzureIoTClient | 56:8704100b3b54 | 353 | char* unique_id; |
AzureIoTClient | 39:e98d5df6dc74 | 354 | |
AzureIoTClient | 56:8704100b3b54 | 355 | if ((unique_id = generate_unique_id()) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 356 | { |
AzureIoTClient | 56:8704100b3b54 | 357 | LogError("Failed generating unique ID for correlation-id"); |
AzureIoTClient | 56:8704100b3b54 | 358 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 359 | } |
AzureIoTClient | 56:8704100b3b54 | 360 | else |
AzureIoTClient | 56:8704100b3b54 | 361 | { |
AzureIoTClient | 56:8704100b3b54 | 362 | if ((result = (char*)malloc(strlen(TWIN_CORRELATION_ID_PROPERTY_FORMAT) + strlen(unique_id) + 1)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 363 | { |
AzureIoTClient | 56:8704100b3b54 | 364 | LogError("Failed allocating correlation-id"); |
AzureIoTClient | 56:8704100b3b54 | 365 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 366 | } |
AzureIoTClient | 56:8704100b3b54 | 367 | else |
AzureIoTClient | 56:8704100b3b54 | 368 | { |
AzureIoTClient | 56:8704100b3b54 | 369 | (void)sprintf(result, TWIN_CORRELATION_ID_PROPERTY_FORMAT, unique_id); |
AzureIoTClient | 56:8704100b3b54 | 370 | } |
AzureIoTClient | 39:e98d5df6dc74 | 371 | |
AzureIoTClient | 56:8704100b3b54 | 372 | free(unique_id); |
AzureIoTClient | 56:8704100b3b54 | 373 | } |
AzureIoTClient | 39:e98d5df6dc74 | 374 | |
AzureIoTClient | 56:8704100b3b54 | 375 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 376 | } |
AzureIoTClient | 39:e98d5df6dc74 | 377 | |
AzureIoTClient | 39:e98d5df6dc74 | 378 | static TWIN_OPERATION_CONTEXT* create_twin_operation_context(TWIN_MESSENGER_INSTANCE* twin_msgr, TWIN_OPERATION_TYPE type) |
AzureIoTClient | 39:e98d5df6dc74 | 379 | { |
AzureIoTClient | 56:8704100b3b54 | 380 | TWIN_OPERATION_CONTEXT* result; |
AzureIoTClient | 39:e98d5df6dc74 | 381 | |
AzureIoTClient | 56:8704100b3b54 | 382 | if ((result = (TWIN_OPERATION_CONTEXT*)malloc(sizeof(TWIN_OPERATION_CONTEXT))) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 383 | { |
AzureIoTClient | 56:8704100b3b54 | 384 | LogError("Failed creating context for %s (%s)", ENUM_TO_STRING(TWIN_OPERATION_TYPE, type), twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 385 | } |
AzureIoTClient | 56:8704100b3b54 | 386 | else |
AzureIoTClient | 56:8704100b3b54 | 387 | { |
AzureIoTClient | 56:8704100b3b54 | 388 | memset(result, 0, sizeof(TWIN_OPERATION_CONTEXT)); |
AzureIoTClient | 39:e98d5df6dc74 | 389 | |
AzureIoTClient | 56:8704100b3b54 | 390 | if ((result->correlation_id = generate_unique_id()) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 391 | { |
AzureIoTClient | 56:8704100b3b54 | 392 | LogError("Failed setting context correlation-id (%s, %s)", ENUM_TO_STRING(TWIN_OPERATION_TYPE, type), twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 393 | free(result); |
AzureIoTClient | 56:8704100b3b54 | 394 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 395 | } |
AzureIoTClient | 56:8704100b3b54 | 396 | else |
AzureIoTClient | 56:8704100b3b54 | 397 | { |
AzureIoTClient | 56:8704100b3b54 | 398 | result->type = type; |
AzureIoTClient | 56:8704100b3b54 | 399 | result->msgr = twin_msgr; |
AzureIoTClient | 56:8704100b3b54 | 400 | } |
AzureIoTClient | 56:8704100b3b54 | 401 | } |
AzureIoTClient | 39:e98d5df6dc74 | 402 | |
AzureIoTClient | 56:8704100b3b54 | 403 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 404 | } |
AzureIoTClient | 39:e98d5df6dc74 | 405 | |
AzureIoTClient | 39:e98d5df6dc74 | 406 | static bool find_twin_operation_by_correlation_id(LIST_ITEM_HANDLE list_item, const void* match_context) |
AzureIoTClient | 39:e98d5df6dc74 | 407 | { |
AzureIoTClient | 56:8704100b3b54 | 408 | TWIN_OPERATION_CONTEXT* twin_op_ctx = (TWIN_OPERATION_CONTEXT*)singlylinkedlist_item_get_value(list_item); |
AzureIoTClient | 56:8704100b3b54 | 409 | return (strcmp(twin_op_ctx->correlation_id, (const char*)match_context) == 0); |
AzureIoTClient | 39:e98d5df6dc74 | 410 | } |
AzureIoTClient | 39:e98d5df6dc74 | 411 | |
AzureIoTClient | 39:e98d5df6dc74 | 412 | static bool find_twin_operation_by_type(LIST_ITEM_HANDLE list_item, const void* match_context) |
AzureIoTClient | 39:e98d5df6dc74 | 413 | { |
AzureIoTClient | 56:8704100b3b54 | 414 | TWIN_OPERATION_CONTEXT* twin_op_ctx = (TWIN_OPERATION_CONTEXT*)singlylinkedlist_item_get_value(list_item); |
AzureIoTClient | 56:8704100b3b54 | 415 | return (twin_op_ctx->type == *(TWIN_OPERATION_TYPE*)match_context); |
AzureIoTClient | 39:e98d5df6dc74 | 416 | } |
AzureIoTClient | 39:e98d5df6dc74 | 417 | |
AzureIoTClient | 39:e98d5df6dc74 | 418 | static void destroy_twin_operation_context(TWIN_OPERATION_CONTEXT* op_ctx) |
AzureIoTClient | 39:e98d5df6dc74 | 419 | { |
AzureIoTClient | 56:8704100b3b54 | 420 | free(op_ctx->correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 421 | free(op_ctx); |
AzureIoTClient | 39:e98d5df6dc74 | 422 | } |
AzureIoTClient | 39:e98d5df6dc74 | 423 | |
AzureIoTClient | 39:e98d5df6dc74 | 424 | static int add_twin_operation_context_to_queue(TWIN_OPERATION_CONTEXT* twin_op_ctx) |
AzureIoTClient | 39:e98d5df6dc74 | 425 | { |
AzureIoTClient | 56:8704100b3b54 | 426 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 427 | |
AzureIoTClient | 56:8704100b3b54 | 428 | if (singlylinkedlist_add(twin_op_ctx->msgr->operations, (const void*)twin_op_ctx) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 429 | { |
AzureIoTClient | 56:8704100b3b54 | 430 | LogError("Failed adding TWIN operation context to queue (%s, %s)", ENUM_TO_STRING(TWIN_OPERATION_TYPE, twin_op_ctx->type), twin_op_ctx->correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 431 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 432 | } |
AzureIoTClient | 56:8704100b3b54 | 433 | else |
AzureIoTClient | 56:8704100b3b54 | 434 | { |
AzureIoTClient | 56:8704100b3b54 | 435 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 436 | } |
AzureIoTClient | 39:e98d5df6dc74 | 437 | |
AzureIoTClient | 56:8704100b3b54 | 438 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 439 | } |
AzureIoTClient | 39:e98d5df6dc74 | 440 | |
AzureIoTClient | 39:e98d5df6dc74 | 441 | static int remove_twin_operation_context_from_queue(TWIN_OPERATION_CONTEXT* twin_op_ctx) |
AzureIoTClient | 39:e98d5df6dc74 | 442 | { |
AzureIoTClient | 56:8704100b3b54 | 443 | int result; |
AzureIoTClient | 56:8704100b3b54 | 444 | LIST_ITEM_HANDLE list_item; |
AzureIoTClient | 39:e98d5df6dc74 | 445 | |
AzureIoTClient | 56:8704100b3b54 | 446 | if ((list_item = singlylinkedlist_find(twin_op_ctx->msgr->operations, find_twin_operation_by_correlation_id, (const void*)twin_op_ctx->correlation_id)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 447 | { |
AzureIoTClient | 56:8704100b3b54 | 448 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 449 | } |
AzureIoTClient | 56:8704100b3b54 | 450 | else if (singlylinkedlist_remove(twin_op_ctx->msgr->operations, list_item) != 0) |
AzureIoTClient | 56:8704100b3b54 | 451 | { |
AzureIoTClient | 56:8704100b3b54 | 452 | LogError("Failed removing TWIN operation context from queue (%s, %s, %s)", |
AzureIoTClient | 56:8704100b3b54 | 453 | twin_op_ctx->msgr->device_id, ENUM_TO_STRING(TWIN_OPERATION_TYPE, twin_op_ctx->type), twin_op_ctx->correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 454 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 455 | } |
AzureIoTClient | 56:8704100b3b54 | 456 | else |
AzureIoTClient | 56:8704100b3b54 | 457 | { |
AzureIoTClient | 56:8704100b3b54 | 458 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 459 | } |
AzureIoTClient | 39:e98d5df6dc74 | 460 | |
AzureIoTClient | 56:8704100b3b54 | 461 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 462 | } |
AzureIoTClient | 39:e98d5df6dc74 | 463 | |
AzureIoTClient | 39:e98d5df6dc74 | 464 | |
AzureIoTClient | 39:e98d5df6dc74 | 465 | //---------- TWIN <-> AMQP Translation Functions ----------// |
AzureIoTClient | 39:e98d5df6dc74 | 466 | |
AzureIoTClient | 39:e98d5df6dc74 | 467 | static int parse_incoming_twin_message(MESSAGE_HANDLE message, |
AzureIoTClient | 56:8704100b3b54 | 468 | char** correlation_id, |
AzureIoTClient | 56:8704100b3b54 | 469 | bool* has_version, int64_t* version, |
AzureIoTClient | 56:8704100b3b54 | 470 | bool* has_status_code, int* status_code, |
AzureIoTClient | 56:8704100b3b54 | 471 | bool* has_twin_report, BINARY_DATA* twin_report) |
AzureIoTClient | 39:e98d5df6dc74 | 472 | { |
AzureIoTClient | 56:8704100b3b54 | 473 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 474 | |
AzureIoTClient | 56:8704100b3b54 | 475 | if (get_message_correlation_id(message, correlation_id) != 0) |
AzureIoTClient | 56:8704100b3b54 | 476 | { |
AzureIoTClient | 56:8704100b3b54 | 477 | LogError("Failed retrieving correlation ID from received TWIN message."); |
AzureIoTClient | 56:8704100b3b54 | 478 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 479 | } |
AzureIoTClient | 56:8704100b3b54 | 480 | else |
AzureIoTClient | 56:8704100b3b54 | 481 | { |
AzureIoTClient | 56:8704100b3b54 | 482 | annotations message_annotations; |
AzureIoTClient | 39:e98d5df6dc74 | 483 | |
AzureIoTClient | 56:8704100b3b54 | 484 | if (message_get_message_annotations(message, &message_annotations) != 0) |
AzureIoTClient | 56:8704100b3b54 | 485 | { |
AzureIoTClient | 56:8704100b3b54 | 486 | LogError("Failed getting TWIN message annotations"); |
AzureIoTClient | 56:8704100b3b54 | 487 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 488 | } |
AzureIoTClient | 56:8704100b3b54 | 489 | else |
AzureIoTClient | 56:8704100b3b54 | 490 | { |
AzureIoTClient | 56:8704100b3b54 | 491 | result = RESULT_OK; |
AzureIoTClient | 39:e98d5df6dc74 | 492 | |
AzureIoTClient | 56:8704100b3b54 | 493 | if (message_annotations == NULL) |
AzureIoTClient | 56:8704100b3b54 | 494 | { |
AzureIoTClient | 56:8704100b3b54 | 495 | *has_version = false; |
AzureIoTClient | 56:8704100b3b54 | 496 | *has_status_code = false; |
AzureIoTClient | 56:8704100b3b54 | 497 | } |
AzureIoTClient | 56:8704100b3b54 | 498 | else |
AzureIoTClient | 56:8704100b3b54 | 499 | { |
AzureIoTClient | 56:8704100b3b54 | 500 | uint32_t pair_count; |
AzureIoTClient | 56:8704100b3b54 | 501 | if (amqpvalue_get_map_pair_count((AMQP_VALUE)message_annotations, &pair_count) != 0) |
AzureIoTClient | 56:8704100b3b54 | 502 | { |
AzureIoTClient | 56:8704100b3b54 | 503 | LogError("Failed getting TWIN message annotations count"); |
AzureIoTClient | 56:8704100b3b54 | 504 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 505 | } |
AzureIoTClient | 56:8704100b3b54 | 506 | else |
AzureIoTClient | 56:8704100b3b54 | 507 | { |
AzureIoTClient | 56:8704100b3b54 | 508 | uint32_t i; |
AzureIoTClient | 39:e98d5df6dc74 | 509 | |
AzureIoTClient | 56:8704100b3b54 | 510 | *has_status_code = false; |
AzureIoTClient | 56:8704100b3b54 | 511 | *has_version = false; |
AzureIoTClient | 39:e98d5df6dc74 | 512 | |
AzureIoTClient | 56:8704100b3b54 | 513 | for (i = 0; i < pair_count; i++) |
AzureIoTClient | 56:8704100b3b54 | 514 | { |
AzureIoTClient | 56:8704100b3b54 | 515 | AMQP_VALUE amqp_map_key; |
AzureIoTClient | 56:8704100b3b54 | 516 | AMQP_VALUE amqp_map_value; |
AzureIoTClient | 39:e98d5df6dc74 | 517 | |
AzureIoTClient | 56:8704100b3b54 | 518 | if (amqpvalue_get_map_key_value_pair((AMQP_VALUE)message_annotations, i, &amqp_map_key, &amqp_map_value) != 0) |
AzureIoTClient | 56:8704100b3b54 | 519 | { |
AzureIoTClient | 56:8704100b3b54 | 520 | LogError("Failed getting AMQP map key/value pair (%d)", i); |
AzureIoTClient | 56:8704100b3b54 | 521 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 522 | } |
AzureIoTClient | 56:8704100b3b54 | 523 | else |
AzureIoTClient | 56:8704100b3b54 | 524 | { |
AzureIoTClient | 56:8704100b3b54 | 525 | const char* map_key_name; |
AzureIoTClient | 39:e98d5df6dc74 | 526 | |
AzureIoTClient | 56:8704100b3b54 | 527 | if (amqpvalue_get_symbol(amqp_map_key, &map_key_name) != 0) |
AzureIoTClient | 56:8704100b3b54 | 528 | { |
AzureIoTClient | 56:8704100b3b54 | 529 | LogError("Failed getting AMQP value symbol"); |
AzureIoTClient | 56:8704100b3b54 | 530 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 531 | break; |
AzureIoTClient | 56:8704100b3b54 | 532 | } |
AzureIoTClient | 56:8704100b3b54 | 533 | else |
AzureIoTClient | 56:8704100b3b54 | 534 | { |
AzureIoTClient | 56:8704100b3b54 | 535 | if (strcmp(TWIN_MESSAGE_PROPERTY_STATUS, map_key_name) == 0) |
AzureIoTClient | 56:8704100b3b54 | 536 | { |
AzureIoTClient | 56:8704100b3b54 | 537 | if (amqpvalue_get_type(amqp_map_value) != AMQP_TYPE_INT) |
AzureIoTClient | 56:8704100b3b54 | 538 | { |
AzureIoTClient | 56:8704100b3b54 | 539 | LogError("TWIN message status property expected to be INT"); |
AzureIoTClient | 56:8704100b3b54 | 540 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 541 | break; |
AzureIoTClient | 56:8704100b3b54 | 542 | } |
AzureIoTClient | 56:8704100b3b54 | 543 | else if (amqpvalue_get_int(amqp_map_value, status_code) != 0) |
AzureIoTClient | 56:8704100b3b54 | 544 | { |
AzureIoTClient | 56:8704100b3b54 | 545 | LogError("Failed getting TWIN message status code value"); |
AzureIoTClient | 56:8704100b3b54 | 546 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 547 | break; |
AzureIoTClient | 56:8704100b3b54 | 548 | } |
AzureIoTClient | 56:8704100b3b54 | 549 | else |
AzureIoTClient | 56:8704100b3b54 | 550 | { |
AzureIoTClient | 56:8704100b3b54 | 551 | *has_status_code = true; |
AzureIoTClient | 56:8704100b3b54 | 552 | } |
AzureIoTClient | 56:8704100b3b54 | 553 | } |
AzureIoTClient | 56:8704100b3b54 | 554 | else if (strcmp(TWIN_MESSAGE_PROPERTY_VERSION, map_key_name) == 0) |
AzureIoTClient | 56:8704100b3b54 | 555 | { |
AzureIoTClient | 56:8704100b3b54 | 556 | if (amqpvalue_get_type(amqp_map_value) != AMQP_TYPE_LONG) |
AzureIoTClient | 56:8704100b3b54 | 557 | { |
AzureIoTClient | 56:8704100b3b54 | 558 | LogError("TWIN message version property expected to be LONG"); |
AzureIoTClient | 56:8704100b3b54 | 559 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 560 | break; |
AzureIoTClient | 56:8704100b3b54 | 561 | } |
AzureIoTClient | 56:8704100b3b54 | 562 | else if (amqpvalue_get_long(amqp_map_value, version) != 0) |
AzureIoTClient | 56:8704100b3b54 | 563 | { |
AzureIoTClient | 56:8704100b3b54 | 564 | LogError("Failed getting TWIN message version value"); |
AzureIoTClient | 56:8704100b3b54 | 565 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 566 | break; |
AzureIoTClient | 56:8704100b3b54 | 567 | } |
AzureIoTClient | 56:8704100b3b54 | 568 | else |
AzureIoTClient | 56:8704100b3b54 | 569 | { |
AzureIoTClient | 56:8704100b3b54 | 570 | *has_version = true; |
AzureIoTClient | 56:8704100b3b54 | 571 | } |
AzureIoTClient | 56:8704100b3b54 | 572 | } |
AzureIoTClient | 39:e98d5df6dc74 | 573 | |
AzureIoTClient | 56:8704100b3b54 | 574 | amqpvalue_destroy(amqp_map_value); |
AzureIoTClient | 56:8704100b3b54 | 575 | } |
AzureIoTClient | 39:e98d5df6dc74 | 576 | |
AzureIoTClient | 56:8704100b3b54 | 577 | amqpvalue_destroy(amqp_map_key); |
AzureIoTClient | 56:8704100b3b54 | 578 | } |
AzureIoTClient | 56:8704100b3b54 | 579 | } |
AzureIoTClient | 56:8704100b3b54 | 580 | } |
AzureIoTClient | 39:e98d5df6dc74 | 581 | |
AzureIoTClient | 56:8704100b3b54 | 582 | amqpvalue_destroy(message_annotations); |
AzureIoTClient | 56:8704100b3b54 | 583 | } |
AzureIoTClient | 39:e98d5df6dc74 | 584 | |
AzureIoTClient | 56:8704100b3b54 | 585 | if (result == RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 586 | { |
AzureIoTClient | 56:8704100b3b54 | 587 | MESSAGE_BODY_TYPE body_type; |
AzureIoTClient | 39:e98d5df6dc74 | 588 | |
AzureIoTClient | 56:8704100b3b54 | 589 | if (message_get_body_type(message, &body_type) != 0) |
AzureIoTClient | 56:8704100b3b54 | 590 | { |
AzureIoTClient | 56:8704100b3b54 | 591 | LogError("Failed getting TWIN message body type"); |
AzureIoTClient | 56:8704100b3b54 | 592 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 593 | } |
AzureIoTClient | 56:8704100b3b54 | 594 | else if (body_type == MESSAGE_BODY_TYPE_DATA) |
AzureIoTClient | 56:8704100b3b54 | 595 | { |
AzureIoTClient | 56:8704100b3b54 | 596 | size_t body_count; |
AzureIoTClient | 39:e98d5df6dc74 | 597 | |
AzureIoTClient | 56:8704100b3b54 | 598 | if (message_get_body_amqp_data_count(message, &body_count) != 0) |
AzureIoTClient | 56:8704100b3b54 | 599 | { |
AzureIoTClient | 56:8704100b3b54 | 600 | LogError("Failed getting TWIN message body count"); |
AzureIoTClient | 56:8704100b3b54 | 601 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 602 | } |
AzureIoTClient | 56:8704100b3b54 | 603 | else if (body_count != 1) |
AzureIoTClient | 56:8704100b3b54 | 604 | { |
AzureIoTClient | 56:8704100b3b54 | 605 | LogError("Unexpected number of TWIN message bodies (%d)", body_count); |
AzureIoTClient | 56:8704100b3b54 | 606 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 607 | } |
AzureIoTClient | 56:8704100b3b54 | 608 | else if (message_get_body_amqp_data_in_place(message, 0, twin_report) != 0) |
AzureIoTClient | 56:8704100b3b54 | 609 | { |
AzureIoTClient | 56:8704100b3b54 | 610 | LogError("Failed getting TWIN message body"); |
AzureIoTClient | 56:8704100b3b54 | 611 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 612 | } |
AzureIoTClient | 56:8704100b3b54 | 613 | else |
AzureIoTClient | 56:8704100b3b54 | 614 | { |
AzureIoTClient | 56:8704100b3b54 | 615 | *has_twin_report = true; |
AzureIoTClient | 56:8704100b3b54 | 616 | } |
AzureIoTClient | 56:8704100b3b54 | 617 | } |
AzureIoTClient | 56:8704100b3b54 | 618 | else if (body_type != MESSAGE_BODY_TYPE_NONE) |
AzureIoTClient | 56:8704100b3b54 | 619 | { |
AzureIoTClient | 56:8704100b3b54 | 620 | LogError("Unexpected TWIN message body %d", body_type); |
AzureIoTClient | 56:8704100b3b54 | 621 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 622 | } |
AzureIoTClient | 56:8704100b3b54 | 623 | else |
AzureIoTClient | 56:8704100b3b54 | 624 | { |
AzureIoTClient | 56:8704100b3b54 | 625 | *has_twin_report = false; |
AzureIoTClient | 56:8704100b3b54 | 626 | } |
AzureIoTClient | 56:8704100b3b54 | 627 | } |
AzureIoTClient | 56:8704100b3b54 | 628 | } |
AzureIoTClient | 39:e98d5df6dc74 | 629 | |
AzureIoTClient | 56:8704100b3b54 | 630 | if (result != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 631 | { |
AzureIoTClient | 56:8704100b3b54 | 632 | free(*correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 633 | *correlation_id = NULL; |
AzureIoTClient | 56:8704100b3b54 | 634 | } |
AzureIoTClient | 56:8704100b3b54 | 635 | } |
AzureIoTClient | 39:e98d5df6dc74 | 636 | |
AzureIoTClient | 56:8704100b3b54 | 637 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 638 | } |
AzureIoTClient | 39:e98d5df6dc74 | 639 | |
AzureIoTClient | 39:e98d5df6dc74 | 640 | static void destroy_link_attach_properties(MAP_HANDLE properties) |
AzureIoTClient | 39:e98d5df6dc74 | 641 | { |
AzureIoTClient | 56:8704100b3b54 | 642 | Map_Destroy(properties); |
AzureIoTClient | 39:e98d5df6dc74 | 643 | } |
AzureIoTClient | 39:e98d5df6dc74 | 644 | |
AzureIoTClient | 39:e98d5df6dc74 | 645 | static MAP_HANDLE create_link_attach_properties(TWIN_MESSENGER_INSTANCE* twin_msgr) |
AzureIoTClient | 39:e98d5df6dc74 | 646 | { |
AzureIoTClient | 56:8704100b3b54 | 647 | MAP_HANDLE result; |
AzureIoTClient | 39:e98d5df6dc74 | 648 | |
AzureIoTClient | 56:8704100b3b54 | 649 | if ((result = Map_Create(NULL)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 650 | { |
AzureIoTClient | 56:8704100b3b54 | 651 | LogError("Failed creating map for AMQP link properties (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 652 | } |
AzureIoTClient | 56:8704100b3b54 | 653 | else |
AzureIoTClient | 56:8704100b3b54 | 654 | { |
AzureIoTClient | 56:8704100b3b54 | 655 | char* correlation_id; |
AzureIoTClient | 39:e98d5df6dc74 | 656 | |
AzureIoTClient | 56:8704100b3b54 | 657 | if ((correlation_id = generate_twin_correlation_id()) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 658 | { |
AzureIoTClient | 56:8704100b3b54 | 659 | LogError("Failed adding AMQP link property "); |
AzureIoTClient | 56:8704100b3b54 | 660 | destroy_link_attach_properties(result); |
AzureIoTClient | 56:8704100b3b54 | 661 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 662 | } |
AzureIoTClient | 56:8704100b3b54 | 663 | else |
AzureIoTClient | 56:8704100b3b54 | 664 | { |
AzureIoTClient | 56:8704100b3b54 | 665 | if (Map_Add(result, CLIENT_VERSION_PROPERTY_NAME, twin_msgr->client_version) != MAP_OK) |
AzureIoTClient | 56:8704100b3b54 | 666 | { |
AzureIoTClient | 56:8704100b3b54 | 667 | LogError("Failed adding AMQP link property 'client version' (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 668 | destroy_link_attach_properties(result); |
AzureIoTClient | 56:8704100b3b54 | 669 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 670 | } |
AzureIoTClient | 56:8704100b3b54 | 671 | else if (Map_Add(result, TWIN_CORRELATION_ID_PROPERTY_NAME, correlation_id) != MAP_OK) |
AzureIoTClient | 56:8704100b3b54 | 672 | { |
AzureIoTClient | 56:8704100b3b54 | 673 | LogError("Failed adding AMQP link property 'correlation-id' (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 674 | destroy_link_attach_properties(result); |
AzureIoTClient | 56:8704100b3b54 | 675 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 676 | } |
AzureIoTClient | 56:8704100b3b54 | 677 | else if (Map_Add(result, TWIN_API_VERSION_PROPERTY_NAME, TWIN_API_VERSION_NUMBER) != MAP_OK) |
AzureIoTClient | 56:8704100b3b54 | 678 | { |
AzureIoTClient | 56:8704100b3b54 | 679 | LogError("Failed adding AMQP link property 'api-version' (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 680 | destroy_link_attach_properties(result); |
AzureIoTClient | 56:8704100b3b54 | 681 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 682 | } |
AzureIoTClient | 39:e98d5df6dc74 | 683 | |
AzureIoTClient | 56:8704100b3b54 | 684 | free(correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 685 | } |
AzureIoTClient | 56:8704100b3b54 | 686 | } |
AzureIoTClient | 39:e98d5df6dc74 | 687 | |
AzureIoTClient | 56:8704100b3b54 | 688 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 689 | } |
AzureIoTClient | 39:e98d5df6dc74 | 690 | |
AzureIoTClient | 39:e98d5df6dc74 | 691 | static const char* get_twin_operation_name(TWIN_OPERATION_TYPE op_type) |
AzureIoTClient | 39:e98d5df6dc74 | 692 | { |
AzureIoTClient | 56:8704100b3b54 | 693 | const char* result; |
AzureIoTClient | 39:e98d5df6dc74 | 694 | |
AzureIoTClient | 56:8704100b3b54 | 695 | switch (op_type) |
AzureIoTClient | 56:8704100b3b54 | 696 | { |
AzureIoTClient | 56:8704100b3b54 | 697 | default: |
AzureIoTClient | 56:8704100b3b54 | 698 | LogError("Unrecognized TWIN operation (%s)", ENUM_TO_STRING(TWIN_OPERATION_TYPE, op_type)); |
AzureIoTClient | 56:8704100b3b54 | 699 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 700 | break; |
AzureIoTClient | 56:8704100b3b54 | 701 | case TWIN_OPERATION_TYPE_PATCH: |
AzureIoTClient | 56:8704100b3b54 | 702 | result = TWIN_OPERATION_PATCH; |
AzureIoTClient | 56:8704100b3b54 | 703 | break; |
AzureIoTClient | 56:8704100b3b54 | 704 | case TWIN_OPERATION_TYPE_GET: |
AzureIoTClient | 56:8704100b3b54 | 705 | result = TWIN_OPERATION_GET; |
AzureIoTClient | 56:8704100b3b54 | 706 | break; |
AzureIoTClient | 56:8704100b3b54 | 707 | case TWIN_OPERATION_TYPE_PUT: |
AzureIoTClient | 56:8704100b3b54 | 708 | result = TWIN_OPERATION_PUT; |
AzureIoTClient | 56:8704100b3b54 | 709 | break; |
AzureIoTClient | 56:8704100b3b54 | 710 | case TWIN_OPERATION_TYPE_DELETE: |
AzureIoTClient | 56:8704100b3b54 | 711 | result = TWIN_OPERATION_DELETE; |
AzureIoTClient | 56:8704100b3b54 | 712 | break; |
AzureIoTClient | 56:8704100b3b54 | 713 | } |
AzureIoTClient | 39:e98d5df6dc74 | 714 | |
AzureIoTClient | 56:8704100b3b54 | 715 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 716 | } |
AzureIoTClient | 39:e98d5df6dc74 | 717 | |
AzureIoTClient | 39:e98d5df6dc74 | 718 | static MESSAGE_HANDLE create_amqp_message_for_twin_operation(TWIN_OPERATION_TYPE op_type, char* correlation_id, CONSTBUFFER_HANDLE data) |
AzureIoTClient | 39:e98d5df6dc74 | 719 | { |
AzureIoTClient | 56:8704100b3b54 | 720 | MESSAGE_HANDLE result; |
AzureIoTClient | 56:8704100b3b54 | 721 | const char* twin_op_name; |
AzureIoTClient | 39:e98d5df6dc74 | 722 | |
AzureIoTClient | 56:8704100b3b54 | 723 | if ((twin_op_name = get_twin_operation_name(op_type))== NULL) |
AzureIoTClient | 56:8704100b3b54 | 724 | { |
AzureIoTClient | 56:8704100b3b54 | 725 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 726 | } |
AzureIoTClient | 56:8704100b3b54 | 727 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_063: [An `amqp_message` (MESSAGE_HANDLE) shall be created using message_create()] |
AzureIoTClient | 56:8704100b3b54 | 728 | else if ((result = message_create()) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 729 | { |
AzureIoTClient | 56:8704100b3b54 | 730 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_064: [If message_create() fails, message_create_for_twin_operation shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 731 | LogError("Failed creating AMQP message (%s)", twin_op_name); |
AzureIoTClient | 56:8704100b3b54 | 732 | } |
AzureIoTClient | 56:8704100b3b54 | 733 | else |
AzureIoTClient | 56:8704100b3b54 | 734 | { |
AzureIoTClient | 56:8704100b3b54 | 735 | AMQP_VALUE msg_annotations_map; |
AzureIoTClient | 39:e98d5df6dc74 | 736 | |
AzureIoTClient | 56:8704100b3b54 | 737 | if ((msg_annotations_map = amqpvalue_create_map()) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 738 | { |
AzureIoTClient | 56:8704100b3b54 | 739 | LogError("Failed creating map for message annotations"); |
AzureIoTClient | 56:8704100b3b54 | 740 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_072: [If any errors occur, message_create_for_twin_operation shall release all memory it has allocated] |
AzureIoTClient | 56:8704100b3b54 | 741 | message_destroy(result); |
AzureIoTClient | 56:8704100b3b54 | 742 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 743 | } |
AzureIoTClient | 56:8704100b3b54 | 744 | else |
AzureIoTClient | 56:8704100b3b54 | 745 | { |
AzureIoTClient | 56:8704100b3b54 | 746 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_065: [`operation=<op_type>` (GET/PATCH/PUT/DELETE) must be added to the `amqp_message` annotations] |
AzureIoTClient | 56:8704100b3b54 | 747 | if (add_map_item(msg_annotations_map, TWIN_MESSAGE_PROPERTY_OPERATION, twin_op_name) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 748 | { |
AzureIoTClient | 56:8704100b3b54 | 749 | LogError("Failed adding operation to AMQP message annotations (%s)", twin_op_name); |
AzureIoTClient | 56:8704100b3b54 | 750 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_072: [If any errors occur, message_create_for_twin_operation shall release all memory it has allocated] |
AzureIoTClient | 56:8704100b3b54 | 751 | message_destroy(result); |
AzureIoTClient | 56:8704100b3b54 | 752 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 753 | } |
AzureIoTClient | 56:8704100b3b54 | 754 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_066: [If `op_type` is PATCH, `resource=/properties/reported` must be added to the `amqp_message` annotations] |
AzureIoTClient | 56:8704100b3b54 | 755 | else if ((op_type == TWIN_OPERATION_TYPE_PATCH) && |
AzureIoTClient | 56:8704100b3b54 | 756 | add_map_item(msg_annotations_map, TWIN_MESSAGE_PROPERTY_RESOURCE, TWIN_RESOURCE_REPORTED) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 757 | { |
AzureIoTClient | 56:8704100b3b54 | 758 | LogError("Failed adding resource to AMQP message annotations (%s)", twin_op_name); |
AzureIoTClient | 56:8704100b3b54 | 759 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_072: [If any errors occur, message_create_for_twin_operation shall release all memory it has allocated] |
AzureIoTClient | 56:8704100b3b54 | 760 | message_destroy(result); |
AzureIoTClient | 56:8704100b3b54 | 761 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 762 | } |
AzureIoTClient | 56:8704100b3b54 | 763 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_067: [If `op_type` is PUT or DELETE, `resource=/notifications/twin/properties/desired` must be added to the `amqp_message` annotations] |
AzureIoTClient | 56:8704100b3b54 | 764 | else if ((op_type == TWIN_OPERATION_TYPE_PUT || op_type == TWIN_OPERATION_TYPE_DELETE) && |
AzureIoTClient | 56:8704100b3b54 | 765 | add_map_item(msg_annotations_map, TWIN_MESSAGE_PROPERTY_RESOURCE, TWIN_RESOURCE_DESIRED) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 766 | { |
AzureIoTClient | 56:8704100b3b54 | 767 | LogError("Failed adding resource to AMQP message annotations (%s)", twin_op_name); |
AzureIoTClient | 56:8704100b3b54 | 768 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_072: [If any errors occur, message_create_for_twin_operation shall release all memory it has allocated] |
AzureIoTClient | 56:8704100b3b54 | 769 | message_destroy(result); |
AzureIoTClient | 56:8704100b3b54 | 770 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 771 | } |
AzureIoTClient | 56:8704100b3b54 | 772 | else if (add_amqp_message_annotation(result, msg_annotations_map) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 773 | { |
AzureIoTClient | 56:8704100b3b54 | 774 | LogError("Failed adding annotations to AMQP message (%s)", twin_op_name); |
AzureIoTClient | 56:8704100b3b54 | 775 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_072: [If any errors occur, message_create_for_twin_operation shall release all memory it has allocated] |
AzureIoTClient | 56:8704100b3b54 | 776 | message_destroy(result); |
AzureIoTClient | 56:8704100b3b54 | 777 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 778 | } |
AzureIoTClient | 56:8704100b3b54 | 779 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_068: [The `correlation-id` property of `amqp_message` shall be set with an UUID string] |
AzureIoTClient | 56:8704100b3b54 | 780 | else if (set_message_correlation_id(result, correlation_id) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 781 | { |
AzureIoTClient | 56:8704100b3b54 | 782 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_069: [If setting `correlation-id` fails, message_create_for_twin_operation shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 783 | LogError("Failed AMQP message correlation-id (%s)", twin_op_name); |
AzureIoTClient | 56:8704100b3b54 | 784 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_072: [If any errors occur, message_create_for_twin_operation shall release all memory it has allocated] |
AzureIoTClient | 56:8704100b3b54 | 785 | message_destroy(result); |
AzureIoTClient | 56:8704100b3b54 | 786 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 787 | } |
AzureIoTClient | 56:8704100b3b54 | 788 | else |
AzureIoTClient | 56:8704100b3b54 | 789 | { |
AzureIoTClient | 56:8704100b3b54 | 790 | BINARY_DATA binary_data; |
AzureIoTClient | 39:e98d5df6dc74 | 791 | |
AzureIoTClient | 56:8704100b3b54 | 792 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_070: [If `data` is not NULL, it shall be added to `amqp_message` using message_add_body_amqp_data()] |
AzureIoTClient | 56:8704100b3b54 | 793 | if (data != NULL) |
AzureIoTClient | 56:8704100b3b54 | 794 | { |
AzureIoTClient | 56:8704100b3b54 | 795 | const CONSTBUFFER* data_buffer; |
AzureIoTClient | 56:8704100b3b54 | 796 | data_buffer = CONSTBUFFER_GetContent(data); |
AzureIoTClient | 56:8704100b3b54 | 797 | binary_data.bytes = data_buffer->buffer; |
AzureIoTClient | 56:8704100b3b54 | 798 | binary_data.length = data_buffer->size; |
AzureIoTClient | 56:8704100b3b54 | 799 | } |
AzureIoTClient | 56:8704100b3b54 | 800 | else |
AzureIoTClient | 56:8704100b3b54 | 801 | { |
AzureIoTClient | 56:8704100b3b54 | 802 | binary_data.bytes = EMPTY_TWIN_BODY_DATA; |
AzureIoTClient | 56:8704100b3b54 | 803 | binary_data.length = EMPTY_TWIN_BODY_SIZE; |
AzureIoTClient | 56:8704100b3b54 | 804 | } |
AzureIoTClient | 39:e98d5df6dc74 | 805 | |
AzureIoTClient | 56:8704100b3b54 | 806 | if (message_add_body_amqp_data(result, binary_data) != 0) |
AzureIoTClient | 56:8704100b3b54 | 807 | { |
AzureIoTClient | 56:8704100b3b54 | 808 | LogError("Failed adding twin patch data to AMQP message body"); |
AzureIoTClient | 56:8704100b3b54 | 809 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_072: [If any errors occur, message_create_for_twin_operation shall release all memory it has allocated] |
AzureIoTClient | 56:8704100b3b54 | 810 | message_destroy(result); |
AzureIoTClient | 56:8704100b3b54 | 811 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_071: [If message_add_body_amqp_data() fails, message_create_for_twin_operation shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 812 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 813 | } |
AzureIoTClient | 56:8704100b3b54 | 814 | } |
AzureIoTClient | 39:e98d5df6dc74 | 815 | |
AzureIoTClient | 56:8704100b3b54 | 816 | amqpvalue_destroy(msg_annotations_map); |
AzureIoTClient | 56:8704100b3b54 | 817 | } |
AzureIoTClient | 56:8704100b3b54 | 818 | } |
AzureIoTClient | 39:e98d5df6dc74 | 819 | |
AzureIoTClient | 56:8704100b3b54 | 820 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_073: [If no errors occur, message_create_for_twin_operation shall return `amqp_message`] |
AzureIoTClient | 56:8704100b3b54 | 821 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 822 | } |
AzureIoTClient | 39:e98d5df6dc74 | 823 | |
AzureIoTClient | 39:e98d5df6dc74 | 824 | static TWIN_REPORT_STATE_RESULT get_twin_messenger_result_from(AMQP_MESSENGER_SEND_RESULT amqp_send_result) |
AzureIoTClient | 39:e98d5df6dc74 | 825 | { |
AzureIoTClient | 56:8704100b3b54 | 826 | TWIN_REPORT_STATE_RESULT result; |
AzureIoTClient | 39:e98d5df6dc74 | 827 | |
AzureIoTClient | 56:8704100b3b54 | 828 | switch (amqp_send_result) |
AzureIoTClient | 56:8704100b3b54 | 829 | { |
AzureIoTClient | 56:8704100b3b54 | 830 | case AMQP_MESSENGER_SEND_RESULT_SUCCESS: |
AzureIoTClient | 56:8704100b3b54 | 831 | result = TWIN_REPORT_STATE_RESULT_SUCCESS; |
AzureIoTClient | 56:8704100b3b54 | 832 | break; |
AzureIoTClient | 56:8704100b3b54 | 833 | case AMQP_MESSENGER_SEND_RESULT_CANCELLED: |
AzureIoTClient | 56:8704100b3b54 | 834 | result = TWIN_REPORT_STATE_RESULT_CANCELLED; |
AzureIoTClient | 56:8704100b3b54 | 835 | break; |
AzureIoTClient | 56:8704100b3b54 | 836 | case AMQP_MESSENGER_SEND_RESULT_ERROR: |
AzureIoTClient | 56:8704100b3b54 | 837 | result = TWIN_REPORT_STATE_RESULT_ERROR; |
AzureIoTClient | 56:8704100b3b54 | 838 | break; |
AzureIoTClient | 56:8704100b3b54 | 839 | default: |
AzureIoTClient | 56:8704100b3b54 | 840 | LogError("Unrecognized enum value %s", ENUM_TO_STRING(AMQP_MESSENGER_SEND_RESULT, amqp_send_result)); |
AzureIoTClient | 56:8704100b3b54 | 841 | result = TWIN_REPORT_STATE_RESULT_ERROR; |
AzureIoTClient | 56:8704100b3b54 | 842 | break; |
AzureIoTClient | 56:8704100b3b54 | 843 | }; |
AzureIoTClient | 39:e98d5df6dc74 | 844 | |
AzureIoTClient | 56:8704100b3b54 | 845 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 846 | } |
AzureIoTClient | 39:e98d5df6dc74 | 847 | |
AzureIoTClient | 39:e98d5df6dc74 | 848 | static TWIN_REPORT_STATE_REASON get_twin_messenger_reason_from(AMQP_MESSENGER_REASON amqp_reason) |
AzureIoTClient | 39:e98d5df6dc74 | 849 | { |
AzureIoTClient | 56:8704100b3b54 | 850 | TWIN_REPORT_STATE_REASON result; |
AzureIoTClient | 39:e98d5df6dc74 | 851 | |
AzureIoTClient | 56:8704100b3b54 | 852 | switch (amqp_reason) |
AzureIoTClient | 56:8704100b3b54 | 853 | { |
AzureIoTClient | 56:8704100b3b54 | 854 | case AMQP_MESSENGER_REASON_NONE: |
AzureIoTClient | 56:8704100b3b54 | 855 | result = TWIN_REPORT_STATE_REASON_NONE; |
AzureIoTClient | 56:8704100b3b54 | 856 | break; |
AzureIoTClient | 56:8704100b3b54 | 857 | case AMQP_MESSENGER_REASON_FAIL_SENDING: |
AzureIoTClient | 56:8704100b3b54 | 858 | result = TWIN_REPORT_STATE_REASON_FAIL_SENDING; |
AzureIoTClient | 56:8704100b3b54 | 859 | break; |
AzureIoTClient | 56:8704100b3b54 | 860 | case AMQP_MESSENGER_REASON_TIMEOUT: |
AzureIoTClient | 56:8704100b3b54 | 861 | result = TWIN_REPORT_STATE_REASON_TIMEOUT; |
AzureIoTClient | 56:8704100b3b54 | 862 | break; |
AzureIoTClient | 56:8704100b3b54 | 863 | case AMQP_MESSENGER_REASON_MESSENGER_DESTROYED: |
AzureIoTClient | 56:8704100b3b54 | 864 | result = TWIN_REPORT_STATE_REASON_MESSENGER_DESTROYED; |
AzureIoTClient | 56:8704100b3b54 | 865 | break; |
AzureIoTClient | 56:8704100b3b54 | 866 | case AMQP_MESSENGER_REASON_CANNOT_PARSE: |
AzureIoTClient | 56:8704100b3b54 | 867 | result = TWIN_REPORT_STATE_REASON_NONE; |
AzureIoTClient | 56:8704100b3b54 | 868 | break; |
AzureIoTClient | 56:8704100b3b54 | 869 | default: |
AzureIoTClient | 56:8704100b3b54 | 870 | LogError("Unrecognized enum value %s (%d)", ENUM_TO_STRING(AMQP_MESSENGER_REASON, amqp_reason), amqp_reason); |
AzureIoTClient | 56:8704100b3b54 | 871 | result = TWIN_REPORT_STATE_REASON_NONE; |
AzureIoTClient | 56:8704100b3b54 | 872 | break; |
AzureIoTClient | 56:8704100b3b54 | 873 | }; |
AzureIoTClient | 39:e98d5df6dc74 | 874 | |
AzureIoTClient | 56:8704100b3b54 | 875 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 876 | } |
AzureIoTClient | 39:e98d5df6dc74 | 877 | |
AzureIoTClient | 39:e98d5df6dc74 | 878 | static void on_amqp_send_complete_callback(AMQP_MESSENGER_SEND_RESULT result, AMQP_MESSENGER_REASON reason, void* context) |
AzureIoTClient | 39:e98d5df6dc74 | 879 | { |
AzureIoTClient | 56:8704100b3b54 | 880 | // Applicable to TWIN requests for reported state PATCH, GET, PUT, DELETE. |
AzureIoTClient | 39:e98d5df6dc74 | 881 | |
AzureIoTClient | 56:8704100b3b54 | 882 | if (context == NULL) |
AzureIoTClient | 56:8704100b3b54 | 883 | { |
AzureIoTClient | 56:8704100b3b54 | 884 | LogError("Invalid argument (context is NULL)"); |
AzureIoTClient | 56:8704100b3b54 | 885 | } |
AzureIoTClient | 56:8704100b3b54 | 886 | else |
AzureIoTClient | 56:8704100b3b54 | 887 | { |
AzureIoTClient | 56:8704100b3b54 | 888 | TWIN_OPERATION_CONTEXT* twin_op_ctx = (TWIN_OPERATION_CONTEXT*)context; |
AzureIoTClient | 39:e98d5df6dc74 | 889 | |
AzureIoTClient | 56:8704100b3b54 | 890 | if (result != AMQP_MESSENGER_SEND_RESULT_SUCCESS) |
AzureIoTClient | 56:8704100b3b54 | 891 | { |
AzureIoTClient | 56:8704100b3b54 | 892 | if (twin_op_ctx->type == TWIN_OPERATION_TYPE_PATCH) |
AzureIoTClient | 56:8704100b3b54 | 893 | { |
AzureIoTClient | 56:8704100b3b54 | 894 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_095: [If operation is a reported state PATCH, if a failure occurs `on_report_state_complete_callback` shall be invoked with TWIN_REPORT_STATE_RESULT_ERROR, status code from the AMQP response and the saved context] |
AzureIoTClient | 56:8704100b3b54 | 895 | if (twin_op_ctx->on_report_state_complete_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 896 | { |
AzureIoTClient | 56:8704100b3b54 | 897 | TWIN_REPORT_STATE_RESULT callback_result; |
AzureIoTClient | 56:8704100b3b54 | 898 | TWIN_REPORT_STATE_REASON callback_reason; |
AzureIoTClient | 39:e98d5df6dc74 | 899 | |
AzureIoTClient | 56:8704100b3b54 | 900 | callback_result = get_twin_messenger_result_from(result); |
AzureIoTClient | 56:8704100b3b54 | 901 | callback_reason = get_twin_messenger_reason_from(reason); |
AzureIoTClient | 39:e98d5df6dc74 | 902 | |
AzureIoTClient | 56:8704100b3b54 | 903 | twin_op_ctx->on_report_state_complete_callback(callback_result, callback_reason, 0, (void*)twin_op_ctx->on_report_state_complete_context); |
AzureIoTClient | 56:8704100b3b54 | 904 | } |
AzureIoTClient | 56:8704100b3b54 | 905 | } |
AzureIoTClient | 56:8704100b3b54 | 906 | else if (reason != AMQP_MESSENGER_REASON_MESSENGER_DESTROYED) |
AzureIoTClient | 56:8704100b3b54 | 907 | { |
AzureIoTClient | 56:8704100b3b54 | 908 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_096: [If operation is a GET/PUT/DELETE, if a failure occurs the TWIN messenger shall attempt to subscribe/unsubscribe again] |
AzureIoTClient | 56:8704100b3b54 | 909 | LogError("Failed sending TWIN operation request (%s, %s, %s, %s, %s)", |
AzureIoTClient | 56:8704100b3b54 | 910 | twin_op_ctx->msgr->device_id, |
AzureIoTClient | 56:8704100b3b54 | 911 | ENUM_TO_STRING(TWIN_OPERATION_TYPE, twin_op_ctx->type), |
AzureIoTClient | 56:8704100b3b54 | 912 | twin_op_ctx->correlation_id, |
AzureIoTClient | 56:8704100b3b54 | 913 | ENUM_TO_STRING(AMQP_MESSENGER_SEND_RESULT, result), ENUM_TO_STRING(AMQP_MESSENGER_REASON, reason)); |
AzureIoTClient | 39:e98d5df6dc74 | 914 | |
AzureIoTClient | 56:8704100b3b54 | 915 | if (twin_op_ctx->type == TWIN_OPERATION_TYPE_GET && |
AzureIoTClient | 56:8704100b3b54 | 916 | twin_op_ctx->msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_GETTING_COMPLETE_PROPERTIES) |
AzureIoTClient | 56:8704100b3b54 | 917 | { |
AzureIoTClient | 56:8704100b3b54 | 918 | twin_op_ctx->msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_GET_COMPLETE_PROPERTIES; |
AzureIoTClient | 56:8704100b3b54 | 919 | twin_op_ctx->msgr->subscription_error_count++; |
AzureIoTClient | 56:8704100b3b54 | 920 | } |
AzureIoTClient | 56:8704100b3b54 | 921 | else if (twin_op_ctx->type == TWIN_OPERATION_TYPE_PUT && |
AzureIoTClient | 56:8704100b3b54 | 922 | twin_op_ctx->msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_GETTING_COMPLETE_PROPERTIES) |
AzureIoTClient | 56:8704100b3b54 | 923 | { |
AzureIoTClient | 56:8704100b3b54 | 924 | twin_op_ctx->msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_GET_COMPLETE_PROPERTIES; |
AzureIoTClient | 56:8704100b3b54 | 925 | twin_op_ctx->msgr->subscription_error_count++; |
AzureIoTClient | 56:8704100b3b54 | 926 | } |
AzureIoTClient | 56:8704100b3b54 | 927 | } |
AzureIoTClient | 39:e98d5df6dc74 | 928 | |
AzureIoTClient | 56:8704100b3b54 | 929 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_097: [If a failure occurred, the current operation shall be removed from `twin_msgr->operations`] |
AzureIoTClient | 56:8704100b3b54 | 930 | if (remove_twin_operation_context_from_queue(twin_op_ctx) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 931 | { |
AzureIoTClient | 56:8704100b3b54 | 932 | update_state(twin_op_ctx->msgr, TWIN_MESSENGER_STATE_ERROR); |
AzureIoTClient | 56:8704100b3b54 | 933 | } |
AzureIoTClient | 56:8704100b3b54 | 934 | else |
AzureIoTClient | 56:8704100b3b54 | 935 | { |
AzureIoTClient | 56:8704100b3b54 | 936 | destroy_twin_operation_context(twin_op_ctx); |
AzureIoTClient | 56:8704100b3b54 | 937 | } |
AzureIoTClient | 56:8704100b3b54 | 938 | } |
AzureIoTClient | 56:8704100b3b54 | 939 | } |
AzureIoTClient | 39:e98d5df6dc74 | 940 | } |
AzureIoTClient | 39:e98d5df6dc74 | 941 | |
AzureIoTClient | 39:e98d5df6dc74 | 942 | static int send_twin_operation_request(TWIN_MESSENGER_INSTANCE* twin_msgr, TWIN_OPERATION_CONTEXT* op_ctx, CONSTBUFFER_HANDLE data) |
AzureIoTClient | 39:e98d5df6dc74 | 943 | { |
AzureIoTClient | 56:8704100b3b54 | 944 | int result; |
AzureIoTClient | 56:8704100b3b54 | 945 | MESSAGE_HANDLE amqp_message; |
AzureIoTClient | 39:e98d5df6dc74 | 946 | |
AzureIoTClient | 56:8704100b3b54 | 947 | if ((amqp_message = create_amqp_message_for_twin_operation(op_ctx->type, op_ctx->correlation_id, data)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 948 | { |
AzureIoTClient | 56:8704100b3b54 | 949 | LogError("Failed creating request message (%s, %s, %s)", twin_msgr->device_id, ENUM_TO_STRING(TWIN_OPERATION_TYPE, op_ctx->type), op_ctx->correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 950 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 951 | } |
AzureIoTClient | 56:8704100b3b54 | 952 | else |
AzureIoTClient | 56:8704100b3b54 | 953 | { |
AzureIoTClient | 56:8704100b3b54 | 954 | if ((op_ctx->time_sent = get_time(NULL)) == INDEFINITE_TIME) |
AzureIoTClient | 56:8704100b3b54 | 955 | { |
AzureIoTClient | 56:8704100b3b54 | 956 | LogError("Failed setting TWIN operation sent time (%s, %s, %s)", twin_msgr->device_id, ENUM_TO_STRING(TWIN_OPERATION_TYPE, op_ctx->type), op_ctx->correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 957 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 958 | } |
AzureIoTClient | 56:8704100b3b54 | 959 | else if (amqp_messenger_send_async(twin_msgr->amqp_msgr, amqp_message, on_amqp_send_complete_callback, (void*)op_ctx) != 0) |
AzureIoTClient | 56:8704100b3b54 | 960 | { |
AzureIoTClient | 56:8704100b3b54 | 961 | LogError("Failed sending request message for (%s, %s, %s)", twin_msgr->device_id, ENUM_TO_STRING(TWIN_OPERATION_TYPE, op_ctx->type), op_ctx->correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 962 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 963 | } |
AzureIoTClient | 56:8704100b3b54 | 964 | else |
AzureIoTClient | 56:8704100b3b54 | 965 | { |
AzureIoTClient | 56:8704100b3b54 | 966 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 967 | } |
AzureIoTClient | 39:e98d5df6dc74 | 968 | |
AzureIoTClient | 56:8704100b3b54 | 969 | message_destroy(amqp_message); |
AzureIoTClient | 56:8704100b3b54 | 970 | } |
AzureIoTClient | 39:e98d5df6dc74 | 971 | |
AzureIoTClient | 56:8704100b3b54 | 972 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 973 | } |
AzureIoTClient | 39:e98d5df6dc74 | 974 | |
AzureIoTClient | 39:e98d5df6dc74 | 975 | |
AzureIoTClient | 39:e98d5df6dc74 | 976 | //---------- Internal Helpers----------// |
AzureIoTClient | 39:e98d5df6dc74 | 977 | |
AzureIoTClient | 39:e98d5df6dc74 | 978 | static bool remove_expired_twin_patch_request(const void* item, const void* match_context, bool* continue_processing) |
AzureIoTClient | 39:e98d5df6dc74 | 979 | { |
AzureIoTClient | 56:8704100b3b54 | 980 | bool remove_item; |
AzureIoTClient | 39:e98d5df6dc74 | 981 | |
AzureIoTClient | 56:8704100b3b54 | 982 | if (item == NULL || match_context == NULL || continue_processing == NULL) |
AzureIoTClient | 56:8704100b3b54 | 983 | { |
AzureIoTClient | 56:8704100b3b54 | 984 | LogError("Invalid argument (item=%p, match_context=%p, continue_processing=%p)", item, match_context, continue_processing); |
AzureIoTClient | 56:8704100b3b54 | 985 | remove_item = false; |
AzureIoTClient | 56:8704100b3b54 | 986 | } |
AzureIoTClient | 56:8704100b3b54 | 987 | else |
AzureIoTClient | 56:8704100b3b54 | 988 | { |
AzureIoTClient | 39:e98d5df6dc74 | 989 | |
AzureIoTClient | 56:8704100b3b54 | 990 | time_t current_time = *(time_t*)match_context; |
AzureIoTClient | 56:8704100b3b54 | 991 | TWIN_PATCH_OPERATION_CONTEXT* twin_patch_ctx = (TWIN_PATCH_OPERATION_CONTEXT*)item; |
AzureIoTClient | 39:e98d5df6dc74 | 992 | |
AzureIoTClient | 56:8704100b3b54 | 993 | if (get_difftime(current_time, twin_patch_ctx->time_enqueued) >= DEFAULT_TWIN_OPERATION_TIMEOUT_SECS) |
AzureIoTClient | 56:8704100b3b54 | 994 | { |
AzureIoTClient | 56:8704100b3b54 | 995 | remove_item = true; |
AzureIoTClient | 56:8704100b3b54 | 996 | *continue_processing = true; |
AzureIoTClient | 39:e98d5df6dc74 | 997 | |
AzureIoTClient | 56:8704100b3b54 | 998 | if (twin_patch_ctx->on_report_state_complete_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 999 | { |
AzureIoTClient | 56:8704100b3b54 | 1000 | twin_patch_ctx->on_report_state_complete_callback(TWIN_REPORT_STATE_RESULT_ERROR, TWIN_REPORT_STATE_REASON_TIMEOUT, 0, twin_patch_ctx->on_report_state_complete_context); |
AzureIoTClient | 56:8704100b3b54 | 1001 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1002 | |
AzureIoTClient | 56:8704100b3b54 | 1003 | CONSTBUFFER_Destroy(twin_patch_ctx->data); |
AzureIoTClient | 56:8704100b3b54 | 1004 | free(twin_patch_ctx); |
AzureIoTClient | 56:8704100b3b54 | 1005 | } |
AzureIoTClient | 56:8704100b3b54 | 1006 | else |
AzureIoTClient | 56:8704100b3b54 | 1007 | { |
AzureIoTClient | 56:8704100b3b54 | 1008 | remove_item = false; |
AzureIoTClient | 56:8704100b3b54 | 1009 | *continue_processing = false; |
AzureIoTClient | 56:8704100b3b54 | 1010 | } |
AzureIoTClient | 56:8704100b3b54 | 1011 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1012 | |
AzureIoTClient | 56:8704100b3b54 | 1013 | return remove_item; |
AzureIoTClient | 39:e98d5df6dc74 | 1014 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1015 | |
AzureIoTClient | 39:e98d5df6dc74 | 1016 | static bool remove_expired_twin_operation_request(const void* item, const void* match_context, bool* continue_processing) |
AzureIoTClient | 39:e98d5df6dc74 | 1017 | { |
AzureIoTClient | 56:8704100b3b54 | 1018 | bool result; |
AzureIoTClient | 39:e98d5df6dc74 | 1019 | |
AzureIoTClient | 56:8704100b3b54 | 1020 | if (item == NULL || match_context == NULL || continue_processing == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1021 | { |
AzureIoTClient | 56:8704100b3b54 | 1022 | LogError("Invalid argument (item=%p, match_context=%p, continue_processing=%p)", item, match_context, continue_processing); |
AzureIoTClient | 56:8704100b3b54 | 1023 | result = false; |
AzureIoTClient | 56:8704100b3b54 | 1024 | } |
AzureIoTClient | 56:8704100b3b54 | 1025 | else |
AzureIoTClient | 56:8704100b3b54 | 1026 | { |
AzureIoTClient | 56:8704100b3b54 | 1027 | TWIN_OPERATION_CONTEXT* twin_op_ctx = (TWIN_OPERATION_CONTEXT*)item; |
AzureIoTClient | 56:8704100b3b54 | 1028 | TWIN_MESSENGER_INSTANCE* twin_msgr = twin_op_ctx->msgr; |
AzureIoTClient | 56:8704100b3b54 | 1029 | time_t current_time = *(time_t*)match_context; |
AzureIoTClient | 39:e98d5df6dc74 | 1030 | |
AzureIoTClient | 56:8704100b3b54 | 1031 | if (get_difftime(current_time, twin_op_ctx->time_sent) < DEFAULT_TWIN_OPERATION_TIMEOUT_SECS) |
AzureIoTClient | 56:8704100b3b54 | 1032 | { |
AzureIoTClient | 56:8704100b3b54 | 1033 | result = false; |
AzureIoTClient | 56:8704100b3b54 | 1034 | // All next elements in the list have a later time_sent, so they won't be expired, and don't need to be removed. |
AzureIoTClient | 56:8704100b3b54 | 1035 | *continue_processing = false; |
AzureIoTClient | 56:8704100b3b54 | 1036 | } |
AzureIoTClient | 56:8704100b3b54 | 1037 | else |
AzureIoTClient | 56:8704100b3b54 | 1038 | { |
AzureIoTClient | 56:8704100b3b54 | 1039 | LogError("Twin operation timed out (%s, %s, %s)", twin_msgr->device_id, ENUM_TO_STRING(TWIN_OPERATION_TYPE, twin_op_ctx->type), twin_op_ctx->correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 1040 | result = true; |
AzureIoTClient | 56:8704100b3b54 | 1041 | *continue_processing = true; |
AzureIoTClient | 39:e98d5df6dc74 | 1042 | |
AzureIoTClient | 56:8704100b3b54 | 1043 | if (twin_op_ctx->type == TWIN_OPERATION_TYPE_PATCH) |
AzureIoTClient | 56:8704100b3b54 | 1044 | { |
AzureIoTClient | 56:8704100b3b54 | 1045 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_081: [If a timed-out item is a reported property PATCH, `on_report_state_complete_callback` shall be invoked with RESULT_ERROR and REASON_TIMEOUT] |
AzureIoTClient | 56:8704100b3b54 | 1046 | if (twin_op_ctx->on_report_state_complete_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1047 | { |
AzureIoTClient | 56:8704100b3b54 | 1048 | twin_op_ctx->on_report_state_complete_callback(TWIN_REPORT_STATE_RESULT_ERROR, TWIN_REPORT_STATE_REASON_TIMEOUT, 0, twin_op_ctx->on_report_state_complete_context); |
AzureIoTClient | 56:8704100b3b54 | 1049 | } |
AzureIoTClient | 56:8704100b3b54 | 1050 | } |
AzureIoTClient | 56:8704100b3b54 | 1051 | else if (twin_op_ctx->type == TWIN_OPERATION_TYPE_GET) |
AzureIoTClient | 56:8704100b3b54 | 1052 | { |
AzureIoTClient | 56:8704100b3b54 | 1053 | if (twin_msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_GETTING_COMPLETE_PROPERTIES) |
AzureIoTClient | 56:8704100b3b54 | 1054 | { |
AzureIoTClient | 56:8704100b3b54 | 1055 | twin_msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_GET_COMPLETE_PROPERTIES; |
AzureIoTClient | 56:8704100b3b54 | 1056 | twin_msgr->subscription_error_count++; |
AzureIoTClient | 56:8704100b3b54 | 1057 | } |
AzureIoTClient | 56:8704100b3b54 | 1058 | } |
AzureIoTClient | 56:8704100b3b54 | 1059 | else if (twin_op_ctx->type == TWIN_OPERATION_TYPE_PUT) |
AzureIoTClient | 56:8704100b3b54 | 1060 | { |
AzureIoTClient | 56:8704100b3b54 | 1061 | if (twin_msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_SUBSCRIBING) |
AzureIoTClient | 56:8704100b3b54 | 1062 | { |
AzureIoTClient | 56:8704100b3b54 | 1063 | twin_msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_SUBSCRIBE_FOR_UPDATES; |
AzureIoTClient | 56:8704100b3b54 | 1064 | twin_msgr->subscription_error_count++; |
AzureIoTClient | 56:8704100b3b54 | 1065 | } |
AzureIoTClient | 56:8704100b3b54 | 1066 | } |
AzureIoTClient | 56:8704100b3b54 | 1067 | else if (twin_op_ctx->type == TWIN_OPERATION_TYPE_DELETE) |
AzureIoTClient | 56:8704100b3b54 | 1068 | { |
AzureIoTClient | 56:8704100b3b54 | 1069 | if (twin_msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_UNSUBSCRIBING) |
AzureIoTClient | 56:8704100b3b54 | 1070 | { |
AzureIoTClient | 56:8704100b3b54 | 1071 | twin_msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_UNSUBSCRIBE; |
AzureIoTClient | 56:8704100b3b54 | 1072 | twin_msgr->subscription_error_count++; |
AzureIoTClient | 56:8704100b3b54 | 1073 | } |
AzureIoTClient | 56:8704100b3b54 | 1074 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1075 | |
AzureIoTClient | 56:8704100b3b54 | 1076 | destroy_twin_operation_context(twin_op_ctx); |
AzureIoTClient | 56:8704100b3b54 | 1077 | } |
AzureIoTClient | 56:8704100b3b54 | 1078 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1079 | |
AzureIoTClient | 56:8704100b3b54 | 1080 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 1081 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1082 | |
AzureIoTClient | 39:e98d5df6dc74 | 1083 | static void process_timeouts(TWIN_MESSENGER_INSTANCE* twin_msgr) |
AzureIoTClient | 39:e98d5df6dc74 | 1084 | { |
AzureIoTClient | 56:8704100b3b54 | 1085 | time_t current_time; |
AzureIoTClient | 39:e98d5df6dc74 | 1086 | |
AzureIoTClient | 56:8704100b3b54 | 1087 | if ((current_time = get_time(NULL)) == INDEFINITE_TIME) |
AzureIoTClient | 56:8704100b3b54 | 1088 | { |
AzureIoTClient | 56:8704100b3b54 | 1089 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_082: [If any failure occurs while verifying/removing timed-out items `twin_msgr->state` shall be set to TWIN_MESSENGER_STATE_ERROR and user informed] |
AzureIoTClient | 56:8704100b3b54 | 1090 | LogError("Failed obtaining current time (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1091 | update_state(twin_msgr, TWIN_MESSENGER_STATE_ERROR); |
AzureIoTClient | 56:8704100b3b54 | 1092 | } |
AzureIoTClient | 56:8704100b3b54 | 1093 | else |
AzureIoTClient | 56:8704100b3b54 | 1094 | { |
AzureIoTClient | 56:8704100b3b54 | 1095 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_080: [twin_messenger_do_work() shall remove and destroy any timed out items from `twin_msgr->pending_patches` and `twin_msgr->operations`] |
AzureIoTClient | 56:8704100b3b54 | 1096 | (void)singlylinkedlist_remove_if(twin_msgr->pending_patches, remove_expired_twin_patch_request, (const void*)¤t_time); |
AzureIoTClient | 56:8704100b3b54 | 1097 | (void)singlylinkedlist_remove_if(twin_msgr->operations, remove_expired_twin_operation_request, (const void*)¤t_time); |
AzureIoTClient | 56:8704100b3b54 | 1098 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1099 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1100 | |
AzureIoTClient | 39:e98d5df6dc74 | 1101 | static bool send_pending_twin_patch(const void* item, const void* match_context, bool* continue_processing) |
AzureIoTClient | 39:e98d5df6dc74 | 1102 | { |
AzureIoTClient | 56:8704100b3b54 | 1103 | bool result; |
AzureIoTClient | 39:e98d5df6dc74 | 1104 | |
AzureIoTClient | 56:8704100b3b54 | 1105 | if (item == NULL || match_context == NULL || continue_processing == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1106 | { |
AzureIoTClient | 56:8704100b3b54 | 1107 | LogError("Invalid argument (item=%p, match_context=%p, continue_processing=%p)", item, match_context, continue_processing); |
AzureIoTClient | 56:8704100b3b54 | 1108 | result = false; |
AzureIoTClient | 56:8704100b3b54 | 1109 | } |
AzureIoTClient | 56:8704100b3b54 | 1110 | else |
AzureIoTClient | 56:8704100b3b54 | 1111 | { |
AzureIoTClient | 56:8704100b3b54 | 1112 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)match_context; |
AzureIoTClient | 56:8704100b3b54 | 1113 | TWIN_PATCH_OPERATION_CONTEXT* twin_patch_ctx = (TWIN_PATCH_OPERATION_CONTEXT*)item; |
AzureIoTClient | 56:8704100b3b54 | 1114 | TWIN_OPERATION_CONTEXT* twin_op_ctx; |
AzureIoTClient | 39:e98d5df6dc74 | 1115 | |
AzureIoTClient | 56:8704100b3b54 | 1116 | if ((twin_op_ctx = create_twin_operation_context(twin_msgr, TWIN_OPERATION_TYPE_PATCH)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1117 | { |
AzureIoTClient | 56:8704100b3b54 | 1118 | LogError("Failed creating context for sending reported state (%s)", twin_msgr->device_id); |
AzureIoTClient | 39:e98d5df6dc74 | 1119 | |
AzureIoTClient | 56:8704100b3b54 | 1120 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_061: [If any other failure occurs sending the PATCH request, `on_report_state_complete_callback` shall be invoked with RESULT_ERROR and REASON_INTERNAL_ERROR] |
AzureIoTClient | 56:8704100b3b54 | 1121 | if (twin_patch_ctx->on_report_state_complete_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1122 | { |
AzureIoTClient | 56:8704100b3b54 | 1123 | twin_patch_ctx->on_report_state_complete_callback(TWIN_REPORT_STATE_RESULT_ERROR, TWIN_REPORT_STATE_REASON_INTERNAL_ERROR, 0, twin_patch_ctx->on_report_state_complete_context); |
AzureIoTClient | 56:8704100b3b54 | 1124 | } |
AzureIoTClient | 56:8704100b3b54 | 1125 | } |
AzureIoTClient | 56:8704100b3b54 | 1126 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_062: [If amqp_send_async() succeeds, the PATCH request shall be queued into `twin_msgr->operations`] |
AzureIoTClient | 56:8704100b3b54 | 1127 | else if (add_twin_operation_context_to_queue(twin_op_ctx) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 1128 | { |
AzureIoTClient | 56:8704100b3b54 | 1129 | LogError("Failed adding TWIN operation context to queue (%s)", twin_msgr->device_id); |
AzureIoTClient | 39:e98d5df6dc74 | 1130 | |
AzureIoTClient | 56:8704100b3b54 | 1131 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_061: [If any other failure occurs sending the PATCH request, `on_report_state_complete_callback` shall be invoked with RESULT_ERROR and REASON_INTERNAL_ERROR] |
AzureIoTClient | 56:8704100b3b54 | 1132 | if (twin_patch_ctx->on_report_state_complete_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1133 | { |
AzureIoTClient | 56:8704100b3b54 | 1134 | twin_patch_ctx->on_report_state_complete_callback(TWIN_REPORT_STATE_RESULT_ERROR, TWIN_REPORT_STATE_REASON_INTERNAL_ERROR, 0, twin_patch_ctx->on_report_state_complete_context); |
AzureIoTClient | 56:8704100b3b54 | 1135 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1136 | |
AzureIoTClient | 56:8704100b3b54 | 1137 | destroy_twin_operation_context(twin_op_ctx); |
AzureIoTClient | 56:8704100b3b54 | 1138 | } |
AzureIoTClient | 56:8704100b3b54 | 1139 | else |
AzureIoTClient | 56:8704100b3b54 | 1140 | { |
AzureIoTClient | 56:8704100b3b54 | 1141 | twin_op_ctx->on_report_state_complete_callback = twin_patch_ctx->on_report_state_complete_callback; |
AzureIoTClient | 56:8704100b3b54 | 1142 | twin_op_ctx->on_report_state_complete_context = twin_patch_ctx->on_report_state_complete_context; |
AzureIoTClient | 39:e98d5df6dc74 | 1143 | |
AzureIoTClient | 56:8704100b3b54 | 1144 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_059: [If reported property PATCH shall be sent as an uAMQP MESSAGE_HANDLE instance using amqp_send_async() passing `on_amqp_send_complete_callback`] |
AzureIoTClient | 56:8704100b3b54 | 1145 | if (send_twin_operation_request(twin_msgr, twin_op_ctx, twin_patch_ctx->data) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 1146 | { |
AzureIoTClient | 56:8704100b3b54 | 1147 | LogError("Failed sending reported state (%s)", twin_msgr->device_id); |
AzureIoTClient | 39:e98d5df6dc74 | 1148 | |
AzureIoTClient | 56:8704100b3b54 | 1149 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_060: [If amqp_send_async() fails, `on_report_state_complete_callback` shall be invoked with RESULT_ERROR and REASON_FAIL_SENDING] |
AzureIoTClient | 56:8704100b3b54 | 1150 | if (twin_patch_ctx->on_report_state_complete_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1151 | { |
AzureIoTClient | 56:8704100b3b54 | 1152 | twin_patch_ctx->on_report_state_complete_callback(TWIN_REPORT_STATE_RESULT_ERROR, TWIN_REPORT_STATE_REASON_FAIL_SENDING, 0, twin_patch_ctx->on_report_state_complete_context); |
AzureIoTClient | 56:8704100b3b54 | 1153 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1154 | |
AzureIoTClient | 56:8704100b3b54 | 1155 | (void)remove_twin_operation_context_from_queue(twin_op_ctx); |
AzureIoTClient | 56:8704100b3b54 | 1156 | destroy_twin_operation_context(twin_op_ctx); |
AzureIoTClient | 56:8704100b3b54 | 1157 | } |
AzureIoTClient | 56:8704100b3b54 | 1158 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1159 | |
AzureIoTClient | 56:8704100b3b54 | 1160 | CONSTBUFFER_Destroy(twin_patch_ctx->data); |
AzureIoTClient | 56:8704100b3b54 | 1161 | free(twin_patch_ctx); |
AzureIoTClient | 39:e98d5df6dc74 | 1162 | |
AzureIoTClient | 56:8704100b3b54 | 1163 | *continue_processing = true; |
AzureIoTClient | 56:8704100b3b54 | 1164 | result = true; |
AzureIoTClient | 56:8704100b3b54 | 1165 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1166 | |
AzureIoTClient | 56:8704100b3b54 | 1167 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 1168 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1169 | |
AzureIoTClient | 39:e98d5df6dc74 | 1170 | static void process_twin_subscription(TWIN_MESSENGER_INSTANCE* twin_msgr) |
AzureIoTClient | 39:e98d5df6dc74 | 1171 | { |
AzureIoTClient | 56:8704100b3b54 | 1172 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_078: [If failures occur sending subscription requests to the service for more than 3 times, TWIN messenger shall set its state to TWIN_MESSENGER_STATE_ERROR and inform the user] |
AzureIoTClient | 56:8704100b3b54 | 1173 | if (twin_msgr->subscription_error_count >= DEFAULT_MAX_TWIN_SUBSCRIPTION_ERROR_COUNT) |
AzureIoTClient | 56:8704100b3b54 | 1174 | { |
AzureIoTClient | 56:8704100b3b54 | 1175 | LogError("Maximum number of TWIN subscription-related failures reached (%s, %d)", twin_msgr->device_id, twin_msgr->subscription_error_count); |
AzureIoTClient | 56:8704100b3b54 | 1176 | update_state(twin_msgr, TWIN_MESSENGER_STATE_ERROR); |
AzureIoTClient | 56:8704100b3b54 | 1177 | } |
AzureIoTClient | 56:8704100b3b54 | 1178 | else |
AzureIoTClient | 56:8704100b3b54 | 1179 | { |
AzureIoTClient | 56:8704100b3b54 | 1180 | TWIN_OPERATION_TYPE op_type = TWIN_OPERATION_TYPE_PATCH; |
AzureIoTClient | 56:8704100b3b54 | 1181 | TWIN_SUBSCRIPTION_STATE next_subscription_state = twin_msgr->subscription_state; |
AzureIoTClient | 39:e98d5df6dc74 | 1182 | |
AzureIoTClient | 56:8704100b3b54 | 1183 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_074: [If subscribing, twin_messenger_do_work() shall request a complete desired properties report] |
AzureIoTClient | 56:8704100b3b54 | 1184 | if (twin_msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_GET_COMPLETE_PROPERTIES) |
AzureIoTClient | 56:8704100b3b54 | 1185 | { |
AzureIoTClient | 56:8704100b3b54 | 1186 | op_type = TWIN_OPERATION_TYPE_GET; |
AzureIoTClient | 56:8704100b3b54 | 1187 | next_subscription_state = TWIN_SUBSCRIPTION_STATE_GETTING_COMPLETE_PROPERTIES; |
AzureIoTClient | 56:8704100b3b54 | 1188 | } |
AzureIoTClient | 56:8704100b3b54 | 1189 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_075: [If a complete desired report has been received, the TWIN messenger shall request partial updates to desired properties] |
AzureIoTClient | 56:8704100b3b54 | 1190 | else if (twin_msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_SUBSCRIBE_FOR_UPDATES) |
AzureIoTClient | 56:8704100b3b54 | 1191 | { |
AzureIoTClient | 56:8704100b3b54 | 1192 | op_type = TWIN_OPERATION_TYPE_PUT; |
AzureIoTClient | 56:8704100b3b54 | 1193 | next_subscription_state = TWIN_SUBSCRIPTION_STATE_SUBSCRIBING; |
AzureIoTClient | 56:8704100b3b54 | 1194 | } |
AzureIoTClient | 56:8704100b3b54 | 1195 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_076: [If unsubscribing, twin_messenger_do_work() shall send a DELETE request to the service] |
AzureIoTClient | 56:8704100b3b54 | 1196 | else if (twin_msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_UNSUBSCRIBE) |
AzureIoTClient | 56:8704100b3b54 | 1197 | { |
AzureIoTClient | 56:8704100b3b54 | 1198 | op_type = TWIN_OPERATION_TYPE_PUT; |
AzureIoTClient | 56:8704100b3b54 | 1199 | next_subscription_state = TWIN_SUBSCRIPTION_STATE_UNSUBSCRIBING; |
AzureIoTClient | 56:8704100b3b54 | 1200 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1201 | |
AzureIoTClient | 56:8704100b3b54 | 1202 | if (next_subscription_state != twin_msgr->subscription_state) |
AzureIoTClient | 56:8704100b3b54 | 1203 | { |
AzureIoTClient | 56:8704100b3b54 | 1204 | TWIN_OPERATION_CONTEXT* twin_op_ctx; |
AzureIoTClient | 39:e98d5df6dc74 | 1205 | |
AzureIoTClient | 56:8704100b3b54 | 1206 | if ((twin_op_ctx = create_twin_operation_context(twin_msgr, op_type)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1207 | { |
AzureIoTClient | 56:8704100b3b54 | 1208 | LogError("Failed creating a context for TWIN request (%s, %s)", twin_msgr->device_id, ENUM_TO_STRING(TWIN_OPERATION_TYPE, op_type)); |
AzureIoTClient | 56:8704100b3b54 | 1209 | update_state(twin_msgr, TWIN_MESSENGER_STATE_ERROR); |
AzureIoTClient | 56:8704100b3b54 | 1210 | } |
AzureIoTClient | 56:8704100b3b54 | 1211 | else |
AzureIoTClient | 56:8704100b3b54 | 1212 | { |
AzureIoTClient | 56:8704100b3b54 | 1213 | if (add_twin_operation_context_to_queue(twin_op_ctx) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 1214 | { |
AzureIoTClient | 56:8704100b3b54 | 1215 | LogError("Failed queueing TWIN request context (%s, %s)", twin_msgr->device_id, ENUM_TO_STRING(TWIN_OPERATION_TYPE, op_type)); |
AzureIoTClient | 56:8704100b3b54 | 1216 | destroy_twin_operation_context(twin_op_ctx); |
AzureIoTClient | 56:8704100b3b54 | 1217 | update_state(twin_msgr, TWIN_MESSENGER_STATE_ERROR); |
AzureIoTClient | 56:8704100b3b54 | 1218 | } |
AzureIoTClient | 56:8704100b3b54 | 1219 | else if (send_twin_operation_request(twin_msgr, twin_op_ctx, NULL) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 1220 | { |
AzureIoTClient | 56:8704100b3b54 | 1221 | LogError("Failed sending TWIN request (%s, %s)", twin_msgr->device_id, ENUM_TO_STRING(TWIN_OPERATION_TYPE, op_type)); |
AzureIoTClient | 39:e98d5df6dc74 | 1222 | |
AzureIoTClient | 56:8704100b3b54 | 1223 | (void)remove_twin_operation_context_from_queue(twin_op_ctx); |
AzureIoTClient | 56:8704100b3b54 | 1224 | destroy_twin_operation_context(twin_op_ctx); |
AzureIoTClient | 56:8704100b3b54 | 1225 | update_state(twin_msgr, TWIN_MESSENGER_STATE_ERROR); |
AzureIoTClient | 56:8704100b3b54 | 1226 | } |
AzureIoTClient | 56:8704100b3b54 | 1227 | else |
AzureIoTClient | 56:8704100b3b54 | 1228 | { |
AzureIoTClient | 56:8704100b3b54 | 1229 | twin_msgr->subscription_state = next_subscription_state; |
AzureIoTClient | 56:8704100b3b54 | 1230 | } |
AzureIoTClient | 56:8704100b3b54 | 1231 | } |
AzureIoTClient | 56:8704100b3b54 | 1232 | } |
AzureIoTClient | 56:8704100b3b54 | 1233 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1234 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1235 | |
AzureIoTClient | 39:e98d5df6dc74 | 1236 | static bool cancel_all_pending_twin_operations(const void* item, const void* match_context, bool* continue_processing) |
AzureIoTClient | 39:e98d5df6dc74 | 1237 | { |
AzureIoTClient | 56:8704100b3b54 | 1238 | bool result; |
AzureIoTClient | 39:e98d5df6dc74 | 1239 | |
AzureIoTClient | 56:8704100b3b54 | 1240 | if (item == NULL || continue_processing == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1241 | { |
AzureIoTClient | 56:8704100b3b54 | 1242 | LogError("Invalid argument (item=%p, continue_processing=%p)", item, continue_processing); |
AzureIoTClient | 56:8704100b3b54 | 1243 | result = false; |
AzureIoTClient | 56:8704100b3b54 | 1244 | } |
AzureIoTClient | 56:8704100b3b54 | 1245 | else |
AzureIoTClient | 56:8704100b3b54 | 1246 | { |
AzureIoTClient | 56:8704100b3b54 | 1247 | TWIN_OPERATION_CONTEXT* twin_op_ctx = (TWIN_OPERATION_CONTEXT*)item; |
AzureIoTClient | 56:8704100b3b54 | 1248 | (void)match_context; |
AzureIoTClient | 39:e98d5df6dc74 | 1249 | |
AzureIoTClient | 56:8704100b3b54 | 1250 | if (twin_op_ctx->type == TWIN_OPERATION_TYPE_PATCH) |
AzureIoTClient | 56:8704100b3b54 | 1251 | { |
AzureIoTClient | 56:8704100b3b54 | 1252 | if (twin_op_ctx->on_report_state_complete_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1253 | { |
AzureIoTClient | 56:8704100b3b54 | 1254 | twin_op_ctx->on_report_state_complete_callback(TWIN_REPORT_STATE_RESULT_CANCELLED, TWIN_REPORT_STATE_REASON_MESSENGER_DESTROYED, 0, twin_op_ctx->on_report_state_complete_context); |
AzureIoTClient | 56:8704100b3b54 | 1255 | } |
AzureIoTClient | 56:8704100b3b54 | 1256 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1257 | |
AzureIoTClient | 56:8704100b3b54 | 1258 | destroy_twin_operation_context(twin_op_ctx); |
AzureIoTClient | 39:e98d5df6dc74 | 1259 | |
AzureIoTClient | 56:8704100b3b54 | 1260 | *continue_processing = true; |
AzureIoTClient | 56:8704100b3b54 | 1261 | result = true; |
AzureIoTClient | 56:8704100b3b54 | 1262 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1263 | |
AzureIoTClient | 56:8704100b3b54 | 1264 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 1265 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1266 | |
AzureIoTClient | 39:e98d5df6dc74 | 1267 | static bool cancel_pending_twin_patch_operation(const void* item, const void* match_context, bool* continue_processing) |
AzureIoTClient | 39:e98d5df6dc74 | 1268 | { |
AzureIoTClient | 56:8704100b3b54 | 1269 | bool result; |
AzureIoTClient | 39:e98d5df6dc74 | 1270 | |
AzureIoTClient | 56:8704100b3b54 | 1271 | if (item == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1272 | { |
AzureIoTClient | 56:8704100b3b54 | 1273 | LogError("Invalid argument (item is NULL)"); |
AzureIoTClient | 56:8704100b3b54 | 1274 | *continue_processing = false; |
AzureIoTClient | 56:8704100b3b54 | 1275 | result = false; |
AzureIoTClient | 56:8704100b3b54 | 1276 | } |
AzureIoTClient | 56:8704100b3b54 | 1277 | else |
AzureIoTClient | 56:8704100b3b54 | 1278 | { |
AzureIoTClient | 56:8704100b3b54 | 1279 | TWIN_PATCH_OPERATION_CONTEXT* twin_patch_ctx = (TWIN_PATCH_OPERATION_CONTEXT*)item; |
AzureIoTClient | 56:8704100b3b54 | 1280 | (void)match_context; |
AzureIoTClient | 39:e98d5df6dc74 | 1281 | |
AzureIoTClient | 56:8704100b3b54 | 1282 | if (twin_patch_ctx->on_report_state_complete_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1283 | { |
AzureIoTClient | 56:8704100b3b54 | 1284 | twin_patch_ctx->on_report_state_complete_callback(TWIN_REPORT_STATE_RESULT_CANCELLED, TWIN_REPORT_STATE_REASON_MESSENGER_DESTROYED, 0, twin_patch_ctx->on_report_state_complete_context); |
AzureIoTClient | 56:8704100b3b54 | 1285 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1286 | |
AzureIoTClient | 56:8704100b3b54 | 1287 | CONSTBUFFER_Destroy(twin_patch_ctx->data); |
AzureIoTClient | 56:8704100b3b54 | 1288 | free(twin_patch_ctx); |
AzureIoTClient | 39:e98d5df6dc74 | 1289 | |
AzureIoTClient | 56:8704100b3b54 | 1290 | *continue_processing = true; |
AzureIoTClient | 56:8704100b3b54 | 1291 | result = true; |
AzureIoTClient | 56:8704100b3b54 | 1292 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1293 | |
AzureIoTClient | 56:8704100b3b54 | 1294 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 1295 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1296 | |
AzureIoTClient | 39:e98d5df6dc74 | 1297 | static void internal_twin_messenger_destroy(TWIN_MESSENGER_INSTANCE* twin_msgr) |
AzureIoTClient | 39:e98d5df6dc74 | 1298 | { |
AzureIoTClient | 56:8704100b3b54 | 1299 | if (twin_msgr->amqp_msgr != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1300 | { |
AzureIoTClient | 56:8704100b3b54 | 1301 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_099: [`twin_msgr->amqp_messenger` shall be destroyed using amqp_messenger_destroy()] |
AzureIoTClient | 56:8704100b3b54 | 1302 | amqp_messenger_destroy(twin_msgr->amqp_msgr); |
AzureIoTClient | 56:8704100b3b54 | 1303 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1304 | |
AzureIoTClient | 56:8704100b3b54 | 1305 | if (twin_msgr->pending_patches != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1306 | { |
AzureIoTClient | 56:8704100b3b54 | 1307 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_100: [All elements of `twin_msgr->pending_patches` shall be removed, invoking `on_report_state_complete_callback` for each with TWIN_REPORT_STATE_REASON_MESSENGER_DESTROYED] |
AzureIoTClient | 56:8704100b3b54 | 1308 | if (singlylinkedlist_remove_if(twin_msgr->pending_patches, cancel_pending_twin_patch_operation, twin_msgr) != 0) |
AzureIoTClient | 56:8704100b3b54 | 1309 | { |
AzureIoTClient | 56:8704100b3b54 | 1310 | LogError("Failed removing pending desired properties PATCH operation (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1311 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1312 | |
AzureIoTClient | 56:8704100b3b54 | 1313 | singlylinkedlist_destroy(twin_msgr->pending_patches); |
AzureIoTClient | 56:8704100b3b54 | 1314 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1315 | |
AzureIoTClient | 56:8704100b3b54 | 1316 | if (twin_msgr->operations != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1317 | { |
AzureIoTClient | 56:8704100b3b54 | 1318 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_101: [All elements of `twin_msgr->operations` shall be removed, invoking `on_report_state_complete_callback` for each PATCH with TWIN_REPORT_STATE_REASON_MESSENGER_DESTROYED] |
AzureIoTClient | 56:8704100b3b54 | 1319 | singlylinkedlist_remove_if(twin_msgr->operations, cancel_all_pending_twin_operations, (const void*)twin_msgr); |
AzureIoTClient | 56:8704100b3b54 | 1320 | singlylinkedlist_destroy(twin_msgr->operations); |
AzureIoTClient | 56:8704100b3b54 | 1321 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1322 | |
AzureIoTClient | 56:8704100b3b54 | 1323 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_102: [twin_messenger_destroy() shall release all memory allocated for and within `twin_msgr`] |
AzureIoTClient | 56:8704100b3b54 | 1324 | if (twin_msgr->client_version != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1325 | { |
AzureIoTClient | 56:8704100b3b54 | 1326 | free(twin_msgr->client_version); |
AzureIoTClient | 56:8704100b3b54 | 1327 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1328 | |
AzureIoTClient | 56:8704100b3b54 | 1329 | if (twin_msgr->device_id != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1330 | { |
AzureIoTClient | 56:8704100b3b54 | 1331 | free(twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1332 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1333 | |
AzureIoTClient | 56:8704100b3b54 | 1334 | if (twin_msgr->module_id != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1335 | { |
AzureIoTClient | 56:8704100b3b54 | 1336 | free(twin_msgr->module_id); |
AzureIoTClient | 56:8704100b3b54 | 1337 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1338 | |
AzureIoTClient | 56:8704100b3b54 | 1339 | if (twin_msgr->iothub_host_fqdn != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1340 | { |
AzureIoTClient | 56:8704100b3b54 | 1341 | free(twin_msgr->iothub_host_fqdn); |
AzureIoTClient | 56:8704100b3b54 | 1342 | } |
AzureIoTClient | 56:8704100b3b54 | 1343 | |
AzureIoTClient | 56:8704100b3b54 | 1344 | free(twin_msgr); |
AzureIoTClient | 39:e98d5df6dc74 | 1345 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1346 | |
AzureIoTClient | 39:e98d5df6dc74 | 1347 | |
AzureIoTClient | 39:e98d5df6dc74 | 1348 | //---------- Internal Callbacks ----------// |
AzureIoTClient | 39:e98d5df6dc74 | 1349 | |
AzureIoTClient | 39:e98d5df6dc74 | 1350 | static AMQP_MESSENGER_DISPOSITION_RESULT on_amqp_message_received_callback(MESSAGE_HANDLE message, AMQP_MESSENGER_MESSAGE_DISPOSITION_INFO* disposition_info, void* context) |
AzureIoTClient | 39:e98d5df6dc74 | 1351 | { |
AzureIoTClient | 39:e98d5df6dc74 | 1352 | |
AzureIoTClient | 56:8704100b3b54 | 1353 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_084: [If `message` or `context` are NULL, on_amqp_message_received_callback shall return immediately] |
AzureIoTClient | 56:8704100b3b54 | 1354 | AMQP_MESSENGER_DISPOSITION_RESULT disposition_result; |
AzureIoTClient | 39:e98d5df6dc74 | 1355 | |
AzureIoTClient | 56:8704100b3b54 | 1356 | if (message == NULL || context == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1357 | { |
AzureIoTClient | 56:8704100b3b54 | 1358 | LogError("Invalid argument (message=%p, context=%p)", message, context); |
AzureIoTClient | 56:8704100b3b54 | 1359 | disposition_result = AMQP_MESSENGER_DISPOSITION_RESULT_REJECTED; |
AzureIoTClient | 56:8704100b3b54 | 1360 | } |
AzureIoTClient | 56:8704100b3b54 | 1361 | else |
AzureIoTClient | 56:8704100b3b54 | 1362 | { |
AzureIoTClient | 56:8704100b3b54 | 1363 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)context; |
AzureIoTClient | 39:e98d5df6dc74 | 1364 | |
AzureIoTClient | 56:8704100b3b54 | 1365 | char* correlation_id; |
AzureIoTClient | 56:8704100b3b54 | 1366 | |
AzureIoTClient | 56:8704100b3b54 | 1367 | bool has_status_code; |
AzureIoTClient | 56:8704100b3b54 | 1368 | int status_code; |
AzureIoTClient | 56:8704100b3b54 | 1369 | |
AzureIoTClient | 56:8704100b3b54 | 1370 | bool has_version; |
AzureIoTClient | 56:8704100b3b54 | 1371 | int64_t version; |
AzureIoTClient | 39:e98d5df6dc74 | 1372 | |
AzureIoTClient | 56:8704100b3b54 | 1373 | bool has_twin_report; |
AzureIoTClient | 56:8704100b3b54 | 1374 | BINARY_DATA twin_report; |
AzureIoTClient | 39:e98d5df6dc74 | 1375 | |
AzureIoTClient | 56:8704100b3b54 | 1376 | amqp_messenger_destroy_disposition_info(disposition_info); |
AzureIoTClient | 56:8704100b3b54 | 1377 | disposition_result = AMQP_MESSENGER_DISPOSITION_RESULT_ACCEPTED; |
AzureIoTClient | 39:e98d5df6dc74 | 1378 | |
AzureIoTClient | 56:8704100b3b54 | 1379 | if (parse_incoming_twin_message(message, &correlation_id, &has_version, &version, &has_status_code, &status_code, &has_twin_report, &twin_report) != 0) |
AzureIoTClient | 56:8704100b3b54 | 1380 | { |
AzureIoTClient | 56:8704100b3b54 | 1381 | LogError("Failed parsing incoming TWIN message (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1382 | } |
AzureIoTClient | 56:8704100b3b54 | 1383 | else |
AzureIoTClient | 56:8704100b3b54 | 1384 | { |
AzureIoTClient | 56:8704100b3b54 | 1385 | if (correlation_id != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1386 | { |
AzureIoTClient | 56:8704100b3b54 | 1387 | // It is supposed to be a request sent previously (reported properties PATCH, GET, PUT or DELETE). |
AzureIoTClient | 39:e98d5df6dc74 | 1388 | |
AzureIoTClient | 56:8704100b3b54 | 1389 | LIST_ITEM_HANDLE list_item; |
AzureIoTClient | 56:8704100b3b54 | 1390 | if ((list_item = singlylinkedlist_find(twin_msgr->operations, find_twin_operation_by_correlation_id, (const void*)correlation_id)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1391 | { |
AzureIoTClient | 56:8704100b3b54 | 1392 | LogError("Could not find context of TWIN incoming message (%s, %s)", twin_msgr->device_id, correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 1393 | } |
AzureIoTClient | 56:8704100b3b54 | 1394 | else |
AzureIoTClient | 56:8704100b3b54 | 1395 | { |
AzureIoTClient | 56:8704100b3b54 | 1396 | TWIN_OPERATION_CONTEXT* twin_op_ctx; |
AzureIoTClient | 39:e98d5df6dc74 | 1397 | |
AzureIoTClient | 56:8704100b3b54 | 1398 | if ((twin_op_ctx = (TWIN_OPERATION_CONTEXT*)singlylinkedlist_item_get_value(list_item)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1399 | { |
AzureIoTClient | 56:8704100b3b54 | 1400 | LogError("Could not get context for incoming TWIN message (%s, %s)", twin_msgr->device_id, correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 1401 | } |
AzureIoTClient | 56:8704100b3b54 | 1402 | else |
AzureIoTClient | 56:8704100b3b54 | 1403 | { |
AzureIoTClient | 56:8704100b3b54 | 1404 | if (twin_op_ctx->type == TWIN_OPERATION_TYPE_PATCH) |
AzureIoTClient | 56:8704100b3b54 | 1405 | { |
AzureIoTClient | 56:8704100b3b54 | 1406 | if (!has_status_code) |
AzureIoTClient | 56:8704100b3b54 | 1407 | { |
AzureIoTClient | 56:8704100b3b54 | 1408 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_086: [If `message` is a failed response for a PATCH request, the `on_report_state_complete_callback` shall be invoked if provided passing RESULT_ERROR and the status_code zero] |
AzureIoTClient | 56:8704100b3b54 | 1409 | LogError("Received an incoming TWIN message for a PATCH operation, but with no status code (%s, %s)", twin_msgr->device_id, correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 1410 | |
AzureIoTClient | 56:8704100b3b54 | 1411 | disposition_result = AMQP_MESSENGER_DISPOSITION_RESULT_REJECTED; |
AzureIoTClient | 39:e98d5df6dc74 | 1412 | |
AzureIoTClient | 56:8704100b3b54 | 1413 | if (twin_op_ctx->on_report_state_complete_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1414 | { |
AzureIoTClient | 56:8704100b3b54 | 1415 | twin_op_ctx->on_report_state_complete_callback(TWIN_REPORT_STATE_RESULT_ERROR, TWIN_REPORT_STATE_REASON_INVALID_RESPONSE, 0, twin_op_ctx->on_report_state_complete_context); |
AzureIoTClient | 56:8704100b3b54 | 1416 | } |
AzureIoTClient | 56:8704100b3b54 | 1417 | } |
AzureIoTClient | 56:8704100b3b54 | 1418 | else |
AzureIoTClient | 56:8704100b3b54 | 1419 | { |
AzureIoTClient | 56:8704100b3b54 | 1420 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_085: [If `message` is a success response for a PATCH request, the `on_report_state_complete_callback` shall be invoked if provided passing RESULT_SUCCESS and the status_code received] |
AzureIoTClient | 56:8704100b3b54 | 1421 | if (twin_op_ctx->on_report_state_complete_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1422 | { |
AzureIoTClient | 56:8704100b3b54 | 1423 | twin_op_ctx->on_report_state_complete_callback(TWIN_REPORT_STATE_RESULT_SUCCESS, TWIN_REPORT_STATE_REASON_NONE, status_code, twin_op_ctx->on_report_state_complete_context); |
AzureIoTClient | 56:8704100b3b54 | 1424 | } |
AzureIoTClient | 56:8704100b3b54 | 1425 | } |
AzureIoTClient | 56:8704100b3b54 | 1426 | } |
AzureIoTClient | 56:8704100b3b54 | 1427 | else if (twin_op_ctx->type == TWIN_OPERATION_TYPE_GET) |
AzureIoTClient | 56:8704100b3b54 | 1428 | { |
AzureIoTClient | 56:8704100b3b54 | 1429 | if (!has_twin_report) |
AzureIoTClient | 56:8704100b3b54 | 1430 | { |
AzureIoTClient | 56:8704100b3b54 | 1431 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_089: [If `message` is a failed response for a GET request, the TWIN messenger shall attempt to send another GET request] |
AzureIoTClient | 56:8704100b3b54 | 1432 | LogError("Received an incoming TWIN message for a GET operation, but with no report (%s, %s)", twin_msgr->device_id, correlation_id); |
AzureIoTClient | 39:e98d5df6dc74 | 1433 | |
AzureIoTClient | 56:8704100b3b54 | 1434 | disposition_result = AMQP_MESSENGER_DISPOSITION_RESULT_REJECTED; |
AzureIoTClient | 39:e98d5df6dc74 | 1435 | |
AzureIoTClient | 56:8704100b3b54 | 1436 | if (twin_op_ctx->msgr->on_message_received_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1437 | { |
AzureIoTClient | 56:8704100b3b54 | 1438 | twin_op_ctx->msgr->on_message_received_callback(TWIN_UPDATE_TYPE_COMPLETE, NULL, 0, twin_op_ctx->msgr->on_message_received_context); |
AzureIoTClient | 56:8704100b3b54 | 1439 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1440 | |
AzureIoTClient | 56:8704100b3b54 | 1441 | if (twin_msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_GETTING_COMPLETE_PROPERTIES) |
AzureIoTClient | 56:8704100b3b54 | 1442 | { |
AzureIoTClient | 56:8704100b3b54 | 1443 | twin_msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_GET_COMPLETE_PROPERTIES; |
AzureIoTClient | 56:8704100b3b54 | 1444 | twin_msgr->subscription_error_count++; |
AzureIoTClient | 56:8704100b3b54 | 1445 | } |
AzureIoTClient | 56:8704100b3b54 | 1446 | } |
AzureIoTClient | 56:8704100b3b54 | 1447 | else |
AzureIoTClient | 56:8704100b3b54 | 1448 | { |
AzureIoTClient | 56:8704100b3b54 | 1449 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_087: [If `message` is a success response for a GET request, `on_message_received_callback` shall be invoked with TWIN_UPDATE_TYPE_COMPLETE and the message body received] |
AzureIoTClient | 56:8704100b3b54 | 1450 | if (twin_op_ctx->msgr->on_message_received_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1451 | { |
AzureIoTClient | 56:8704100b3b54 | 1452 | twin_op_ctx->msgr->on_message_received_callback(TWIN_UPDATE_TYPE_COMPLETE, (const char*)twin_report.bytes, twin_report.length, twin_op_ctx->msgr->on_message_received_context); |
AzureIoTClient | 56:8704100b3b54 | 1453 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1454 | |
AzureIoTClient | 56:8704100b3b54 | 1455 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_088: [If `message` is a success response for a GET request, the TWIN messenger shall trigger the subscription for partial updates] |
AzureIoTClient | 56:8704100b3b54 | 1456 | if (twin_msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_GETTING_COMPLETE_PROPERTIES) |
AzureIoTClient | 56:8704100b3b54 | 1457 | { |
AzureIoTClient | 56:8704100b3b54 | 1458 | twin_msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_SUBSCRIBE_FOR_UPDATES; |
AzureIoTClient | 56:8704100b3b54 | 1459 | twin_msgr->subscription_error_count = 0; |
AzureIoTClient | 56:8704100b3b54 | 1460 | } |
AzureIoTClient | 56:8704100b3b54 | 1461 | } |
AzureIoTClient | 56:8704100b3b54 | 1462 | } |
AzureIoTClient | 56:8704100b3b54 | 1463 | else if (twin_op_ctx->type == TWIN_OPERATION_TYPE_PUT) |
AzureIoTClient | 56:8704100b3b54 | 1464 | { |
AzureIoTClient | 56:8704100b3b54 | 1465 | if (twin_msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_SUBSCRIBED) |
AzureIoTClient | 56:8704100b3b54 | 1466 | { |
AzureIoTClient | 56:8704100b3b54 | 1467 | bool subscription_succeeded = true; |
AzureIoTClient | 56:8704100b3b54 | 1468 | |
AzureIoTClient | 56:8704100b3b54 | 1469 | if (!has_status_code) |
AzureIoTClient | 56:8704100b3b54 | 1470 | { |
AzureIoTClient | 56:8704100b3b54 | 1471 | LogError("Received an incoming TWIN message for a PUT operation, but with no status code (%s, %s)", twin_msgr->device_id, correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 1472 | |
AzureIoTClient | 56:8704100b3b54 | 1473 | subscription_succeeded = false; |
AzureIoTClient | 56:8704100b3b54 | 1474 | } |
AzureIoTClient | 56:8704100b3b54 | 1475 | else if (status_code < 200 || status_code >= 300) |
AzureIoTClient | 56:8704100b3b54 | 1476 | { |
AzureIoTClient | 56:8704100b3b54 | 1477 | LogError("Received status code %d for TWIN subscription request (%s, %s)", status_code, twin_msgr->device_id, correlation_id); |
AzureIoTClient | 39:e98d5df6dc74 | 1478 | |
AzureIoTClient | 56:8704100b3b54 | 1479 | subscription_succeeded = false; |
AzureIoTClient | 56:8704100b3b54 | 1480 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1481 | |
AzureIoTClient | 56:8704100b3b54 | 1482 | if (twin_msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_SUBSCRIBING) |
AzureIoTClient | 56:8704100b3b54 | 1483 | { |
AzureIoTClient | 56:8704100b3b54 | 1484 | if (subscription_succeeded) |
AzureIoTClient | 56:8704100b3b54 | 1485 | { |
AzureIoTClient | 56:8704100b3b54 | 1486 | twin_msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_SUBSCRIBED; |
AzureIoTClient | 56:8704100b3b54 | 1487 | twin_msgr->subscription_error_count = 0; |
AzureIoTClient | 56:8704100b3b54 | 1488 | } |
AzureIoTClient | 56:8704100b3b54 | 1489 | else |
AzureIoTClient | 56:8704100b3b54 | 1490 | { |
AzureIoTClient | 56:8704100b3b54 | 1491 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_090: [If `message` is a failed response for a PUT request, the TWIN messenger shall attempt to send another PUT request] |
AzureIoTClient | 56:8704100b3b54 | 1492 | twin_msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_SUBSCRIBE_FOR_UPDATES; |
AzureIoTClient | 56:8704100b3b54 | 1493 | twin_msgr->subscription_error_count++; |
AzureIoTClient | 56:8704100b3b54 | 1494 | } |
AzureIoTClient | 56:8704100b3b54 | 1495 | } |
AzureIoTClient | 56:8704100b3b54 | 1496 | } |
AzureIoTClient | 56:8704100b3b54 | 1497 | } |
AzureIoTClient | 56:8704100b3b54 | 1498 | else if (twin_op_ctx->type == TWIN_OPERATION_TYPE_DELETE) |
AzureIoTClient | 56:8704100b3b54 | 1499 | { |
AzureIoTClient | 56:8704100b3b54 | 1500 | if (twin_msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_NOT_SUBSCRIBED) |
AzureIoTClient | 56:8704100b3b54 | 1501 | { |
AzureIoTClient | 56:8704100b3b54 | 1502 | bool unsubscription_succeeded = true; |
AzureIoTClient | 56:8704100b3b54 | 1503 | |
AzureIoTClient | 56:8704100b3b54 | 1504 | if (!has_status_code) |
AzureIoTClient | 56:8704100b3b54 | 1505 | { |
AzureIoTClient | 56:8704100b3b54 | 1506 | LogError("Received an incoming TWIN message for a DELETE operation, but with no status code (%s, %s)", twin_msgr->device_id, correlation_id); |
AzureIoTClient | 39:e98d5df6dc74 | 1507 | |
AzureIoTClient | 56:8704100b3b54 | 1508 | unsubscription_succeeded = false; |
AzureIoTClient | 56:8704100b3b54 | 1509 | } |
AzureIoTClient | 56:8704100b3b54 | 1510 | else if (status_code < 200 || status_code >= 300) |
AzureIoTClient | 56:8704100b3b54 | 1511 | { |
AzureIoTClient | 56:8704100b3b54 | 1512 | LogError("Received status code %d for TWIN unsubscription request (%s, %s)", status_code, twin_msgr->device_id, correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 1513 | |
AzureIoTClient | 56:8704100b3b54 | 1514 | unsubscription_succeeded = false; |
AzureIoTClient | 56:8704100b3b54 | 1515 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1516 | |
AzureIoTClient | 56:8704100b3b54 | 1517 | if (twin_msgr->subscription_state == TWIN_SUBSCRIPTION_STATE_UNSUBSCRIBING) |
AzureIoTClient | 56:8704100b3b54 | 1518 | { |
AzureIoTClient | 56:8704100b3b54 | 1519 | if (unsubscription_succeeded) |
AzureIoTClient | 56:8704100b3b54 | 1520 | { |
AzureIoTClient | 56:8704100b3b54 | 1521 | twin_msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_NOT_SUBSCRIBED; |
AzureIoTClient | 56:8704100b3b54 | 1522 | twin_msgr->subscription_error_count = 0; |
AzureIoTClient | 56:8704100b3b54 | 1523 | } |
AzureIoTClient | 56:8704100b3b54 | 1524 | else |
AzureIoTClient | 56:8704100b3b54 | 1525 | { |
AzureIoTClient | 56:8704100b3b54 | 1526 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_091: [If `message` is a failed response for a DELETE request, the TWIN messenger shall attempt to send another DELETE request] |
AzureIoTClient | 56:8704100b3b54 | 1527 | twin_msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_UNSUBSCRIBE; |
AzureIoTClient | 56:8704100b3b54 | 1528 | twin_msgr->subscription_error_count++; |
AzureIoTClient | 56:8704100b3b54 | 1529 | } |
AzureIoTClient | 56:8704100b3b54 | 1530 | } |
AzureIoTClient | 56:8704100b3b54 | 1531 | } |
AzureIoTClient | 56:8704100b3b54 | 1532 | } |
AzureIoTClient | 56:8704100b3b54 | 1533 | |
AzureIoTClient | 56:8704100b3b54 | 1534 | destroy_twin_operation_context(twin_op_ctx); |
AzureIoTClient | 56:8704100b3b54 | 1535 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1536 | |
AzureIoTClient | 56:8704100b3b54 | 1537 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_092: [The corresponding TWIN request shall be removed from `twin_msgr->operations` and destroyed] |
AzureIoTClient | 56:8704100b3b54 | 1538 | if (singlylinkedlist_remove(twin_msgr->operations, list_item) != 0) |
AzureIoTClient | 56:8704100b3b54 | 1539 | { |
AzureIoTClient | 56:8704100b3b54 | 1540 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_093: [The corresponding TWIN request failed to be removed from `twin_msgr->operations`, `twin_msgr->state` shall be set to TWIN_MESSENGER_STATE_ERROR and informed to the user] |
AzureIoTClient | 56:8704100b3b54 | 1541 | LogError("Failed removing context for incoming TWIN message (%s, %s)", |
AzureIoTClient | 56:8704100b3b54 | 1542 | twin_msgr->device_id, correlation_id); |
AzureIoTClient | 39:e98d5df6dc74 | 1543 | |
AzureIoTClient | 56:8704100b3b54 | 1544 | update_state(twin_msgr, TWIN_MESSENGER_STATE_ERROR); |
AzureIoTClient | 56:8704100b3b54 | 1545 | } |
AzureIoTClient | 56:8704100b3b54 | 1546 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1547 | |
AzureIoTClient | 56:8704100b3b54 | 1548 | free(correlation_id); |
AzureIoTClient | 56:8704100b3b54 | 1549 | } |
AzureIoTClient | 56:8704100b3b54 | 1550 | else if (has_twin_report) |
AzureIoTClient | 56:8704100b3b54 | 1551 | { |
AzureIoTClient | 56:8704100b3b54 | 1552 | // It is supposed to be a desired properties delta update. |
AzureIoTClient | 39:e98d5df6dc74 | 1553 | |
AzureIoTClient | 56:8704100b3b54 | 1554 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_094: [If `message` is not a client request, `on_message_received_callback` shall be invoked with TWIN_UPDATE_TYPE_PARTIAL and the message body received] |
AzureIoTClient | 56:8704100b3b54 | 1555 | if (twin_msgr->on_message_received_callback != NULL) |
AzureIoTClient | 56:8704100b3b54 | 1556 | { |
AzureIoTClient | 56:8704100b3b54 | 1557 | twin_msgr->on_message_received_callback(TWIN_UPDATE_TYPE_PARTIAL, (const char*)twin_report.bytes, twin_report.length, twin_msgr->on_message_received_context); |
AzureIoTClient | 56:8704100b3b54 | 1558 | } |
AzureIoTClient | 56:8704100b3b54 | 1559 | } |
AzureIoTClient | 56:8704100b3b54 | 1560 | else |
AzureIoTClient | 56:8704100b3b54 | 1561 | { |
AzureIoTClient | 56:8704100b3b54 | 1562 | LogError("Received TWIN message with no correlation-id and no report (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1563 | } |
AzureIoTClient | 56:8704100b3b54 | 1564 | } |
AzureIoTClient | 56:8704100b3b54 | 1565 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1566 | |
AzureIoTClient | 56:8704100b3b54 | 1567 | return disposition_result; |
AzureIoTClient | 39:e98d5df6dc74 | 1568 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1569 | |
AzureIoTClient | 39:e98d5df6dc74 | 1570 | static void on_amqp_messenger_state_changed_callback(void* context, AMQP_MESSENGER_STATE previous_state, AMQP_MESSENGER_STATE new_state) |
AzureIoTClient | 39:e98d5df6dc74 | 1571 | { |
AzureIoTClient | 56:8704100b3b54 | 1572 | if (context == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1573 | { |
AzureIoTClient | 56:8704100b3b54 | 1574 | LogError("Invalid argument (context is NULL)"); |
AzureIoTClient | 56:8704100b3b54 | 1575 | } |
AzureIoTClient | 56:8704100b3b54 | 1576 | else if (new_state != previous_state) |
AzureIoTClient | 56:8704100b3b54 | 1577 | { |
AzureIoTClient | 56:8704100b3b54 | 1578 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)context; |
AzureIoTClient | 39:e98d5df6dc74 | 1579 | |
AzureIoTClient | 56:8704100b3b54 | 1580 | if (twin_msgr->state == TWIN_MESSENGER_STATE_STARTING && new_state == AMQP_MESSENGER_STATE_STARTED) |
AzureIoTClient | 56:8704100b3b54 | 1581 | { |
AzureIoTClient | 56:8704100b3b54 | 1582 | if (twin_msgr->amqp_msgr_is_subscribed) |
AzureIoTClient | 56:8704100b3b54 | 1583 | { |
AzureIoTClient | 56:8704100b3b54 | 1584 | update_state(twin_msgr, TWIN_MESSENGER_STATE_STARTED); |
AzureIoTClient | 56:8704100b3b54 | 1585 | } |
AzureIoTClient | 56:8704100b3b54 | 1586 | // Else, it shall wait for the moment the AMQP msgr is subscribed. |
AzureIoTClient | 56:8704100b3b54 | 1587 | } |
AzureIoTClient | 56:8704100b3b54 | 1588 | else if (twin_msgr->state == TWIN_MESSENGER_STATE_STOPPING && new_state == TWIN_MESSENGER_STATE_STOPPED) |
AzureIoTClient | 56:8704100b3b54 | 1589 | { |
AzureIoTClient | 56:8704100b3b54 | 1590 | if (!twin_msgr->amqp_msgr_is_subscribed) |
AzureIoTClient | 56:8704100b3b54 | 1591 | { |
AzureIoTClient | 56:8704100b3b54 | 1592 | update_state(twin_msgr, TWIN_MESSENGER_STATE_STOPPED); |
AzureIoTClient | 56:8704100b3b54 | 1593 | } |
AzureIoTClient | 56:8704100b3b54 | 1594 | // Else, it shall wait for the moment the AMQP msgr is unsubscribed. |
AzureIoTClient | 56:8704100b3b54 | 1595 | } |
AzureIoTClient | 56:8704100b3b54 | 1596 | else if ((twin_msgr->state == TWIN_MESSENGER_STATE_STARTING && new_state == AMQP_MESSENGER_STATE_STARTING) || |
AzureIoTClient | 56:8704100b3b54 | 1597 | (twin_msgr->state == TWIN_MESSENGER_STATE_STOPPING && new_state == AMQP_MESSENGER_STATE_STOPPING)) |
AzureIoTClient | 56:8704100b3b54 | 1598 | { |
AzureIoTClient | 56:8704100b3b54 | 1599 | // Do nothing, this is expected. |
AzureIoTClient | 56:8704100b3b54 | 1600 | } |
AzureIoTClient | 56:8704100b3b54 | 1601 | else |
AzureIoTClient | 56:8704100b3b54 | 1602 | { |
AzureIoTClient | 56:8704100b3b54 | 1603 | LogError("Unexpected AMQP messenger state (%s, %s, %s)", |
AzureIoTClient | 56:8704100b3b54 | 1604 | twin_msgr->device_id, ENUM_TO_STRING(TWIN_MESSENGER_STATE, twin_msgr->state), ENUM_TO_STRING(AMQP_MESSENGER_STATE, new_state)); |
AzureIoTClient | 39:e98d5df6dc74 | 1605 | |
AzureIoTClient | 56:8704100b3b54 | 1606 | update_state(twin_msgr, TWIN_MESSENGER_STATE_ERROR); |
AzureIoTClient | 56:8704100b3b54 | 1607 | } |
AzureIoTClient | 56:8704100b3b54 | 1608 | |
AzureIoTClient | 56:8704100b3b54 | 1609 | twin_msgr->amqp_msgr_state = new_state; |
AzureIoTClient | 56:8704100b3b54 | 1610 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1611 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1612 | |
AzureIoTClient | 39:e98d5df6dc74 | 1613 | static void on_amqp_messenger_subscription_changed_callback(void* context, bool is_subscribed) |
AzureIoTClient | 39:e98d5df6dc74 | 1614 | { |
AzureIoTClient | 56:8704100b3b54 | 1615 | if (context == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1616 | { |
AzureIoTClient | 56:8704100b3b54 | 1617 | LogError("Invalid argument (context is NULL)"); |
AzureIoTClient | 56:8704100b3b54 | 1618 | } |
AzureIoTClient | 56:8704100b3b54 | 1619 | else |
AzureIoTClient | 56:8704100b3b54 | 1620 | { |
AzureIoTClient | 56:8704100b3b54 | 1621 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)context; |
AzureIoTClient | 39:e98d5df6dc74 | 1622 | |
AzureIoTClient | 56:8704100b3b54 | 1623 | if (twin_msgr->state == TWIN_MESSENGER_STATE_STARTING && is_subscribed) |
AzureIoTClient | 56:8704100b3b54 | 1624 | { |
AzureIoTClient | 56:8704100b3b54 | 1625 | if (twin_msgr->amqp_msgr_state == AMQP_MESSENGER_STATE_STARTED) |
AzureIoTClient | 56:8704100b3b54 | 1626 | { |
AzureIoTClient | 56:8704100b3b54 | 1627 | update_state(twin_msgr, TWIN_MESSENGER_STATE_STARTED); |
AzureIoTClient | 56:8704100b3b54 | 1628 | } |
AzureIoTClient | 56:8704100b3b54 | 1629 | // Else, it shall wait for the moment the AMQP msgr is STARTED. |
AzureIoTClient | 56:8704100b3b54 | 1630 | } |
AzureIoTClient | 56:8704100b3b54 | 1631 | else if (twin_msgr->state == TWIN_MESSENGER_STATE_STOPPING && !is_subscribed) |
AzureIoTClient | 56:8704100b3b54 | 1632 | { |
AzureIoTClient | 56:8704100b3b54 | 1633 | if (twin_msgr->amqp_msgr_state == AMQP_MESSENGER_STATE_STOPPED) |
AzureIoTClient | 56:8704100b3b54 | 1634 | { |
AzureIoTClient | 56:8704100b3b54 | 1635 | update_state(twin_msgr, TWIN_MESSENGER_STATE_STOPPED); |
AzureIoTClient | 56:8704100b3b54 | 1636 | } |
AzureIoTClient | 56:8704100b3b54 | 1637 | // Else, it shall wait for the moment the AMQP msgr is STOPPED. |
AzureIoTClient | 56:8704100b3b54 | 1638 | } |
AzureIoTClient | 56:8704100b3b54 | 1639 | else |
AzureIoTClient | 56:8704100b3b54 | 1640 | { |
AzureIoTClient | 56:8704100b3b54 | 1641 | LogError("Unexpected AMQP messenger state (%s, %s, %d)", |
AzureIoTClient | 56:8704100b3b54 | 1642 | twin_msgr->device_id, ENUM_TO_STRING(TWIN_MESSENGER_STATE, twin_msgr->state), is_subscribed); |
AzureIoTClient | 39:e98d5df6dc74 | 1643 | |
AzureIoTClient | 56:8704100b3b54 | 1644 | update_state(twin_msgr, TWIN_MESSENGER_STATE_ERROR); |
AzureIoTClient | 56:8704100b3b54 | 1645 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1646 | |
AzureIoTClient | 56:8704100b3b54 | 1647 | twin_msgr->amqp_msgr_is_subscribed = is_subscribed; |
AzureIoTClient | 56:8704100b3b54 | 1648 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1649 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1650 | |
AzureIoTClient | 39:e98d5df6dc74 | 1651 | |
AzureIoTClient | 39:e98d5df6dc74 | 1652 | //---------- Public APIs ----------// |
AzureIoTClient | 39:e98d5df6dc74 | 1653 | |
AzureIoTClient | 39:e98d5df6dc74 | 1654 | TWIN_MESSENGER_HANDLE twin_messenger_create(const TWIN_MESSENGER_CONFIG* messenger_config) |
AzureIoTClient | 39:e98d5df6dc74 | 1655 | { |
AzureIoTClient | 56:8704100b3b54 | 1656 | TWIN_MESSENGER_INSTANCE* twin_msgr; |
AzureIoTClient | 39:e98d5df6dc74 | 1657 | |
AzureIoTClient | 56:8704100b3b54 | 1658 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_001: [If parameter `messenger_config` is NULL, twin_messenger_create() shall return NULL] |
AzureIoTClient | 56:8704100b3b54 | 1659 | if (messenger_config == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1660 | { |
AzureIoTClient | 56:8704100b3b54 | 1661 | LogError("Invalid argument (messenger_config is NULL)"); |
AzureIoTClient | 56:8704100b3b54 | 1662 | twin_msgr = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1663 | } |
AzureIoTClient | 56:8704100b3b54 | 1664 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_002: [If `messenger_config`'s `device_id`, `iothub_host_fqdn` or `client_version` is NULL, twin_messenger_create() shall return NULL] |
AzureIoTClient | 56:8704100b3b54 | 1665 | else if (messenger_config->device_id == NULL || messenger_config->iothub_host_fqdn == NULL || messenger_config->client_version == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1666 | { |
AzureIoTClient | 56:8704100b3b54 | 1667 | LogError("Invalid argument (device_id=%p, iothub_host_fqdn=%p, client_version=%p)", |
AzureIoTClient | 56:8704100b3b54 | 1668 | messenger_config->device_id, messenger_config->iothub_host_fqdn, messenger_config->client_version); |
AzureIoTClient | 56:8704100b3b54 | 1669 | twin_msgr = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1670 | } |
AzureIoTClient | 56:8704100b3b54 | 1671 | else |
AzureIoTClient | 56:8704100b3b54 | 1672 | { |
AzureIoTClient | 56:8704100b3b54 | 1673 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_003: [twin_messenger_create() shall allocate memory for the messenger instance structure (aka `twin_msgr`)] |
AzureIoTClient | 56:8704100b3b54 | 1674 | if ((twin_msgr = (TWIN_MESSENGER_INSTANCE*)malloc(sizeof(TWIN_MESSENGER_INSTANCE))) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1675 | { |
AzureIoTClient | 56:8704100b3b54 | 1676 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_004: [If malloc() fails, twin_messenger_create() shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 1677 | LogError("Failed allocating TWIN_MESSENGER_INSTANCE (%s)", messenger_config->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1678 | } |
AzureIoTClient | 56:8704100b3b54 | 1679 | else |
AzureIoTClient | 56:8704100b3b54 | 1680 | { |
AzureIoTClient | 56:8704100b3b54 | 1681 | MAP_HANDLE link_attach_properties; |
AzureIoTClient | 56:8704100b3b54 | 1682 | |
AzureIoTClient | 56:8704100b3b54 | 1683 | memset(twin_msgr, 0, sizeof(TWIN_MESSENGER_INSTANCE)); |
AzureIoTClient | 56:8704100b3b54 | 1684 | twin_msgr->state = TWIN_MESSENGER_STATE_STOPPED; |
AzureIoTClient | 56:8704100b3b54 | 1685 | twin_msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_NOT_SUBSCRIBED; |
AzureIoTClient | 56:8704100b3b54 | 1686 | twin_msgr->amqp_msgr_state = AMQP_MESSENGER_STATE_STOPPED; |
AzureIoTClient | 39:e98d5df6dc74 | 1687 | |
AzureIoTClient | 56:8704100b3b54 | 1688 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_005: [twin_messenger_create() shall save a copy of `messenger_config` info into `twin_msgr`] |
AzureIoTClient | 56:8704100b3b54 | 1689 | if (mallocAndStrcpy_s(&twin_msgr->client_version, messenger_config->client_version) != 0) |
AzureIoTClient | 56:8704100b3b54 | 1690 | { |
AzureIoTClient | 56:8704100b3b54 | 1691 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_006: [If any `messenger_config` info fails to be copied, twin_messenger_create() shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 1692 | LogError("Failed copying client_version (%s)", messenger_config->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1693 | internal_twin_messenger_destroy(twin_msgr); |
AzureIoTClient | 56:8704100b3b54 | 1694 | twin_msgr = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1695 | } |
AzureIoTClient | 56:8704100b3b54 | 1696 | else if (mallocAndStrcpy_s(&twin_msgr->device_id, messenger_config->device_id) != 0) |
AzureIoTClient | 56:8704100b3b54 | 1697 | { |
AzureIoTClient | 56:8704100b3b54 | 1698 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_006: [If any `messenger_config` info fails to be copied, twin_messenger_create() shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 1699 | LogError("Failed copying device_id (%s)", messenger_config->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1700 | internal_twin_messenger_destroy(twin_msgr); |
AzureIoTClient | 56:8704100b3b54 | 1701 | twin_msgr = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1702 | } |
AzureIoTClient | 56:8704100b3b54 | 1703 | else if ((messenger_config->module_id != NULL) && (mallocAndStrcpy_s(&twin_msgr->module_id, messenger_config->module_id) != 0)) |
AzureIoTClient | 56:8704100b3b54 | 1704 | { |
AzureIoTClient | 56:8704100b3b54 | 1705 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_006: [If any `messenger_config` info fails to be copied, twin_messenger_create() shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 1706 | LogError("Failed copying module_id (%s)", messenger_config->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1707 | internal_twin_messenger_destroy(twin_msgr); |
AzureIoTClient | 56:8704100b3b54 | 1708 | twin_msgr = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1709 | } |
AzureIoTClient | 56:8704100b3b54 | 1710 | else if (mallocAndStrcpy_s(&twin_msgr->iothub_host_fqdn, messenger_config->iothub_host_fqdn) != 0) |
AzureIoTClient | 56:8704100b3b54 | 1711 | { |
AzureIoTClient | 56:8704100b3b54 | 1712 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_006: [If any `messenger_config` info fails to be copied, twin_messenger_create() shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 1713 | LogError("Failed copying iothub_host_fqdn (%s)", messenger_config->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1714 | internal_twin_messenger_destroy(twin_msgr); |
AzureIoTClient | 56:8704100b3b54 | 1715 | twin_msgr = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1716 | } |
AzureIoTClient | 56:8704100b3b54 | 1717 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_007: [`twin_msgr->pending_patches` shall be set using singlylinkedlist_create()] |
AzureIoTClient | 56:8704100b3b54 | 1718 | else if ((twin_msgr->pending_patches = singlylinkedlist_create()) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1719 | { |
AzureIoTClient | 56:8704100b3b54 | 1720 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_008: [If singlylinkedlist_create() fails, twin_messenger_create() shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 1721 | LogError("Failed creating list for queueing patches (%s)", messenger_config->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1722 | internal_twin_messenger_destroy(twin_msgr); |
AzureIoTClient | 56:8704100b3b54 | 1723 | twin_msgr = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1724 | } |
AzureIoTClient | 56:8704100b3b54 | 1725 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_009: [`twin_msgr->operations` shall be set using singlylinkedlist_create()] |
AzureIoTClient | 56:8704100b3b54 | 1726 | else if ((twin_msgr->operations = singlylinkedlist_create()) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1727 | { |
AzureIoTClient | 56:8704100b3b54 | 1728 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_010: [If singlylinkedlist_create() fails, twin_messenger_create() shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 1729 | LogError("Failed creating list for operations (%s)", messenger_config->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1730 | internal_twin_messenger_destroy(twin_msgr); |
AzureIoTClient | 56:8704100b3b54 | 1731 | twin_msgr = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1732 | } |
AzureIoTClient | 56:8704100b3b54 | 1733 | else if ((link_attach_properties = create_link_attach_properties(twin_msgr)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1734 | { |
AzureIoTClient | 56:8704100b3b54 | 1735 | LogError("Failed creating link attach properties (%s)", messenger_config->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1736 | internal_twin_messenger_destroy(twin_msgr); |
AzureIoTClient | 56:8704100b3b54 | 1737 | twin_msgr = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1738 | } |
AzureIoTClient | 56:8704100b3b54 | 1739 | else |
AzureIoTClient | 56:8704100b3b54 | 1740 | { |
AzureIoTClient | 39:e98d5df6dc74 | 1741 | |
AzureIoTClient | 56:8704100b3b54 | 1742 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_012: [`amqp_msgr_config->client_version` shall be set with `twin_msgr->client_version`] |
AzureIoTClient | 56:8704100b3b54 | 1743 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_013: [`amqp_msgr_config->device_id` shall be set with `twin_msgr->device_id`] |
AzureIoTClient | 56:8704100b3b54 | 1744 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_014: [`amqp_msgr_config->iothub_host_fqdn` shall be set with `twin_msgr->iothub_host_fqdn`] |
AzureIoTClient | 56:8704100b3b54 | 1745 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_015: [`amqp_msgr_config` shall have "twin/" as send link target suffix and receive link source suffix] |
AzureIoTClient | 56:8704100b3b54 | 1746 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_016: [`amqp_msgr_config` shall have send and receive link attach properties set as "com.microsoft:client-version" = `twin_msgr->client_version`, "com.microsoft:channel-correlation-id" = `twin:<UUID>`, "com.microsoft:api-version" = "2016-11-14"] |
AzureIoTClient | 56:8704100b3b54 | 1747 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_017: [`amqp_msgr_config` shall be set with `on_amqp_messenger_state_changed_callback` and `on_amqp_messenger_subscription_changed_callback` callbacks] |
AzureIoTClient | 56:8704100b3b54 | 1748 | AMQP_MESSENGER_CONFIG amqp_msgr_config; |
AzureIoTClient | 56:8704100b3b54 | 1749 | amqp_msgr_config.client_version = twin_msgr->client_version; |
AzureIoTClient | 56:8704100b3b54 | 1750 | amqp_msgr_config.device_id = twin_msgr->device_id; |
AzureIoTClient | 56:8704100b3b54 | 1751 | amqp_msgr_config.module_id = twin_msgr->module_id; |
AzureIoTClient | 56:8704100b3b54 | 1752 | amqp_msgr_config.iothub_host_fqdn = twin_msgr->iothub_host_fqdn; |
AzureIoTClient | 56:8704100b3b54 | 1753 | amqp_msgr_config.send_link.target_suffix = DEFAULT_TWIN_SEND_LINK_SOURCE_NAME; |
AzureIoTClient | 56:8704100b3b54 | 1754 | amqp_msgr_config.send_link.attach_properties = link_attach_properties; |
AzureIoTClient | 56:8704100b3b54 | 1755 | amqp_msgr_config.send_link.snd_settle_mode = sender_settle_mode_settled; |
AzureIoTClient | 56:8704100b3b54 | 1756 | amqp_msgr_config.send_link.rcv_settle_mode = receiver_settle_mode_first; |
AzureIoTClient | 56:8704100b3b54 | 1757 | amqp_msgr_config.receive_link.source_suffix = DEFAULT_TWIN_RECEIVE_LINK_TARGET_NAME; |
AzureIoTClient | 56:8704100b3b54 | 1758 | amqp_msgr_config.receive_link.attach_properties = link_attach_properties; |
AzureIoTClient | 56:8704100b3b54 | 1759 | amqp_msgr_config.receive_link.snd_settle_mode = sender_settle_mode_settled; |
AzureIoTClient | 56:8704100b3b54 | 1760 | amqp_msgr_config.receive_link.rcv_settle_mode = receiver_settle_mode_first; |
AzureIoTClient | 56:8704100b3b54 | 1761 | amqp_msgr_config.on_state_changed_callback = on_amqp_messenger_state_changed_callback; |
AzureIoTClient | 56:8704100b3b54 | 1762 | amqp_msgr_config.on_state_changed_context = (void*)twin_msgr; |
AzureIoTClient | 56:8704100b3b54 | 1763 | amqp_msgr_config.on_subscription_changed_callback = on_amqp_messenger_subscription_changed_callback; |
AzureIoTClient | 56:8704100b3b54 | 1764 | amqp_msgr_config.on_subscription_changed_context = (void*)twin_msgr; |
AzureIoTClient | 39:e98d5df6dc74 | 1765 | |
AzureIoTClient | 56:8704100b3b54 | 1766 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_011: [`twin_msgr->amqp_msgr` shall be set using amqp_messenger_create(), passing a AMQP_MESSENGER_CONFIG instance `amqp_msgr_config`] |
AzureIoTClient | 56:8704100b3b54 | 1767 | if ((twin_msgr->amqp_msgr = amqp_messenger_create(&amqp_msgr_config)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1768 | { |
AzureIoTClient | 56:8704100b3b54 | 1769 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_018: [If amqp_messenger_create() fails, twin_messenger_create() shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 1770 | LogError("Failed creating the AMQP messenger (%s)", messenger_config->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1771 | internal_twin_messenger_destroy(twin_msgr); |
AzureIoTClient | 56:8704100b3b54 | 1772 | twin_msgr = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1773 | } |
AzureIoTClient | 56:8704100b3b54 | 1774 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_019: [`twin_msgr->amqp_msgr` shall subscribe for AMQP messages by calling amqp_messenger_subscribe_for_messages() passing `on_amqp_message_received`] |
AzureIoTClient | 56:8704100b3b54 | 1775 | else if (amqp_messenger_subscribe_for_messages(twin_msgr->amqp_msgr, on_amqp_message_received_callback, (void*)twin_msgr)) |
AzureIoTClient | 56:8704100b3b54 | 1776 | { |
AzureIoTClient | 56:8704100b3b54 | 1777 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_020: [If amqp_messenger_subscribe_for_messages() fails, twin_messenger_create() shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 1778 | LogError("Failed subscribing for AMQP messages (%s)", messenger_config->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1779 | internal_twin_messenger_destroy(twin_msgr); |
AzureIoTClient | 56:8704100b3b54 | 1780 | twin_msgr = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1781 | } |
AzureIoTClient | 56:8704100b3b54 | 1782 | else |
AzureIoTClient | 56:8704100b3b54 | 1783 | { |
AzureIoTClient | 56:8704100b3b54 | 1784 | // Codes_SRS_IOTHUBTRANSPORT_TWIN_MESSENGER_09_013: [`messenger_config->on_state_changed_callback` shall be saved into `twin_msgr->on_state_changed_callback`] |
AzureIoTClient | 56:8704100b3b54 | 1785 | twin_msgr->on_state_changed_callback = messenger_config->on_state_changed_callback; |
AzureIoTClient | 39:e98d5df6dc74 | 1786 | |
AzureIoTClient | 56:8704100b3b54 | 1787 | // Codes_SRS_IOTHUBTRANSPORT_TWIN_MESSENGER_09_014: [`messenger_config->on_state_changed_context` shall be saved into `twin_msgr->on_state_changed_context`] |
AzureIoTClient | 56:8704100b3b54 | 1788 | twin_msgr->on_state_changed_context = messenger_config->on_state_changed_context; |
AzureIoTClient | 56:8704100b3b54 | 1789 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1790 | |
AzureIoTClient | 56:8704100b3b54 | 1791 | destroy_link_attach_properties(link_attach_properties); |
AzureIoTClient | 56:8704100b3b54 | 1792 | } |
AzureIoTClient | 56:8704100b3b54 | 1793 | } |
AzureIoTClient | 56:8704100b3b54 | 1794 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1795 | |
AzureIoTClient | 56:8704100b3b54 | 1796 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_021: [If no failures occurr, twin_messenger_create() shall return a handle to `twin_msgr`] |
AzureIoTClient | 56:8704100b3b54 | 1797 | return (TWIN_MESSENGER_HANDLE)twin_msgr; |
AzureIoTClient | 39:e98d5df6dc74 | 1798 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1799 | |
AzureIoTClient | 39:e98d5df6dc74 | 1800 | int twin_messenger_report_state_async(TWIN_MESSENGER_HANDLE twin_msgr_handle, CONSTBUFFER_HANDLE data, TWIN_MESSENGER_REPORT_STATE_COMPLETE_CALLBACK on_report_state_complete_callback, const void* context) |
AzureIoTClient | 39:e98d5df6dc74 | 1801 | { |
AzureIoTClient | 56:8704100b3b54 | 1802 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 1803 | |
AzureIoTClient | 56:8704100b3b54 | 1804 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_022: [If `twin_msgr_handle` or `data` are NULL, twin_messenger_report_state_async() shall fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 1805 | if (twin_msgr_handle == NULL || data == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1806 | { |
AzureIoTClient | 56:8704100b3b54 | 1807 | LogError("Invalid argument (twin_msgr_handle=%p, data=%p)", twin_msgr_handle, data); |
AzureIoTClient | 56:8704100b3b54 | 1808 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 1809 | } |
AzureIoTClient | 56:8704100b3b54 | 1810 | else |
AzureIoTClient | 56:8704100b3b54 | 1811 | { |
AzureIoTClient | 56:8704100b3b54 | 1812 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)twin_msgr_handle; |
AzureIoTClient | 56:8704100b3b54 | 1813 | TWIN_PATCH_OPERATION_CONTEXT* twin_patch_ctx; |
AzureIoTClient | 39:e98d5df6dc74 | 1814 | |
AzureIoTClient | 56:8704100b3b54 | 1815 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_023: [twin_messenger_report_state_async() shall allocate memory for a TWIN_PATCH_OPERATION_CONTEXT structure (aka `twin_op_ctx`)] |
AzureIoTClient | 56:8704100b3b54 | 1816 | if ((twin_patch_ctx = (TWIN_PATCH_OPERATION_CONTEXT*)malloc(sizeof(TWIN_PATCH_OPERATION_CONTEXT))) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1817 | { |
AzureIoTClient | 56:8704100b3b54 | 1818 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_024: [If malloc() fails, twin_messenger_report_state_async() shall fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 1819 | LogError("Failed creating context for sending reported state (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1820 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 1821 | } |
AzureIoTClient | 56:8704100b3b54 | 1822 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_025: [`twin_op_ctx` shall have a copy of `data`] |
AzureIoTClient | 56:8704100b3b54 | 1823 | else if ((twin_patch_ctx->data = CONSTBUFFER_Clone(data)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1824 | { |
AzureIoTClient | 56:8704100b3b54 | 1825 | LogError("Failed cloning TWIN patch request data (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1826 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_031: [If any failure occurs, twin_messenger_report_state_async() shall free any memory it has allocated] |
AzureIoTClient | 56:8704100b3b54 | 1827 | free(twin_patch_ctx); |
AzureIoTClient | 56:8704100b3b54 | 1828 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_026: [If `data` fails to be copied, twin_messenger_report_state_async() shall fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 1829 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 1830 | } |
AzureIoTClient | 56:8704100b3b54 | 1831 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_027: [`twin_op_ctx->time_enqueued` shall be set using get_time] |
AzureIoTClient | 56:8704100b3b54 | 1832 | else if ((twin_patch_ctx->time_enqueued = get_time(NULL)) == INDEFINITE_TIME) |
AzureIoTClient | 56:8704100b3b54 | 1833 | { |
AzureIoTClient | 56:8704100b3b54 | 1834 | LogError("Failed setting reported state enqueue time (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1835 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_031: [If any failure occurs, twin_messenger_report_state_async() shall free any memory it has allocated] |
AzureIoTClient | 56:8704100b3b54 | 1836 | CONSTBUFFER_Destroy(twin_patch_ctx->data); |
AzureIoTClient | 56:8704100b3b54 | 1837 | free(twin_patch_ctx); |
AzureIoTClient | 56:8704100b3b54 | 1838 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_028: [If `twin_op_ctx->time_enqueued` fails to be set, twin_messenger_report_state_async() shall fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 1839 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 1840 | } |
AzureIoTClient | 56:8704100b3b54 | 1841 | else |
AzureIoTClient | 56:8704100b3b54 | 1842 | { |
AzureIoTClient | 56:8704100b3b54 | 1843 | twin_patch_ctx->on_report_state_complete_callback = on_report_state_complete_callback; |
AzureIoTClient | 56:8704100b3b54 | 1844 | twin_patch_ctx->on_report_state_complete_context = context; |
AzureIoTClient | 39:e98d5df6dc74 | 1845 | |
AzureIoTClient | 56:8704100b3b54 | 1846 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_029: [`twin_op_ctx` shall be added to `twin_msgr->pending_patches` using singlylinkedlist_add()] |
AzureIoTClient | 56:8704100b3b54 | 1847 | if (singlylinkedlist_add(twin_msgr->pending_patches, twin_patch_ctx) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1848 | { |
AzureIoTClient | 56:8704100b3b54 | 1849 | LogError("Failed adding TWIN patch request to queue (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1850 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_031: [If any failure occurs, twin_messenger_report_state_async() shall free any memory it has allocated] |
AzureIoTClient | 56:8704100b3b54 | 1851 | CONSTBUFFER_Destroy(twin_patch_ctx->data); |
AzureIoTClient | 56:8704100b3b54 | 1852 | free(twin_patch_ctx); |
AzureIoTClient | 56:8704100b3b54 | 1853 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_030: [If singlylinkedlist_add() fails, twin_messenger_report_state_async() shall fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 1854 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 1855 | } |
AzureIoTClient | 56:8704100b3b54 | 1856 | else |
AzureIoTClient | 56:8704100b3b54 | 1857 | { |
AzureIoTClient | 56:8704100b3b54 | 1858 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_032: [If no failures occur, twin_messenger_report_state_async() shall return zero] |
AzureIoTClient | 56:8704100b3b54 | 1859 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 1860 | } |
AzureIoTClient | 56:8704100b3b54 | 1861 | } |
AzureIoTClient | 56:8704100b3b54 | 1862 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1863 | |
AzureIoTClient | 56:8704100b3b54 | 1864 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 1865 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1866 | |
AzureIoTClient | 39:e98d5df6dc74 | 1867 | int twin_messenger_subscribe(TWIN_MESSENGER_HANDLE twin_msgr_handle, TWIN_STATE_UPDATE_CALLBACK on_twin_state_update_callback, void* context) |
AzureIoTClient | 39:e98d5df6dc74 | 1868 | { |
AzureIoTClient | 56:8704100b3b54 | 1869 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 1870 | |
AzureIoTClient | 56:8704100b3b54 | 1871 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_037: [If `twin_msgr_handle` or `on_twin_state_update_callback` are NULL, twin_messenger_subscribe() shall fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 1872 | if (twin_msgr_handle == NULL || on_twin_state_update_callback == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1873 | { |
AzureIoTClient | 56:8704100b3b54 | 1874 | LogError("Invalid argument (twin_msgr_handle=%p, on_twin_state_update_callback=%p)", twin_msgr_handle, on_twin_state_update_callback); |
AzureIoTClient | 56:8704100b3b54 | 1875 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 1876 | } |
AzureIoTClient | 56:8704100b3b54 | 1877 | else |
AzureIoTClient | 56:8704100b3b54 | 1878 | { |
AzureIoTClient | 56:8704100b3b54 | 1879 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)twin_msgr_handle; |
AzureIoTClient | 39:e98d5df6dc74 | 1880 | |
AzureIoTClient | 56:8704100b3b54 | 1881 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_038: [If `twin_msgr` is already subscribed, twin_messenger_subscribe() shall return zero] |
AzureIoTClient | 56:8704100b3b54 | 1882 | if (twin_msgr->subscription_state != TWIN_SUBSCRIPTION_STATE_NOT_SUBSCRIBED) |
AzureIoTClient | 56:8704100b3b54 | 1883 | { |
AzureIoTClient | 56:8704100b3b54 | 1884 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 1885 | } |
AzureIoTClient | 56:8704100b3b54 | 1886 | else |
AzureIoTClient | 56:8704100b3b54 | 1887 | { |
AzureIoTClient | 56:8704100b3b54 | 1888 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_039: [`on_twin_state_update_callback` and `context` shall be saved on `twin_msgr`] |
AzureIoTClient | 56:8704100b3b54 | 1889 | twin_msgr->on_message_received_callback = on_twin_state_update_callback; |
AzureIoTClient | 56:8704100b3b54 | 1890 | twin_msgr->on_message_received_context = context; |
AzureIoTClient | 56:8704100b3b54 | 1891 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_040: [twin_messenger_subscribe() shall change `twin_msgr->subscription_state` to TWIN_SUBSCRIPTION_STATE_GET_COMPLETE_PROPERTIES] |
AzureIoTClient | 56:8704100b3b54 | 1892 | twin_msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_GET_COMPLETE_PROPERTIES; |
AzureIoTClient | 56:8704100b3b54 | 1893 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_041: [If no failures occurr, twin_messenger_subscribe() shall return 0] |
AzureIoTClient | 56:8704100b3b54 | 1894 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 1895 | } |
AzureIoTClient | 56:8704100b3b54 | 1896 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1897 | |
AzureIoTClient | 56:8704100b3b54 | 1898 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 1899 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1900 | |
AzureIoTClient | 39:e98d5df6dc74 | 1901 | int twin_messenger_unsubscribe(TWIN_MESSENGER_HANDLE twin_msgr_handle) |
AzureIoTClient | 39:e98d5df6dc74 | 1902 | { |
AzureIoTClient | 56:8704100b3b54 | 1903 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 1904 | |
AzureIoTClient | 56:8704100b3b54 | 1905 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_042: [If `twin_msgr_handle` is NULL, twin_messenger_unsubscribe() shall fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 1906 | if (twin_msgr_handle == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1907 | { |
AzureIoTClient | 56:8704100b3b54 | 1908 | LogError("Invalid argument (twin_msgr_handle is NULL)"); |
AzureIoTClient | 56:8704100b3b54 | 1909 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 1910 | } |
AzureIoTClient | 56:8704100b3b54 | 1911 | else |
AzureIoTClient | 56:8704100b3b54 | 1912 | { |
AzureIoTClient | 56:8704100b3b54 | 1913 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)twin_msgr_handle; |
AzureIoTClient | 56:8704100b3b54 | 1914 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_043: [twin_messenger_subscribe() shall change `twin_msgr->subscription_state` to TWIN_SUBSCRIPTION_STATE_UNSUBSCRIBE] |
AzureIoTClient | 56:8704100b3b54 | 1915 | twin_msgr->subscription_state = TWIN_SUBSCRIPTION_STATE_UNSUBSCRIBE; |
AzureIoTClient | 56:8704100b3b54 | 1916 | twin_msgr->on_message_received_callback = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1917 | twin_msgr->on_message_received_context = NULL; |
AzureIoTClient | 56:8704100b3b54 | 1918 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_044: [If no failures occurr, twin_messenger_unsubscribe() shall return zero] |
AzureIoTClient | 56:8704100b3b54 | 1919 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 1920 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1921 | |
AzureIoTClient | 56:8704100b3b54 | 1922 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 1923 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1924 | |
AzureIoTClient | 39:e98d5df6dc74 | 1925 | int twin_messenger_get_send_status(TWIN_MESSENGER_HANDLE twin_msgr_handle, TWIN_MESSENGER_SEND_STATUS* send_status) |
AzureIoTClient | 39:e98d5df6dc74 | 1926 | { |
AzureIoTClient | 56:8704100b3b54 | 1927 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 1928 | |
AzureIoTClient | 56:8704100b3b54 | 1929 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_033: [If `twin_msgr_handle` or `send_status` are NULL, twin_messenger_get_send_status() shall fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 1930 | if (twin_msgr_handle == NULL || send_status == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1931 | { |
AzureIoTClient | 56:8704100b3b54 | 1932 | LogError("Invalid argument (twin_msgr_handle=%p, send_status=%p)", twin_msgr_handle, send_status); |
AzureIoTClient | 56:8704100b3b54 | 1933 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 1934 | } |
AzureIoTClient | 56:8704100b3b54 | 1935 | else |
AzureIoTClient | 56:8704100b3b54 | 1936 | { |
AzureIoTClient | 56:8704100b3b54 | 1937 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)twin_msgr_handle; |
AzureIoTClient | 56:8704100b3b54 | 1938 | TWIN_OPERATION_TYPE twin_op_type = TWIN_OPERATION_TYPE_PATCH; |
AzureIoTClient | 39:e98d5df6dc74 | 1939 | |
AzureIoTClient | 56:8704100b3b54 | 1940 | if (singlylinkedlist_get_head_item(twin_msgr->pending_patches) != NULL || |
AzureIoTClient | 56:8704100b3b54 | 1941 | singlylinkedlist_find(twin_msgr->operations, find_twin_operation_by_type, &twin_op_type)) |
AzureIoTClient | 56:8704100b3b54 | 1942 | { |
AzureIoTClient | 56:8704100b3b54 | 1943 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_034: [If `twin_msgr->pending_patches` or `twin_msgr->operations` have any TWIN patch requests, send_status shall be set to TWIN_MESSENGER_SEND_STATUS_BUSY] |
AzureIoTClient | 56:8704100b3b54 | 1944 | *send_status = TWIN_MESSENGER_SEND_STATUS_BUSY; |
AzureIoTClient | 56:8704100b3b54 | 1945 | } |
AzureIoTClient | 56:8704100b3b54 | 1946 | else |
AzureIoTClient | 56:8704100b3b54 | 1947 | { |
AzureIoTClient | 56:8704100b3b54 | 1948 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_035: [Otherwise, send_status shall be set to TWIN_MESSENGER_SEND_STATUS_IDLE] |
AzureIoTClient | 56:8704100b3b54 | 1949 | *send_status = TWIN_MESSENGER_SEND_STATUS_IDLE; |
AzureIoTClient | 56:8704100b3b54 | 1950 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1951 | |
AzureIoTClient | 56:8704100b3b54 | 1952 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_036: [If no failures occur, twin_messenger_get_send_status() shall return 0] |
AzureIoTClient | 56:8704100b3b54 | 1953 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 1954 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1955 | |
AzureIoTClient | 56:8704100b3b54 | 1956 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 1957 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1958 | |
AzureIoTClient | 39:e98d5df6dc74 | 1959 | int twin_messenger_start(TWIN_MESSENGER_HANDLE twin_msgr_handle, SESSION_HANDLE session_handle) |
AzureIoTClient | 39:e98d5df6dc74 | 1960 | { |
AzureIoTClient | 56:8704100b3b54 | 1961 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 1962 | |
AzureIoTClient | 56:8704100b3b54 | 1963 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_045: [If `twin_msgr_handle` or `session_handle` are NULL, twin_messenger_start() shall fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 1964 | if (twin_msgr_handle == NULL || session_handle == NULL) |
AzureIoTClient | 56:8704100b3b54 | 1965 | { |
AzureIoTClient | 56:8704100b3b54 | 1966 | LogError("Invalid argument (twin_msgr_handle=%p, session_handle=%p)", twin_msgr_handle, session_handle); |
AzureIoTClient | 56:8704100b3b54 | 1967 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 1968 | } |
AzureIoTClient | 56:8704100b3b54 | 1969 | else |
AzureIoTClient | 56:8704100b3b54 | 1970 | { |
AzureIoTClient | 56:8704100b3b54 | 1971 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)twin_msgr_handle; |
AzureIoTClient | 39:e98d5df6dc74 | 1972 | |
AzureIoTClient | 56:8704100b3b54 | 1973 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_048: [If no failures occurr, `twin_msgr->state` shall be set to TWIN_MESSENGER_STATE_STARTING, and `twin_msgr->on_state_changed_callback` invoked if provided] |
AzureIoTClient | 56:8704100b3b54 | 1974 | update_state(twin_msgr, TWIN_MESSENGER_STATE_STARTING); |
AzureIoTClient | 39:e98d5df6dc74 | 1975 | |
AzureIoTClient | 56:8704100b3b54 | 1976 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_046: [amqp_messenger_start() shall be invoked passing `twin_msgr->amqp_msgr` and `session_handle`] |
AzureIoTClient | 56:8704100b3b54 | 1977 | if (amqp_messenger_start(twin_msgr->amqp_msgr, session_handle) != 0) |
AzureIoTClient | 56:8704100b3b54 | 1978 | { |
AzureIoTClient | 56:8704100b3b54 | 1979 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_047: [If amqp_messenger_start() fails, twin_messenger_start() fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 1980 | LogError("Failed starting the AMQP messenger (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 1981 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_049: [If any failures occurr, `twin_msgr->state` shall be set to TWIN_MESSENGER_STATE_ERROR, and `twin_msgr->on_state_changed_callback` invoked if provided] |
AzureIoTClient | 56:8704100b3b54 | 1982 | update_state(twin_msgr, TWIN_MESSENGER_STATE_ERROR); |
AzureIoTClient | 56:8704100b3b54 | 1983 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 1984 | } |
AzureIoTClient | 56:8704100b3b54 | 1985 | else |
AzureIoTClient | 56:8704100b3b54 | 1986 | { |
AzureIoTClient | 56:8704100b3b54 | 1987 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_050: [If no failures occurr, twin_messenger_start() shall return 0] |
AzureIoTClient | 56:8704100b3b54 | 1988 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 1989 | } |
AzureIoTClient | 56:8704100b3b54 | 1990 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1991 | |
AzureIoTClient | 56:8704100b3b54 | 1992 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 1993 | } |
AzureIoTClient | 39:e98d5df6dc74 | 1994 | |
AzureIoTClient | 39:e98d5df6dc74 | 1995 | int twin_messenger_stop(TWIN_MESSENGER_HANDLE twin_msgr_handle) |
AzureIoTClient | 39:e98d5df6dc74 | 1996 | { |
AzureIoTClient | 56:8704100b3b54 | 1997 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 1998 | |
AzureIoTClient | 56:8704100b3b54 | 1999 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_051: [If `twin_msgr_handle` is NULL, twin_messenger_stop() shall fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 2000 | if (twin_msgr_handle == NULL) |
AzureIoTClient | 56:8704100b3b54 | 2001 | { |
AzureIoTClient | 56:8704100b3b54 | 2002 | LogError("Invalid argument (twin_msgr_handle is NULL)"); |
AzureIoTClient | 56:8704100b3b54 | 2003 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 2004 | } |
AzureIoTClient | 56:8704100b3b54 | 2005 | else |
AzureIoTClient | 56:8704100b3b54 | 2006 | { |
AzureIoTClient | 56:8704100b3b54 | 2007 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)twin_msgr_handle; |
AzureIoTClient | 39:e98d5df6dc74 | 2008 | |
AzureIoTClient | 56:8704100b3b54 | 2009 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_054: [`twin_msgr->state` shall be set to TWIN_MESSENGER_STATE_STOPPING, and `twin_msgr->on_state_changed_callback` invoked if provided] |
AzureIoTClient | 56:8704100b3b54 | 2010 | update_state(twin_msgr, TWIN_MESSENGER_STATE_STOPPING); |
AzureIoTClient | 39:e98d5df6dc74 | 2011 | |
AzureIoTClient | 56:8704100b3b54 | 2012 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_052: [amqp_messenger_stop() shall be invoked passing `twin_msgr->amqp_msgr`] |
AzureIoTClient | 56:8704100b3b54 | 2013 | if (amqp_messenger_stop(twin_msgr->amqp_msgr) != 0) |
AzureIoTClient | 56:8704100b3b54 | 2014 | { |
AzureIoTClient | 56:8704100b3b54 | 2015 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_053: [If amqp_messenger_stop() fails, twin_messenger_stop() fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 2016 | LogError("Failed stopping the AMQP messenger (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 2017 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_055: [If any failures occurr, `twin_msgr->state` shall be set to TWIN_MESSENGER_STATE_ERROR, and `twin_msgr->on_state_changed_callback` invoked if provided] |
AzureIoTClient | 56:8704100b3b54 | 2018 | update_state(twin_msgr, TWIN_MESSENGER_STATE_ERROR); |
AzureIoTClient | 56:8704100b3b54 | 2019 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 2020 | } |
AzureIoTClient | 56:8704100b3b54 | 2021 | else |
AzureIoTClient | 56:8704100b3b54 | 2022 | { |
AzureIoTClient | 56:8704100b3b54 | 2023 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_056: [If no failures occurr, twin_messenger_stop() shall return 0] |
AzureIoTClient | 56:8704100b3b54 | 2024 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 2025 | } |
AzureIoTClient | 56:8704100b3b54 | 2026 | } |
AzureIoTClient | 39:e98d5df6dc74 | 2027 | |
AzureIoTClient | 56:8704100b3b54 | 2028 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 2029 | } |
AzureIoTClient | 39:e98d5df6dc74 | 2030 | |
AzureIoTClient | 39:e98d5df6dc74 | 2031 | void twin_messenger_do_work(TWIN_MESSENGER_HANDLE twin_msgr_handle) |
AzureIoTClient | 39:e98d5df6dc74 | 2032 | { |
AzureIoTClient | 56:8704100b3b54 | 2033 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_057: [If `twin_msgr_handle` is NULL, twin_messenger_do_work() shall return immediately] |
AzureIoTClient | 56:8704100b3b54 | 2034 | if (twin_msgr_handle != NULL) |
AzureIoTClient | 56:8704100b3b54 | 2035 | { |
AzureIoTClient | 56:8704100b3b54 | 2036 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)twin_msgr_handle; |
AzureIoTClient | 39:e98d5df6dc74 | 2037 | |
AzureIoTClient | 56:8704100b3b54 | 2038 | if (twin_msgr->state == TWIN_MESSENGER_STATE_STARTED) |
AzureIoTClient | 56:8704100b3b54 | 2039 | { |
AzureIoTClient | 56:8704100b3b54 | 2040 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_058: [If `twin_msgr->state` is TWIN_MESSENGER_STATE_STARTED, twin_messenger_do_work() shall send the PATCHES in `twin_msgr->pending_patches`, removing them from the list] |
AzureIoTClient | 56:8704100b3b54 | 2041 | (void)singlylinkedlist_remove_if(twin_msgr->pending_patches, send_pending_twin_patch, (const void*)twin_msgr); |
AzureIoTClient | 39:e98d5df6dc74 | 2042 | |
AzureIoTClient | 56:8704100b3b54 | 2043 | process_twin_subscription(twin_msgr); |
AzureIoTClient | 56:8704100b3b54 | 2044 | } |
AzureIoTClient | 39:e98d5df6dc74 | 2045 | |
AzureIoTClient | 56:8704100b3b54 | 2046 | process_timeouts(twin_msgr); |
AzureIoTClient | 39:e98d5df6dc74 | 2047 | |
AzureIoTClient | 56:8704100b3b54 | 2048 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_083: [twin_messenger_do_work() shall invoke amqp_messenger_do_work() passing `twin_msgr->amqp_msgr`] |
AzureIoTClient | 56:8704100b3b54 | 2049 | amqp_messenger_do_work(twin_msgr->amqp_msgr); |
AzureIoTClient | 56:8704100b3b54 | 2050 | } |
AzureIoTClient | 39:e98d5df6dc74 | 2051 | } |
AzureIoTClient | 39:e98d5df6dc74 | 2052 | |
AzureIoTClient | 39:e98d5df6dc74 | 2053 | void twin_messenger_destroy(TWIN_MESSENGER_HANDLE twin_msgr_handle) |
AzureIoTClient | 39:e98d5df6dc74 | 2054 | { |
AzureIoTClient | 56:8704100b3b54 | 2055 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_098: [If `twin_msgr_handle` is NULL, twin_messenger_destroy() shall return immediately] |
AzureIoTClient | 56:8704100b3b54 | 2056 | if (twin_msgr_handle == NULL) |
AzureIoTClient | 56:8704100b3b54 | 2057 | { |
AzureIoTClient | 56:8704100b3b54 | 2058 | LogError("Invalid argument (twin_msgr_handle is NULL)"); |
AzureIoTClient | 56:8704100b3b54 | 2059 | } |
AzureIoTClient | 56:8704100b3b54 | 2060 | else |
AzureIoTClient | 56:8704100b3b54 | 2061 | { |
AzureIoTClient | 56:8704100b3b54 | 2062 | internal_twin_messenger_destroy((TWIN_MESSENGER_INSTANCE*)twin_msgr_handle); |
AzureIoTClient | 56:8704100b3b54 | 2063 | } |
AzureIoTClient | 39:e98d5df6dc74 | 2064 | } |
AzureIoTClient | 39:e98d5df6dc74 | 2065 | |
AzureIoTClient | 39:e98d5df6dc74 | 2066 | int twin_messenger_set_option(TWIN_MESSENGER_HANDLE twin_msgr_handle, const char* name, void* value) |
AzureIoTClient | 39:e98d5df6dc74 | 2067 | { |
AzureIoTClient | 56:8704100b3b54 | 2068 | int result; |
AzureIoTClient | 39:e98d5df6dc74 | 2069 | |
AzureIoTClient | 56:8704100b3b54 | 2070 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_103: [If `twin_msgr_handle` or `name` or `value` are NULL, twin_messenger_set_option() shall fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 2071 | if (twin_msgr_handle == NULL || name == NULL || value == NULL) |
AzureIoTClient | 56:8704100b3b54 | 2072 | { |
AzureIoTClient | 56:8704100b3b54 | 2073 | LogError("Invalid argument (twin_msgr_handle=%p, name=%p, value=%p)", twin_msgr_handle, name, value); |
AzureIoTClient | 56:8704100b3b54 | 2074 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 2075 | } |
AzureIoTClient | 56:8704100b3b54 | 2076 | else |
AzureIoTClient | 56:8704100b3b54 | 2077 | { |
AzureIoTClient | 56:8704100b3b54 | 2078 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)twin_msgr_handle; |
AzureIoTClient | 39:e98d5df6dc74 | 2079 | |
AzureIoTClient | 56:8704100b3b54 | 2080 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_104: [amqp_messenger_set_option() shall be invoked passing `name` and `option`] |
AzureIoTClient | 56:8704100b3b54 | 2081 | if (amqp_messenger_set_option(twin_msgr->amqp_msgr, name, value) != RESULT_OK) |
AzureIoTClient | 56:8704100b3b54 | 2082 | { |
AzureIoTClient | 56:8704100b3b54 | 2083 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_105: [If amqp_messenger_set_option() fails, twin_messenger_set_option() shall fail and return a non-zero value] |
AzureIoTClient | 56:8704100b3b54 | 2084 | LogError("Failed setting TWIN messenger option (%s, %s)", twin_msgr->device_id, name); |
AzureIoTClient | 56:8704100b3b54 | 2085 | result = __FAILURE__; |
AzureIoTClient | 56:8704100b3b54 | 2086 | } |
AzureIoTClient | 56:8704100b3b54 | 2087 | else |
AzureIoTClient | 56:8704100b3b54 | 2088 | { |
AzureIoTClient | 56:8704100b3b54 | 2089 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_106: [If no errors occur, twin_messenger_set_option shall return zero] |
AzureIoTClient | 56:8704100b3b54 | 2090 | result = RESULT_OK; |
AzureIoTClient | 56:8704100b3b54 | 2091 | } |
AzureIoTClient | 56:8704100b3b54 | 2092 | } |
AzureIoTClient | 39:e98d5df6dc74 | 2093 | |
AzureIoTClient | 56:8704100b3b54 | 2094 | return result; |
AzureIoTClient | 39:e98d5df6dc74 | 2095 | } |
AzureIoTClient | 39:e98d5df6dc74 | 2096 | |
AzureIoTClient | 39:e98d5df6dc74 | 2097 | OPTIONHANDLER_HANDLE twin_messenger_retrieve_options(TWIN_MESSENGER_HANDLE twin_msgr_handle) |
AzureIoTClient | 39:e98d5df6dc74 | 2098 | { |
AzureIoTClient | 56:8704100b3b54 | 2099 | OPTIONHANDLER_HANDLE result; |
AzureIoTClient | 39:e98d5df6dc74 | 2100 | |
AzureIoTClient | 56:8704100b3b54 | 2101 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_107: [If `twin_msgr_handle` is NULL, twin_messenger_retrieve_options shall fail and return NULL] |
AzureIoTClient | 56:8704100b3b54 | 2102 | if (twin_msgr_handle == NULL) |
AzureIoTClient | 56:8704100b3b54 | 2103 | { |
AzureIoTClient | 56:8704100b3b54 | 2104 | LogError("Invalid argument (twin_msgr_handle is NULL)"); |
AzureIoTClient | 56:8704100b3b54 | 2105 | result = NULL; |
AzureIoTClient | 56:8704100b3b54 | 2106 | } |
AzureIoTClient | 56:8704100b3b54 | 2107 | else |
AzureIoTClient | 56:8704100b3b54 | 2108 | { |
AzureIoTClient | 56:8704100b3b54 | 2109 | TWIN_MESSENGER_INSTANCE* twin_msgr = (TWIN_MESSENGER_INSTANCE*)twin_msgr_handle; |
AzureIoTClient | 39:e98d5df6dc74 | 2110 | |
AzureIoTClient | 56:8704100b3b54 | 2111 | // Codes_IOTHUBTRANSPORT_AMQP_TWIN_MESSENGER_09_108: [twin_messenger_retrieve_options() shall return the result of amqp_messenger_retrieve_options()] |
AzureIoTClient | 56:8704100b3b54 | 2112 | if ((result = amqp_messenger_retrieve_options(twin_msgr->amqp_msgr)) == NULL) |
AzureIoTClient | 56:8704100b3b54 | 2113 | { |
AzureIoTClient | 56:8704100b3b54 | 2114 | LogError("Failed TWIN messenger options (%s)", twin_msgr->device_id); |
AzureIoTClient | 56:8704100b3b54 | 2115 | } |
AzureIoTClient | 56:8704100b3b54 | 2116 | } |
AzureIoTClient | 39:e98d5df6dc74 | 2117 | |
AzureIoTClient | 56:8704100b3b54 | 2118 | return result; |
AzureIoTClient | 50:f3a92c6c6534 | 2119 | } |