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