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