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

Committer:
AzureIoTClient
Date:
Thu Oct 04 09:14:47 2018 -0700
Revision:
57:56ac1346c70d
Parent:
56:8704100b3b54
1.2.10

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AzureIoTClient 30:20a85b733111 1 // Copyright (c) Microsoft. All rights reserved.
AzureIoTClient 30:20a85b733111 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
AzureIoTClient 30:20a85b733111 3
AzureIoTClient 30:20a85b733111 4 #include <stdlib.h>
AzureIoTClient 30:20a85b733111 5 #include "azure_c_shared_utility/optimize_size.h"
AzureIoTClient 30:20a85b733111 6 #include "azure_c_shared_utility/gballoc.h"
AzureIoTClient 56:8704100b3b54 7 #include "azure_c_shared_utility/agenttime.h"
AzureIoTClient 30:20a85b733111 8 #include "azure_c_shared_utility/xlogging.h"
AzureIoTClient 30:20a85b733111 9 #include "azure_c_shared_utility/strings.h"
AzureIoTClient 53:e21e1e88460f 10 #include "internal/iothubtransport_amqp_cbs_auth.h"
AzureIoTClient 53:e21e1e88460f 11 #include "internal/iothubtransport_amqp_device.h"
AzureIoTClient 53:e21e1e88460f 12 #include "internal/iothubtransport_amqp_telemetry_messenger.h"
AzureIoTClient 53:e21e1e88460f 13 #include "internal/iothubtransport_amqp_twin_messenger.h"
AzureIoTClient 39:e98d5df6dc74 14
AzureIoTClient 39:e98d5df6dc74 15 DEFINE_ENUM_STRINGS(DEVICE_STATE, DEVICE_STATE_VALUES);
AzureIoTClient 39:e98d5df6dc74 16 DEFINE_ENUM_STRINGS(DEVICE_AUTH_MODE, DEVICE_AUTH_MODE_VALUES);
AzureIoTClient 39:e98d5df6dc74 17 DEFINE_ENUM_STRINGS(DEVICE_SEND_STATUS, DEVICE_SEND_STATUS_VALUES);
AzureIoTClient 39:e98d5df6dc74 18 DEFINE_ENUM_STRINGS(D2C_EVENT_SEND_RESULT, D2C_EVENT_SEND_RESULT_VALUES);
AzureIoTClient 39:e98d5df6dc74 19 DEFINE_ENUM_STRINGS(DEVICE_MESSAGE_DISPOSITION_RESULT, DEVICE_MESSAGE_DISPOSITION_RESULT_VALUES);
AzureIoTClient 39:e98d5df6dc74 20 DEFINE_ENUM_STRINGS(DEVICE_TWIN_UPDATE_RESULT, DEVICE_TWIN_UPDATE_RESULT_STRINGS);
AzureIoTClient 39:e98d5df6dc74 21 DEFINE_ENUM_STRINGS(DEVICE_TWIN_UPDATE_TYPE, DEVICE_TWIN_UPDATE_TYPE_STRINGS)
AzureIoTClient 30:20a85b733111 22
AzureIoTClient 30:20a85b733111 23 #define RESULT_OK 0
AzureIoTClient 30:20a85b733111 24 #define INDEFINITE_TIME ((time_t)-1)
AzureIoTClient 30:20a85b733111 25 #define DEFAULT_AUTH_STATE_CHANGED_TIMEOUT_SECS 60
AzureIoTClient 30:20a85b733111 26 #define DEFAULT_MSGR_STATE_CHANGED_TIMEOUT_SECS 60
AzureIoTClient 30:20a85b733111 27
AzureIoTClient 30:20a85b733111 28 static const char* DEVICE_OPTION_SAVED_AUTH_OPTIONS = "saved_device_auth_options";
AzureIoTClient 30:20a85b733111 29 static const char* DEVICE_OPTION_SAVED_MESSENGER_OPTIONS = "saved_device_messenger_options";
AzureIoTClient 30:20a85b733111 30
AzureIoTClient 30:20a85b733111 31 typedef struct DEVICE_INSTANCE_TAG
AzureIoTClient 30:20a85b733111 32 {
AzureIoTClient 34:51d158b409d2 33 DEVICE_CONFIG* config;
AzureIoTClient 34:51d158b409d2 34 DEVICE_STATE state;
AzureIoTClient 30:20a85b733111 35
AzureIoTClient 34:51d158b409d2 36 SESSION_HANDLE session_handle;
AzureIoTClient 34:51d158b409d2 37 CBS_HANDLE cbs_handle;
AzureIoTClient 30:20a85b733111 38
AzureIoTClient 34:51d158b409d2 39 AUTHENTICATION_HANDLE authentication_handle;
AzureIoTClient 34:51d158b409d2 40 AUTHENTICATION_STATE auth_state;
AzureIoTClient 34:51d158b409d2 41 AUTHENTICATION_ERROR_CODE auth_error_code;
AzureIoTClient 34:51d158b409d2 42 time_t auth_state_last_changed_time;
AzureIoTClient 34:51d158b409d2 43 size_t auth_state_change_timeout_secs;
AzureIoTClient 30:20a85b733111 44
AzureIoTClient 36:f78f9a56869e 45 TELEMETRY_MESSENGER_HANDLE messenger_handle;
AzureIoTClient 36:f78f9a56869e 46 TELEMETRY_MESSENGER_STATE msgr_state;
AzureIoTClient 34:51d158b409d2 47 time_t msgr_state_last_changed_time;
AzureIoTClient 34:51d158b409d2 48 size_t msgr_state_change_timeout_secs;
AzureIoTClient 30:20a85b733111 49
AzureIoTClient 34:51d158b409d2 50 ON_DEVICE_C2D_MESSAGE_RECEIVED on_message_received_callback;
AzureIoTClient 34:51d158b409d2 51 void* on_message_received_context;
AzureIoTClient 39:e98d5df6dc74 52
AzureIoTClient 41:71c01aa3df1a 53 TWIN_MESSENGER_HANDLE twin_messenger_handle;
AzureIoTClient 41:71c01aa3df1a 54 TWIN_MESSENGER_STATE twin_msgr_state;
AzureIoTClient 41:71c01aa3df1a 55 time_t twin_msgr_state_last_changed_time;
AzureIoTClient 41:71c01aa3df1a 56 size_t twin_msgr_state_change_timeout_secs;
AzureIoTClient 41:71c01aa3df1a 57 DEVICE_TWIN_UPDATE_RECEIVED_CALLBACK on_device_twin_update_received_callback;
AzureIoTClient 41:71c01aa3df1a 58 void* on_device_twin_update_received_context;
AzureIoTClient 51:269e65571b39 59 } AMQP_DEVICE_INSTANCE;
AzureIoTClient 30:20a85b733111 60
AzureIoTClient 30:20a85b733111 61 typedef struct DEVICE_SEND_EVENT_TASK_TAG
AzureIoTClient 30:20a85b733111 62 {
AzureIoTClient 34:51d158b409d2 63 ON_DEVICE_D2C_EVENT_SEND_COMPLETE on_event_send_complete_callback;
AzureIoTClient 34:51d158b409d2 64 void* on_event_send_complete_context;
AzureIoTClient 30:20a85b733111 65 } DEVICE_SEND_EVENT_TASK;
AzureIoTClient 30:20a85b733111 66
AzureIoTClient 39:e98d5df6dc74 67 typedef struct DEVICE_SEND_TWIN_UPDATE_CONTEXT_TAG
AzureIoTClient 39:e98d5df6dc74 68 {
AzureIoTClient 41:71c01aa3df1a 69 DEVICE_SEND_TWIN_UPDATE_COMPLETE_CALLBACK on_send_twin_update_complete_callback;
AzureIoTClient 41:71c01aa3df1a 70 void* context;
AzureIoTClient 39:e98d5df6dc74 71 } DEVICE_SEND_TWIN_UPDATE_CONTEXT;
AzureIoTClient 39:e98d5df6dc74 72
AzureIoTClient 30:20a85b733111 73 // Internal state control
AzureIoTClient 51:269e65571b39 74 static void update_state(AMQP_DEVICE_INSTANCE* instance, DEVICE_STATE new_state)
AzureIoTClient 30:20a85b733111 75 {
AzureIoTClient 34:51d158b409d2 76 if (new_state != instance->state)
AzureIoTClient 34:51d158b409d2 77 {
AzureIoTClient 34:51d158b409d2 78 DEVICE_STATE previous_state = instance->state;
AzureIoTClient 34:51d158b409d2 79 instance->state = new_state;
AzureIoTClient 30:20a85b733111 80
AzureIoTClient 34:51d158b409d2 81 if (instance->config->on_state_changed_callback != NULL)
AzureIoTClient 34:51d158b409d2 82 {
AzureIoTClient 34:51d158b409d2 83 instance->config->on_state_changed_callback(instance->config->on_state_changed_context, previous_state, new_state);
AzureIoTClient 34:51d158b409d2 84 }
AzureIoTClient 34:51d158b409d2 85 }
AzureIoTClient 30:20a85b733111 86 }
AzureIoTClient 30:20a85b733111 87
AzureIoTClient 30:20a85b733111 88 static int is_timeout_reached(time_t start_time, size_t timeout_in_secs, int *is_timed_out)
AzureIoTClient 30:20a85b733111 89 {
AzureIoTClient 34:51d158b409d2 90 int result;
AzureIoTClient 30:20a85b733111 91
AzureIoTClient 34:51d158b409d2 92 if (start_time == INDEFINITE_TIME)
AzureIoTClient 34:51d158b409d2 93 {
AzureIoTClient 34:51d158b409d2 94 LogError("Failed to verify timeout (start_time is INDEFINITE)");
AzureIoTClient 34:51d158b409d2 95 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 96 }
AzureIoTClient 34:51d158b409d2 97 else
AzureIoTClient 34:51d158b409d2 98 {
AzureIoTClient 34:51d158b409d2 99 time_t current_time;
AzureIoTClient 30:20a85b733111 100
AzureIoTClient 34:51d158b409d2 101 if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
AzureIoTClient 34:51d158b409d2 102 {
AzureIoTClient 34:51d158b409d2 103 LogError("Failed to verify timeout (get_time failed)");
AzureIoTClient 34:51d158b409d2 104 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 105 }
AzureIoTClient 34:51d158b409d2 106 else
AzureIoTClient 34:51d158b409d2 107 {
AzureIoTClient 34:51d158b409d2 108 if (get_difftime(current_time, start_time) >= timeout_in_secs)
AzureIoTClient 34:51d158b409d2 109 {
AzureIoTClient 34:51d158b409d2 110 *is_timed_out = 1;
AzureIoTClient 34:51d158b409d2 111 }
AzureIoTClient 34:51d158b409d2 112 else
AzureIoTClient 34:51d158b409d2 113 {
AzureIoTClient 34:51d158b409d2 114 *is_timed_out = 0;
AzureIoTClient 34:51d158b409d2 115 }
AzureIoTClient 30:20a85b733111 116
AzureIoTClient 34:51d158b409d2 117 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 118 }
AzureIoTClient 34:51d158b409d2 119 }
AzureIoTClient 30:20a85b733111 120
AzureIoTClient 34:51d158b409d2 121 return result;
AzureIoTClient 30:20a85b733111 122 }
AzureIoTClient 30:20a85b733111 123
AzureIoTClient 39:e98d5df6dc74 124
AzureIoTClient 39:e98d5df6dc74 125 //---------- Callback Handlers ----------//
AzureIoTClient 39:e98d5df6dc74 126
AzureIoTClient 36:f78f9a56869e 127 static D2C_EVENT_SEND_RESULT get_d2c_event_send_result_from(TELEMETRY_MESSENGER_EVENT_SEND_COMPLETE_RESULT result)
AzureIoTClient 30:20a85b733111 128 {
AzureIoTClient 34:51d158b409d2 129 D2C_EVENT_SEND_RESULT d2c_esr;
AzureIoTClient 30:20a85b733111 130
AzureIoTClient 34:51d158b409d2 131 switch (result)
AzureIoTClient 34:51d158b409d2 132 {
AzureIoTClient 36:f78f9a56869e 133 case TELEMETRY_MESSENGER_EVENT_SEND_COMPLETE_RESULT_OK:
AzureIoTClient 34:51d158b409d2 134 d2c_esr = D2C_EVENT_SEND_COMPLETE_RESULT_OK;
AzureIoTClient 34:51d158b409d2 135 break;
AzureIoTClient 36:f78f9a56869e 136 case TELEMETRY_MESSENGER_EVENT_SEND_COMPLETE_RESULT_ERROR_CANNOT_PARSE:
AzureIoTClient 34:51d158b409d2 137 d2c_esr = D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_CANNOT_PARSE;
AzureIoTClient 34:51d158b409d2 138 break;
AzureIoTClient 36:f78f9a56869e 139 case TELEMETRY_MESSENGER_EVENT_SEND_COMPLETE_RESULT_ERROR_FAIL_SENDING:
AzureIoTClient 34:51d158b409d2 140 d2c_esr = D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_FAIL_SENDING;
AzureIoTClient 34:51d158b409d2 141 break;
AzureIoTClient 36:f78f9a56869e 142 case TELEMETRY_MESSENGER_EVENT_SEND_COMPLETE_RESULT_ERROR_TIMEOUT:
AzureIoTClient 34:51d158b409d2 143 d2c_esr = D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_TIMEOUT;
AzureIoTClient 34:51d158b409d2 144 break;
AzureIoTClient 36:f78f9a56869e 145 case TELEMETRY_MESSENGER_EVENT_SEND_COMPLETE_RESULT_MESSENGER_DESTROYED:
AzureIoTClient 34:51d158b409d2 146 d2c_esr = D2C_EVENT_SEND_COMPLETE_RESULT_DEVICE_DESTROYED;
AzureIoTClient 34:51d158b409d2 147 break;
AzureIoTClient 34:51d158b409d2 148 default:
AzureIoTClient 34:51d158b409d2 149 // This is not expected. All states should be mapped.
AzureIoTClient 34:51d158b409d2 150 d2c_esr = D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_UNKNOWN;
AzureIoTClient 34:51d158b409d2 151 break;
AzureIoTClient 34:51d158b409d2 152 };
AzureIoTClient 30:20a85b733111 153
AzureIoTClient 34:51d158b409d2 154 return d2c_esr;
AzureIoTClient 30:20a85b733111 155 }
AzureIoTClient 30:20a85b733111 156
AzureIoTClient 36:f78f9a56869e 157 static void on_event_send_complete_messenger_callback(IOTHUB_MESSAGE_LIST* iothub_message, TELEMETRY_MESSENGER_EVENT_SEND_COMPLETE_RESULT ev_send_comp_result, void* context)
AzureIoTClient 30:20a85b733111 158 {
AzureIoTClient 34:51d158b409d2 159 if (iothub_message == NULL || context == NULL)
AzureIoTClient 34:51d158b409d2 160 {
AzureIoTClient 34:51d158b409d2 161 LogError("on_event_send_complete_messenger_callback was invoked, but either iothub_message (%p) or context (%p) are NULL", iothub_message, context);
AzureIoTClient 34:51d158b409d2 162 }
AzureIoTClient 34:51d158b409d2 163 else
AzureIoTClient 34:51d158b409d2 164 {
AzureIoTClient 34:51d158b409d2 165 DEVICE_SEND_EVENT_TASK* send_task = (DEVICE_SEND_EVENT_TASK*)context;
AzureIoTClient 30:20a85b733111 166
AzureIoTClient 36:f78f9a56869e 167 // Codes_SRS_DEVICE_09_059: [If `ev_send_comp_result` is TELEMETRY_MESSENGER_EVENT_SEND_COMPLETE_RESULT_OK, D2C_EVENT_SEND_COMPLETE_RESULT_OK shall be reported as `event_send_complete`]
AzureIoTClient 36:f78f9a56869e 168 // Codes_SRS_DEVICE_09_060: [If `ev_send_comp_result` is TELEMETRY_MESSENGER_EVENT_SEND_COMPLETE_RESULT_ERROR_CANNOT_PARSE, D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_CANNOT_PARSE shall be reported as `event_send_complete`]
AzureIoTClient 36:f78f9a56869e 169 // Codes_SRS_DEVICE_09_061: [If `ev_send_comp_result` is TELEMETRY_MESSENGER_EVENT_SEND_COMPLETE_RESULT_ERROR_FAIL_SENDING, D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_FAIL_SENDING shall be reported as `event_send_complete`]
AzureIoTClient 36:f78f9a56869e 170 // Codes_SRS_DEVICE_09_062: [If `ev_send_comp_result` is TELEMETRY_MESSENGER_EVENT_SEND_COMPLETE_RESULT_ERROR_TIMEOUT, D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_TIMEOUT shall be reported as `event_send_complete`]
AzureIoTClient 36:f78f9a56869e 171 // Codes_SRS_DEVICE_09_063: [If `ev_send_comp_result` is TELEMETRY_MESSENGER_EVENT_SEND_COMPLETE_RESULT_MESSENGER_DESTROYED, D2C_EVENT_SEND_COMPLETE_RESULT_DEVICE_DESTROYED shall be reported as `event_send_complete`]
AzureIoTClient 34:51d158b409d2 172 D2C_EVENT_SEND_RESULT device_send_result = get_d2c_event_send_result_from(ev_send_comp_result);
AzureIoTClient 30:20a85b733111 173
AzureIoTClient 34:51d158b409d2 174 // Codes_SRS_DEVICE_09_064: [If provided, the user callback and context saved in `send_task` shall be invoked passing the device `event_send_complete`]
AzureIoTClient 34:51d158b409d2 175 if (send_task->on_event_send_complete_callback != NULL)
AzureIoTClient 34:51d158b409d2 176 {
AzureIoTClient 34:51d158b409d2 177 send_task->on_event_send_complete_callback(iothub_message, device_send_result, send_task->on_event_send_complete_context);
AzureIoTClient 34:51d158b409d2 178 }
AzureIoTClient 30:20a85b733111 179
AzureIoTClient 34:51d158b409d2 180 // Codes_SRS_DEVICE_09_065: [The memory allocated for `send_task` shall be released]
AzureIoTClient 34:51d158b409d2 181 free(send_task);
AzureIoTClient 34:51d158b409d2 182 }
AzureIoTClient 30:20a85b733111 183 }
AzureIoTClient 30:20a85b733111 184
AzureIoTClient 30:20a85b733111 185 static void on_authentication_error_callback(void* context, AUTHENTICATION_ERROR_CODE error_code)
AzureIoTClient 30:20a85b733111 186 {
AzureIoTClient 34:51d158b409d2 187 if (context == NULL)
AzureIoTClient 34:51d158b409d2 188 {
AzureIoTClient 34:51d158b409d2 189 LogError("on_authentication_error_callback was invoked with error %d, but context is NULL", error_code);
AzureIoTClient 34:51d158b409d2 190 }
AzureIoTClient 34:51d158b409d2 191 else
AzureIoTClient 56:8704100b3b54 192 {
AzureIoTClient 51:269e65571b39 193 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)context;
AzureIoTClient 34:51d158b409d2 194 instance->auth_error_code = error_code;
AzureIoTClient 34:51d158b409d2 195 }
AzureIoTClient 30:20a85b733111 196 }
AzureIoTClient 30:20a85b733111 197
AzureIoTClient 30:20a85b733111 198 static void on_authentication_state_changed_callback(void* context, AUTHENTICATION_STATE previous_state, AUTHENTICATION_STATE new_state)
AzureIoTClient 30:20a85b733111 199 {
AzureIoTClient 34:51d158b409d2 200 if (context == NULL)
AzureIoTClient 34:51d158b409d2 201 {
AzureIoTClient 34:51d158b409d2 202 LogError("on_authentication_state_changed_callback was invoked with new_state %d, but context is NULL", new_state);
AzureIoTClient 34:51d158b409d2 203 }
AzureIoTClient 34:51d158b409d2 204 else if (new_state != previous_state)
AzureIoTClient 34:51d158b409d2 205 {
AzureIoTClient 51:269e65571b39 206 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)context;
AzureIoTClient 34:51d158b409d2 207 instance->auth_state = new_state;
AzureIoTClient 30:20a85b733111 208
AzureIoTClient 34:51d158b409d2 209 if ((instance->auth_state_last_changed_time = get_time(NULL)) == INDEFINITE_TIME)
AzureIoTClient 34:51d158b409d2 210 {
AzureIoTClient 34:51d158b409d2 211 LogError("Device '%s' failed to set time of last authentication state change (get_time failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 212 }
AzureIoTClient 34:51d158b409d2 213 }
AzureIoTClient 30:20a85b733111 214 }
AzureIoTClient 30:20a85b733111 215
AzureIoTClient 36:f78f9a56869e 216 static void on_messenger_state_changed_callback(void* context, TELEMETRY_MESSENGER_STATE previous_state, TELEMETRY_MESSENGER_STATE new_state)
AzureIoTClient 30:20a85b733111 217 {
AzureIoTClient 34:51d158b409d2 218 if (context == NULL)
AzureIoTClient 34:51d158b409d2 219 {
AzureIoTClient 34:51d158b409d2 220 LogError("on_messenger_state_changed_callback was invoked with new_state %d, but context is NULL", new_state);
AzureIoTClient 34:51d158b409d2 221 }
AzureIoTClient 34:51d158b409d2 222 else if (new_state != previous_state)
AzureIoTClient 34:51d158b409d2 223 {
AzureIoTClient 51:269e65571b39 224 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)context;
AzureIoTClient 34:51d158b409d2 225 instance->msgr_state = new_state;
AzureIoTClient 30:20a85b733111 226
AzureIoTClient 34:51d158b409d2 227 if ((instance->msgr_state_last_changed_time = get_time(NULL)) == INDEFINITE_TIME)
AzureIoTClient 34:51d158b409d2 228 {
AzureIoTClient 34:51d158b409d2 229 LogError("Device '%s' failed to set time of last messenger state change (get_time failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 230 }
AzureIoTClient 34:51d158b409d2 231 }
AzureIoTClient 30:20a85b733111 232 }
AzureIoTClient 30:20a85b733111 233
AzureIoTClient 39:e98d5df6dc74 234 static DEVICE_TWIN_UPDATE_RESULT get_device_twin_update_result_from(TWIN_REPORT_STATE_RESULT result)
AzureIoTClient 39:e98d5df6dc74 235 {
AzureIoTClient 41:71c01aa3df1a 236 DEVICE_TWIN_UPDATE_RESULT device_result;
AzureIoTClient 39:e98d5df6dc74 237
AzureIoTClient 41:71c01aa3df1a 238 switch (result)
AzureIoTClient 41:71c01aa3df1a 239 {
AzureIoTClient 41:71c01aa3df1a 240 case TWIN_REPORT_STATE_RESULT_SUCCESS:
AzureIoTClient 41:71c01aa3df1a 241 device_result = DEVICE_TWIN_UPDATE_RESULT_OK;
AzureIoTClient 41:71c01aa3df1a 242 break;
AzureIoTClient 41:71c01aa3df1a 243 case TWIN_REPORT_STATE_RESULT_ERROR:
AzureIoTClient 41:71c01aa3df1a 244 device_result = DEVICE_TWIN_UPDATE_RESULT_ERROR;
AzureIoTClient 41:71c01aa3df1a 245 break;
AzureIoTClient 41:71c01aa3df1a 246 default:
AzureIoTClient 41:71c01aa3df1a 247 device_result = DEVICE_TWIN_UPDATE_RESULT_ERROR;
AzureIoTClient 41:71c01aa3df1a 248 };
AzureIoTClient 39:e98d5df6dc74 249
AzureIoTClient 41:71c01aa3df1a 250 return device_result;
AzureIoTClient 39:e98d5df6dc74 251 }
AzureIoTClient 39:e98d5df6dc74 252
AzureIoTClient 39:e98d5df6dc74 253 static void on_report_state_complete_callback(TWIN_REPORT_STATE_RESULT result, TWIN_REPORT_STATE_REASON reason, int status_code, const void* context)
AzureIoTClient 39:e98d5df6dc74 254 {
AzureIoTClient 41:71c01aa3df1a 255 (void)reason;
AzureIoTClient 56:8704100b3b54 256
AzureIoTClient 41:71c01aa3df1a 257 if (context == NULL)
AzureIoTClient 41:71c01aa3df1a 258 {
AzureIoTClient 41:71c01aa3df1a 259 LogError("Invalid argument (context is NULL)");
AzureIoTClient 41:71c01aa3df1a 260 }
AzureIoTClient 41:71c01aa3df1a 261 else
AzureIoTClient 41:71c01aa3df1a 262 {
AzureIoTClient 41:71c01aa3df1a 263 DEVICE_SEND_TWIN_UPDATE_CONTEXT* twin_ctx = (DEVICE_SEND_TWIN_UPDATE_CONTEXT*)context;
AzureIoTClient 56:8704100b3b54 264
AzureIoTClient 41:71c01aa3df1a 265 // Codes_SRS_DEVICE_09_141: [on_send_twin_update_complete_callback (if provided by user) shall be invoked passing the corresponding device result and `status_code`]
AzureIoTClient 41:71c01aa3df1a 266 if (twin_ctx->on_send_twin_update_complete_callback != NULL)
AzureIoTClient 41:71c01aa3df1a 267 {
AzureIoTClient 41:71c01aa3df1a 268 DEVICE_TWIN_UPDATE_RESULT device_result;
AzureIoTClient 39:e98d5df6dc74 269
AzureIoTClient 41:71c01aa3df1a 270 device_result = get_device_twin_update_result_from(result);
AzureIoTClient 39:e98d5df6dc74 271
AzureIoTClient 41:71c01aa3df1a 272 twin_ctx->on_send_twin_update_complete_callback(device_result, status_code, twin_ctx->context);
AzureIoTClient 41:71c01aa3df1a 273 }
AzureIoTClient 39:e98d5df6dc74 274
AzureIoTClient 41:71c01aa3df1a 275 // Codes_SRS_DEVICE_09_142: [Memory allocated for `context` shall be released]
AzureIoTClient 41:71c01aa3df1a 276 free(twin_ctx);
AzureIoTClient 41:71c01aa3df1a 277 }
AzureIoTClient 39:e98d5df6dc74 278 }
AzureIoTClient 39:e98d5df6dc74 279
AzureIoTClient 39:e98d5df6dc74 280 static void on_twin_state_update_callback(TWIN_UPDATE_TYPE update_type, const char* payload, size_t size, const void* context)
AzureIoTClient 39:e98d5df6dc74 281 {
AzureIoTClient 41:71c01aa3df1a 282 if (payload == NULL || context == NULL)
AzureIoTClient 41:71c01aa3df1a 283 {
AzureIoTClient 41:71c01aa3df1a 284 LogError("Invalid argument (context=%p, payload=%p)", context, payload);
AzureIoTClient 41:71c01aa3df1a 285 }
AzureIoTClient 41:71c01aa3df1a 286 else
AzureIoTClient 41:71c01aa3df1a 287 {
AzureIoTClient 51:269e65571b39 288 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)context;
AzureIoTClient 39:e98d5df6dc74 289
AzureIoTClient 41:71c01aa3df1a 290 DEVICE_TWIN_UPDATE_TYPE device_update_type;
AzureIoTClient 39:e98d5df6dc74 291
AzureIoTClient 41:71c01aa3df1a 292 if (update_type == TWIN_UPDATE_TYPE_COMPLETE)
AzureIoTClient 41:71c01aa3df1a 293 {
AzureIoTClient 41:71c01aa3df1a 294 device_update_type = DEVICE_TWIN_UPDATE_TYPE_COMPLETE;
AzureIoTClient 41:71c01aa3df1a 295 }
AzureIoTClient 41:71c01aa3df1a 296 else
AzureIoTClient 41:71c01aa3df1a 297 {
AzureIoTClient 41:71c01aa3df1a 298 device_update_type = DEVICE_TWIN_UPDATE_TYPE_PARTIAL;
AzureIoTClient 41:71c01aa3df1a 299 }
AzureIoTClient 39:e98d5df6dc74 300
AzureIoTClient 41:71c01aa3df1a 301 // Codes_SRS_DEVICE_09_151: [on_device_twin_update_received_callback (provided by user) shall be invoked passing the corresponding update type, `payload` and `size`]
AzureIoTClient 41:71c01aa3df1a 302 instance->on_device_twin_update_received_callback(device_update_type, (const unsigned char*)payload, size, instance->on_device_twin_update_received_context);
AzureIoTClient 41:71c01aa3df1a 303 }
AzureIoTClient 39:e98d5df6dc74 304 }
AzureIoTClient 39:e98d5df6dc74 305
AzureIoTClient 39:e98d5df6dc74 306 static void on_twin_messenger_state_changed_callback(void* context, TWIN_MESSENGER_STATE previous_state, TWIN_MESSENGER_STATE new_state)
AzureIoTClient 39:e98d5df6dc74 307 {
AzureIoTClient 41:71c01aa3df1a 308 if (context != NULL && new_state != previous_state)
AzureIoTClient 41:71c01aa3df1a 309 {
AzureIoTClient 51:269e65571b39 310 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)context;
AzureIoTClient 41:71c01aa3df1a 311 instance->twin_msgr_state = new_state;
AzureIoTClient 39:e98d5df6dc74 312
AzureIoTClient 41:71c01aa3df1a 313 if ((instance->twin_msgr_state_last_changed_time = get_time(NULL)) == INDEFINITE_TIME)
AzureIoTClient 41:71c01aa3df1a 314 {
AzureIoTClient 41:71c01aa3df1a 315 LogError("Failed setting time of last twin messenger state changed event");
AzureIoTClient 41:71c01aa3df1a 316 }
AzureIoTClient 41:71c01aa3df1a 317 }
AzureIoTClient 39:e98d5df6dc74 318 }
AzureIoTClient 39:e98d5df6dc74 319
AzureIoTClient 39:e98d5df6dc74 320
AzureIoTClient 39:e98d5df6dc74 321 //---------- Message Dispostion ----------//
AzureIoTClient 39:e98d5df6dc74 322
AzureIoTClient 36:f78f9a56869e 323 static DEVICE_MESSAGE_DISPOSITION_INFO* create_device_message_disposition_info_from(TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO* messenger_disposition_info)
AzureIoTClient 30:20a85b733111 324 {
AzureIoTClient 34:51d158b409d2 325 DEVICE_MESSAGE_DISPOSITION_INFO* device_disposition_info;
AzureIoTClient 30:20a85b733111 326
AzureIoTClient 34:51d158b409d2 327 if ((device_disposition_info = (DEVICE_MESSAGE_DISPOSITION_INFO*)malloc(sizeof(DEVICE_MESSAGE_DISPOSITION_INFO))) == NULL)
AzureIoTClient 34:51d158b409d2 328 {
AzureIoTClient 34:51d158b409d2 329 LogError("Failed creating DEVICE_MESSAGE_DISPOSITION_INFO (malloc failed)");
AzureIoTClient 34:51d158b409d2 330 }
AzureIoTClient 34:51d158b409d2 331 else if (mallocAndStrcpy_s(&device_disposition_info->source, messenger_disposition_info->source) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 332 {
AzureIoTClient 34:51d158b409d2 333 LogError("Failed creating DEVICE_MESSAGE_DISPOSITION_INFO (mallocAndStrcpy_s failed)");
AzureIoTClient 34:51d158b409d2 334 free(device_disposition_info);
AzureIoTClient 34:51d158b409d2 335 device_disposition_info = NULL;
AzureIoTClient 34:51d158b409d2 336 }
AzureIoTClient 34:51d158b409d2 337 else
AzureIoTClient 34:51d158b409d2 338 {
AzureIoTClient 34:51d158b409d2 339 device_disposition_info->message_id = messenger_disposition_info->message_id;
AzureIoTClient 34:51d158b409d2 340 }
AzureIoTClient 30:20a85b733111 341
AzureIoTClient 34:51d158b409d2 342 return device_disposition_info;
AzureIoTClient 30:20a85b733111 343 }
AzureIoTClient 30:20a85b733111 344
AzureIoTClient 30:20a85b733111 345 static void destroy_device_disposition_info(DEVICE_MESSAGE_DISPOSITION_INFO* disposition_info)
AzureIoTClient 30:20a85b733111 346 {
AzureIoTClient 34:51d158b409d2 347 free(disposition_info->source);
AzureIoTClient 34:51d158b409d2 348 free(disposition_info);
AzureIoTClient 30:20a85b733111 349 }
AzureIoTClient 30:20a85b733111 350
AzureIoTClient 36:f78f9a56869e 351 static TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO* create_messenger_disposition_info(DEVICE_MESSAGE_DISPOSITION_INFO* device_disposition_info)
AzureIoTClient 30:20a85b733111 352 {
AzureIoTClient 36:f78f9a56869e 353 TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO* messenger_disposition_info;
AzureIoTClient 30:20a85b733111 354
AzureIoTClient 36:f78f9a56869e 355 if ((messenger_disposition_info = (TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO*)malloc(sizeof(TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO))) == NULL)
AzureIoTClient 34:51d158b409d2 356 {
AzureIoTClient 36:f78f9a56869e 357 LogError("Failed creating TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO (malloc failed)");
AzureIoTClient 34:51d158b409d2 358 }
AzureIoTClient 34:51d158b409d2 359 else if (mallocAndStrcpy_s(&messenger_disposition_info->source, device_disposition_info->source) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 360 {
AzureIoTClient 36:f78f9a56869e 361 LogError("Failed creating TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO (mallocAndStrcpy_s failed)");
AzureIoTClient 34:51d158b409d2 362 free(messenger_disposition_info);
AzureIoTClient 34:51d158b409d2 363 messenger_disposition_info = NULL;
AzureIoTClient 34:51d158b409d2 364 }
AzureIoTClient 34:51d158b409d2 365 else
AzureIoTClient 34:51d158b409d2 366 {
AzureIoTClient 48:06c522453dd6 367 messenger_disposition_info->message_id = (delivery_number)device_disposition_info->message_id;
AzureIoTClient 34:51d158b409d2 368 }
AzureIoTClient 30:20a85b733111 369
AzureIoTClient 34:51d158b409d2 370 return messenger_disposition_info;
AzureIoTClient 30:20a85b733111 371 }
AzureIoTClient 30:20a85b733111 372
AzureIoTClient 36:f78f9a56869e 373 static void destroy_messenger_disposition_info(TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO* messenger_disposition_info)
AzureIoTClient 30:20a85b733111 374 {
AzureIoTClient 34:51d158b409d2 375 free(messenger_disposition_info->source);
AzureIoTClient 34:51d158b409d2 376 free(messenger_disposition_info);
AzureIoTClient 30:20a85b733111 377 }
AzureIoTClient 30:20a85b733111 378
AzureIoTClient 36:f78f9a56869e 379 static TELEMETRY_MESSENGER_DISPOSITION_RESULT get_messenger_message_disposition_result_from(DEVICE_MESSAGE_DISPOSITION_RESULT device_disposition_result)
AzureIoTClient 30:20a85b733111 380 {
AzureIoTClient 36:f78f9a56869e 381 TELEMETRY_MESSENGER_DISPOSITION_RESULT messenger_disposition_result;
AzureIoTClient 30:20a85b733111 382
AzureIoTClient 34:51d158b409d2 383 switch (device_disposition_result)
AzureIoTClient 34:51d158b409d2 384 {
AzureIoTClient 34:51d158b409d2 385 case DEVICE_MESSAGE_DISPOSITION_RESULT_NONE:
AzureIoTClient 36:f78f9a56869e 386 messenger_disposition_result = TELEMETRY_MESSENGER_DISPOSITION_RESULT_NONE;
AzureIoTClient 34:51d158b409d2 387 break;
AzureIoTClient 34:51d158b409d2 388 case DEVICE_MESSAGE_DISPOSITION_RESULT_ACCEPTED:
AzureIoTClient 36:f78f9a56869e 389 messenger_disposition_result = TELEMETRY_MESSENGER_DISPOSITION_RESULT_ACCEPTED;
AzureIoTClient 34:51d158b409d2 390 break;
AzureIoTClient 34:51d158b409d2 391 case DEVICE_MESSAGE_DISPOSITION_RESULT_REJECTED:
AzureIoTClient 36:f78f9a56869e 392 messenger_disposition_result = TELEMETRY_MESSENGER_DISPOSITION_RESULT_REJECTED;
AzureIoTClient 34:51d158b409d2 393 break;
AzureIoTClient 34:51d158b409d2 394 case DEVICE_MESSAGE_DISPOSITION_RESULT_RELEASED:
AzureIoTClient 36:f78f9a56869e 395 messenger_disposition_result = TELEMETRY_MESSENGER_DISPOSITION_RESULT_RELEASED;
AzureIoTClient 34:51d158b409d2 396 break;
AzureIoTClient 34:51d158b409d2 397 default:
AzureIoTClient 36:f78f9a56869e 398 LogError("Failed to get the corresponding TELEMETRY_MESSENGER_DISPOSITION_RESULT (%d is not supported)", device_disposition_result);
AzureIoTClient 36:f78f9a56869e 399 messenger_disposition_result = TELEMETRY_MESSENGER_DISPOSITION_RESULT_RELEASED;
AzureIoTClient 34:51d158b409d2 400 break;
AzureIoTClient 34:51d158b409d2 401 }
AzureIoTClient 30:20a85b733111 402
AzureIoTClient 34:51d158b409d2 403 return messenger_disposition_result;
AzureIoTClient 30:20a85b733111 404 }
AzureIoTClient 30:20a85b733111 405
AzureIoTClient 36:f78f9a56869e 406 static TELEMETRY_MESSENGER_DISPOSITION_RESULT on_messenger_message_received_callback(IOTHUB_MESSAGE_HANDLE iothub_message_handle, TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO* disposition_info, void* context)
AzureIoTClient 30:20a85b733111 407 {
AzureIoTClient 36:f78f9a56869e 408 TELEMETRY_MESSENGER_DISPOSITION_RESULT msgr_disposition_result;
AzureIoTClient 30:20a85b733111 409
AzureIoTClient 36:f78f9a56869e 410 // Codes_SRS_DEVICE_09_070: [If `iothub_message_handle` or `context` is NULL, on_messenger_message_received_callback shall return TELEMETRY_MESSENGER_DISPOSITION_RESULT_RELEASED]
AzureIoTClient 34:51d158b409d2 411 if (iothub_message_handle == NULL || context == NULL)
AzureIoTClient 34:51d158b409d2 412 {
AzureIoTClient 34:51d158b409d2 413 LogError("Failed receiving incoming C2D message (message handle (%p) or context (%p) is NULL)", iothub_message_handle, context);
AzureIoTClient 36:f78f9a56869e 414 msgr_disposition_result = TELEMETRY_MESSENGER_DISPOSITION_RESULT_RELEASED;
AzureIoTClient 34:51d158b409d2 415 }
AzureIoTClient 34:51d158b409d2 416 else
AzureIoTClient 34:51d158b409d2 417 {
AzureIoTClient 51:269e65571b39 418 AMQP_DEVICE_INSTANCE* device_instance = (AMQP_DEVICE_INSTANCE*)context;
AzureIoTClient 30:20a85b733111 419
AzureIoTClient 34:51d158b409d2 420 if (device_instance->on_message_received_callback == NULL)
AzureIoTClient 34:51d158b409d2 421 {
AzureIoTClient 34:51d158b409d2 422 LogError("Device '%s' failed receiving incoming C2D message (callback is NULL)", device_instance->config->device_id);
AzureIoTClient 36:f78f9a56869e 423 msgr_disposition_result = TELEMETRY_MESSENGER_DISPOSITION_RESULT_RELEASED;
AzureIoTClient 34:51d158b409d2 424 }
AzureIoTClient 34:51d158b409d2 425 else
AzureIoTClient 34:51d158b409d2 426 {
AzureIoTClient 34:51d158b409d2 427 DEVICE_MESSAGE_DISPOSITION_INFO* device_message_disposition_info;
AzureIoTClient 30:20a85b733111 428
AzureIoTClient 34:51d158b409d2 429 // Codes_SRS_DEVICE_09_119: [A DEVICE_MESSAGE_DISPOSITION_INFO instance shall be created containing a copy of `disposition_info->source` and `disposition_info->message_id`]
AzureIoTClient 34:51d158b409d2 430 if ((device_message_disposition_info = create_device_message_disposition_info_from(disposition_info)) == NULL)
AzureIoTClient 34:51d158b409d2 431 {
AzureIoTClient 36:f78f9a56869e 432 // Codes_SRS_DEVICE_09_120: [If the DEVICE_MESSAGE_DISPOSITION_INFO instance fails to be created, on_messenger_message_received_callback shall return TELEMETRY_MESSENGER_DISPOSITION_RESULT_RELEASED]
AzureIoTClient 34:51d158b409d2 433 LogError("Device '%s' failed receiving incoming C2D message (failed creating DEVICE_MESSAGE_DISPOSITION_INFO)", device_instance->config->device_id);
AzureIoTClient 36:f78f9a56869e 434 msgr_disposition_result = TELEMETRY_MESSENGER_DISPOSITION_RESULT_RELEASED;
AzureIoTClient 34:51d158b409d2 435 }
AzureIoTClient 34:51d158b409d2 436 else
AzureIoTClient 34:51d158b409d2 437 {
AzureIoTClient 34:51d158b409d2 438 // Codes_SRS_DEVICE_09_071: [The user callback shall be invoked, passing the context it provided]
AzureIoTClient 34:51d158b409d2 439 DEVICE_MESSAGE_DISPOSITION_RESULT device_disposition_result = device_instance->on_message_received_callback(iothub_message_handle, device_message_disposition_info, device_instance->on_message_received_context);
AzureIoTClient 30:20a85b733111 440
AzureIoTClient 36:f78f9a56869e 441 // Codes_SRS_DEVICE_09_072: [If the user callback returns DEVICE_MESSAGE_DISPOSITION_RESULT_ACCEPTED, on_messenger_message_received_callback shall return TELEMETRY_MESSENGER_DISPOSITION_RESULT_ACCEPTED]
AzureIoTClient 36:f78f9a56869e 442 // Codes_SRS_DEVICE_09_073: [If the user callback returns DEVICE_MESSAGE_DISPOSITION_RESULT_REJECTED, on_messenger_message_received_callback shall return TELEMETRY_MESSENGER_DISPOSITION_RESULT_REJECTED]
AzureIoTClient 36:f78f9a56869e 443 // Codes_SRS_DEVICE_09_074: [If the user callback returns DEVICE_MESSAGE_DISPOSITION_RESULT_RELEASED, on_messenger_message_received_callback shall return TELEMETRY_MESSENGER_DISPOSITION_RESULT_RELEASED]
AzureIoTClient 34:51d158b409d2 444 msgr_disposition_result = get_messenger_message_disposition_result_from(device_disposition_result);
AzureIoTClient 30:20a85b733111 445
AzureIoTClient 34:51d158b409d2 446 // Codes_SRS_DEVICE_09_121: [on_messenger_message_received_callback shall release the memory allocated for DEVICE_MESSAGE_DISPOSITION_INFO]
AzureIoTClient 34:51d158b409d2 447 destroy_device_disposition_info(device_message_disposition_info);
AzureIoTClient 34:51d158b409d2 448 }
AzureIoTClient 34:51d158b409d2 449 }
AzureIoTClient 34:51d158b409d2 450 }
AzureIoTClient 30:20a85b733111 451
AzureIoTClient 34:51d158b409d2 452 return msgr_disposition_result;
AzureIoTClient 30:20a85b733111 453 }
AzureIoTClient 30:20a85b733111 454
AzureIoTClient 39:e98d5df6dc74 455
AzureIoTClient 39:e98d5df6dc74 456 //---------- Configuration Helpers ----------//
AzureIoTClient 39:e98d5df6dc74 457
AzureIoTClient 30:20a85b733111 458 static void destroy_device_config(DEVICE_CONFIG* config)
AzureIoTClient 30:20a85b733111 459 {
AzureIoTClient 34:51d158b409d2 460 if (config != NULL)
AzureIoTClient 34:51d158b409d2 461 {
AzureIoTClient 34:51d158b409d2 462 free(config->product_info);
AzureIoTClient 34:51d158b409d2 463 free(config->iothub_host_fqdn);
AzureIoTClient 34:51d158b409d2 464 free(config);
AzureIoTClient 34:51d158b409d2 465 }
AzureIoTClient 30:20a85b733111 466 }
AzureIoTClient 30:20a85b733111 467
AzureIoTClient 30:20a85b733111 468 static DEVICE_CONFIG* clone_device_config(DEVICE_CONFIG *config)
AzureIoTClient 30:20a85b733111 469 {
AzureIoTClient 34:51d158b409d2 470 DEVICE_CONFIG* new_config;
AzureIoTClient 30:20a85b733111 471
AzureIoTClient 34:51d158b409d2 472 if ((new_config = (DEVICE_CONFIG*)malloc(sizeof(DEVICE_CONFIG))) == NULL)
AzureIoTClient 34:51d158b409d2 473 {
AzureIoTClient 34:51d158b409d2 474 LogError("Failed copying the DEVICE_CONFIG (malloc failed)");
AzureIoTClient 34:51d158b409d2 475 }
AzureIoTClient 34:51d158b409d2 476 else
AzureIoTClient 34:51d158b409d2 477 {
AzureIoTClient 34:51d158b409d2 478 int result;
AzureIoTClient 34:51d158b409d2 479 memset(new_config, 0, sizeof(DEVICE_CONFIG));
AzureIoTClient 30:20a85b733111 480
AzureIoTClient 34:51d158b409d2 481 if (config->product_info != NULL &&
AzureIoTClient 34:51d158b409d2 482 mallocAndStrcpy_s(&new_config->product_info, config->product_info) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 483 {
AzureIoTClient 34:51d158b409d2 484 LogError("Failed copying the DEVICE_CONFIG (failed copying product_info)");
AzureIoTClient 34:51d158b409d2 485 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 486 }
AzureIoTClient 34:51d158b409d2 487 else if (mallocAndStrcpy_s(&new_config->iothub_host_fqdn, config->iothub_host_fqdn) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 488 {
AzureIoTClient 34:51d158b409d2 489 LogError("Failed copying the DEVICE_CONFIG (failed copying iothub_host_fqdn)");
AzureIoTClient 34:51d158b409d2 490 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 491 }
AzureIoTClient 34:51d158b409d2 492 else
AzureIoTClient 34:51d158b409d2 493 {
AzureIoTClient 34:51d158b409d2 494 new_config->authorization_module = config->authorization_module;
AzureIoTClient 34:51d158b409d2 495 new_config->authentication_mode = config->authentication_mode;
AzureIoTClient 34:51d158b409d2 496 new_config->on_state_changed_callback = config->on_state_changed_callback;
AzureIoTClient 34:51d158b409d2 497 new_config->on_state_changed_context = config->on_state_changed_context;
AzureIoTClient 34:51d158b409d2 498 new_config->device_id = IoTHubClient_Auth_Get_DeviceId(config->authorization_module);
AzureIoTClient 54:830550fef7ea 499 new_config->module_id = IoTHubClient_Auth_Get_ModuleId(config->authorization_module);
AzureIoTClient 34:51d158b409d2 500 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 501 }
AzureIoTClient 30:20a85b733111 502
AzureIoTClient 34:51d158b409d2 503 if (result != RESULT_OK)
AzureIoTClient 34:51d158b409d2 504 {
AzureIoTClient 34:51d158b409d2 505 destroy_device_config(new_config);
AzureIoTClient 34:51d158b409d2 506 new_config = NULL;
AzureIoTClient 34:51d158b409d2 507 }
AzureIoTClient 34:51d158b409d2 508 }
AzureIoTClient 30:20a85b733111 509
AzureIoTClient 34:51d158b409d2 510 return new_config;
AzureIoTClient 30:20a85b733111 511 }
AzureIoTClient 30:20a85b733111 512
AzureIoTClient 51:269e65571b39 513 static void set_authentication_config(AMQP_DEVICE_INSTANCE* device_instance, AUTHENTICATION_CONFIG* auth_config)
AzureIoTClient 30:20a85b733111 514 {
AzureIoTClient 34:51d158b409d2 515 DEVICE_CONFIG *device_config = device_instance->config;
AzureIoTClient 30:20a85b733111 516
AzureIoTClient 34:51d158b409d2 517 auth_config->device_id = device_config->device_id;
AzureIoTClient 54:830550fef7ea 518 auth_config->module_id = device_config->module_id;
AzureIoTClient 34:51d158b409d2 519 auth_config->iothub_host_fqdn = device_config->iothub_host_fqdn;
AzureIoTClient 34:51d158b409d2 520 auth_config->on_error_callback = on_authentication_error_callback;
AzureIoTClient 34:51d158b409d2 521 auth_config->on_error_callback_context = device_instance;
AzureIoTClient 34:51d158b409d2 522 auth_config->on_state_changed_callback = on_authentication_state_changed_callback;
AzureIoTClient 34:51d158b409d2 523 auth_config->on_state_changed_callback_context = device_instance;
AzureIoTClient 34:51d158b409d2 524 auth_config->authorization_module = device_config->authorization_module;
AzureIoTClient 30:20a85b733111 525 }
AzureIoTClient 30:20a85b733111 526
AzureIoTClient 30:20a85b733111 527 // Create and Destroy Helpers
AzureIoTClient 51:269e65571b39 528 static void internal_destroy_device(AMQP_DEVICE_INSTANCE* instance)
AzureIoTClient 30:20a85b733111 529 {
AzureIoTClient 34:51d158b409d2 530 if (instance != NULL)
AzureIoTClient 34:51d158b409d2 531 {
AzureIoTClient 34:51d158b409d2 532 if (instance->messenger_handle != NULL)
AzureIoTClient 34:51d158b409d2 533 {
AzureIoTClient 36:f78f9a56869e 534 telemetry_messenger_destroy(instance->messenger_handle);
AzureIoTClient 34:51d158b409d2 535 }
AzureIoTClient 30:20a85b733111 536
AzureIoTClient 41:71c01aa3df1a 537 if (instance->twin_messenger_handle != NULL)
AzureIoTClient 41:71c01aa3df1a 538 {
AzureIoTClient 41:71c01aa3df1a 539 twin_messenger_destroy(instance->twin_messenger_handle);
AzureIoTClient 41:71c01aa3df1a 540 }
AzureIoTClient 39:e98d5df6dc74 541
AzureIoTClient 34:51d158b409d2 542 if (instance->authentication_handle != NULL)
AzureIoTClient 34:51d158b409d2 543 {
AzureIoTClient 34:51d158b409d2 544 authentication_destroy(instance->authentication_handle);
AzureIoTClient 34:51d158b409d2 545 }
AzureIoTClient 30:20a85b733111 546
AzureIoTClient 34:51d158b409d2 547 destroy_device_config(instance->config);
AzureIoTClient 34:51d158b409d2 548 free(instance);
AzureIoTClient 34:51d158b409d2 549 }
AzureIoTClient 30:20a85b733111 550 }
AzureIoTClient 30:20a85b733111 551
AzureIoTClient 51:269e65571b39 552 static int create_authentication_instance(AMQP_DEVICE_INSTANCE *instance)
AzureIoTClient 30:20a85b733111 553 {
AzureIoTClient 34:51d158b409d2 554 int result;
AzureIoTClient 34:51d158b409d2 555 AUTHENTICATION_CONFIG auth_config;
AzureIoTClient 30:20a85b733111 556
AzureIoTClient 34:51d158b409d2 557 set_authentication_config(instance, &auth_config);
AzureIoTClient 30:20a85b733111 558
AzureIoTClient 34:51d158b409d2 559 if ((instance->authentication_handle = authentication_create(&auth_config)) == NULL)
AzureIoTClient 34:51d158b409d2 560 {
AzureIoTClient 34:51d158b409d2 561 LogError("Failed creating the AUTHENTICATION_HANDLE (authentication_create failed)");
AzureIoTClient 34:51d158b409d2 562 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 563 }
AzureIoTClient 34:51d158b409d2 564 else
AzureIoTClient 34:51d158b409d2 565 {
AzureIoTClient 34:51d158b409d2 566 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 567 }
AzureIoTClient 30:20a85b733111 568
AzureIoTClient 34:51d158b409d2 569 return result;
AzureIoTClient 30:20a85b733111 570 }
AzureIoTClient 30:20a85b733111 571
AzureIoTClient 51:269e65571b39 572 static int create_telemetry_messenger_instance(AMQP_DEVICE_INSTANCE* instance, const char* pi)
AzureIoTClient 30:20a85b733111 573 {
AzureIoTClient 34:51d158b409d2 574 int result;
AzureIoTClient 30:20a85b733111 575
AzureIoTClient 36:f78f9a56869e 576 TELEMETRY_MESSENGER_CONFIG messenger_config;
AzureIoTClient 34:51d158b409d2 577 messenger_config.device_id = instance->config->device_id;
AzureIoTClient 54:830550fef7ea 578 messenger_config.module_id = instance->config->module_id;
AzureIoTClient 34:51d158b409d2 579 messenger_config.iothub_host_fqdn = instance->config->iothub_host_fqdn;
AzureIoTClient 34:51d158b409d2 580 messenger_config.on_state_changed_callback = on_messenger_state_changed_callback;
AzureIoTClient 34:51d158b409d2 581 messenger_config.on_state_changed_context = instance;
AzureIoTClient 30:20a85b733111 582
AzureIoTClient 36:f78f9a56869e 583 if ((instance->messenger_handle = telemetry_messenger_create(&messenger_config, pi)) == NULL)
AzureIoTClient 34:51d158b409d2 584 {
AzureIoTClient 36:f78f9a56869e 585 LogError("Failed creating the TELEMETRY_MESSENGER_HANDLE (messenger_create failed)");
AzureIoTClient 34:51d158b409d2 586 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 587 }
AzureIoTClient 34:51d158b409d2 588 else
AzureIoTClient 34:51d158b409d2 589 {
AzureIoTClient 34:51d158b409d2 590 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 591 }
AzureIoTClient 30:20a85b733111 592
AzureIoTClient 34:51d158b409d2 593 return result;
AzureIoTClient 30:20a85b733111 594 }
AzureIoTClient 30:20a85b733111 595
AzureIoTClient 51:269e65571b39 596 static int create_twin_messenger(AMQP_DEVICE_INSTANCE* instance)
AzureIoTClient 39:e98d5df6dc74 597 {
AzureIoTClient 41:71c01aa3df1a 598 int result;
AzureIoTClient 41:71c01aa3df1a 599 TWIN_MESSENGER_CONFIG twin_msgr_config;
AzureIoTClient 39:e98d5df6dc74 600
AzureIoTClient 41:71c01aa3df1a 601 twin_msgr_config.client_version = instance->config->product_info;
AzureIoTClient 41:71c01aa3df1a 602 twin_msgr_config.device_id = instance->config->device_id;
AzureIoTClient 54:830550fef7ea 603 twin_msgr_config.module_id = instance->config->module_id;
AzureIoTClient 41:71c01aa3df1a 604 twin_msgr_config.iothub_host_fqdn = instance->config->iothub_host_fqdn;
AzureIoTClient 41:71c01aa3df1a 605 twin_msgr_config.on_state_changed_callback = on_twin_messenger_state_changed_callback;
AzureIoTClient 41:71c01aa3df1a 606 twin_msgr_config.on_state_changed_context = (void*)instance;
AzureIoTClient 39:e98d5df6dc74 607
AzureIoTClient 41:71c01aa3df1a 608 if ((instance->twin_messenger_handle = twin_messenger_create(&twin_msgr_config)) == NULL)
AzureIoTClient 41:71c01aa3df1a 609 {
AzureIoTClient 41:71c01aa3df1a 610 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 611 }
AzureIoTClient 41:71c01aa3df1a 612 else
AzureIoTClient 41:71c01aa3df1a 613 {
AzureIoTClient 41:71c01aa3df1a 614 result = RESULT_OK;
AzureIoTClient 41:71c01aa3df1a 615 }
AzureIoTClient 39:e98d5df6dc74 616
AzureIoTClient 41:71c01aa3df1a 617 return result;
AzureIoTClient 39:e98d5df6dc74 618 }
AzureIoTClient 39:e98d5df6dc74 619
AzureIoTClient 39:e98d5df6dc74 620
AzureIoTClient 30:20a85b733111 621 // ---------- Set/Retrieve Options Helpers ----------//
AzureIoTClient 39:e98d5df6dc74 622
AzureIoTClient 30:20a85b733111 623 static void* device_clone_option(const char* name, const void* value)
AzureIoTClient 30:20a85b733111 624 {
AzureIoTClient 34:51d158b409d2 625 void* result;
AzureIoTClient 30:20a85b733111 626
AzureIoTClient 34:51d158b409d2 627 if (name == NULL || value == NULL)
AzureIoTClient 34:51d158b409d2 628 {
AzureIoTClient 34:51d158b409d2 629 LogError("Failed to clone device option (either name (%p) or value (%p) is NULL)", name, value);
AzureIoTClient 34:51d158b409d2 630 result = NULL;
AzureIoTClient 34:51d158b409d2 631 }
AzureIoTClient 34:51d158b409d2 632 else
AzureIoTClient 34:51d158b409d2 633 {
AzureIoTClient 34:51d158b409d2 634 if (strcmp(DEVICE_OPTION_SAVED_AUTH_OPTIONS, name) == 0 ||
AzureIoTClient 34:51d158b409d2 635 strcmp(DEVICE_OPTION_SAVED_MESSENGER_OPTIONS, name) == 0)
AzureIoTClient 34:51d158b409d2 636 {
AzureIoTClient 34:51d158b409d2 637 if ((result = (void*)OptionHandler_Clone((OPTIONHANDLER_HANDLE)value)) == NULL)
AzureIoTClient 34:51d158b409d2 638 {
AzureIoTClient 34:51d158b409d2 639 LogError("Failed to clone device option (OptionHandler_Clone failed for option %s)", name);
AzureIoTClient 34:51d158b409d2 640 }
AzureIoTClient 34:51d158b409d2 641 }
AzureIoTClient 34:51d158b409d2 642 else
AzureIoTClient 34:51d158b409d2 643 {
AzureIoTClient 34:51d158b409d2 644 LogError("Failed to clone device option (option with name '%s' is not suppported)", name);
AzureIoTClient 34:51d158b409d2 645 result = NULL;
AzureIoTClient 34:51d158b409d2 646 }
AzureIoTClient 34:51d158b409d2 647 }
AzureIoTClient 30:20a85b733111 648
AzureIoTClient 34:51d158b409d2 649 return result;
AzureIoTClient 30:20a85b733111 650 }
AzureIoTClient 30:20a85b733111 651
AzureIoTClient 30:20a85b733111 652 static void device_destroy_option(const char* name, const void* value)
AzureIoTClient 30:20a85b733111 653 {
AzureIoTClient 34:51d158b409d2 654 if (name == NULL || value == NULL)
AzureIoTClient 34:51d158b409d2 655 {
AzureIoTClient 34:51d158b409d2 656 LogError("Failed to destroy device option (either name (%p) or value (%p) is NULL)", name, value);
AzureIoTClient 34:51d158b409d2 657 }
AzureIoTClient 34:51d158b409d2 658 else
AzureIoTClient 34:51d158b409d2 659 {
AzureIoTClient 34:51d158b409d2 660 if (strcmp(name, DEVICE_OPTION_SAVED_AUTH_OPTIONS) == 0 ||
AzureIoTClient 34:51d158b409d2 661 strcmp(name, DEVICE_OPTION_SAVED_MESSENGER_OPTIONS) == 0)
AzureIoTClient 34:51d158b409d2 662 {
AzureIoTClient 34:51d158b409d2 663 OptionHandler_Destroy((OPTIONHANDLER_HANDLE)value);
AzureIoTClient 34:51d158b409d2 664 }
AzureIoTClient 34:51d158b409d2 665 else
AzureIoTClient 34:51d158b409d2 666 {
AzureIoTClient 34:51d158b409d2 667 LogError("Failed to clone device option (option with name '%s' is not suppported)", name);
AzureIoTClient 34:51d158b409d2 668 }
AzureIoTClient 34:51d158b409d2 669 }
AzureIoTClient 30:20a85b733111 670 }
AzureIoTClient 30:20a85b733111 671
AzureIoTClient 39:e98d5df6dc74 672
AzureIoTClient 39:e98d5df6dc74 673 //---------- Public APIs ----------//
AzureIoTClient 39:e98d5df6dc74 674
AzureIoTClient 51:269e65571b39 675 AMQP_DEVICE_HANDLE device_create(DEVICE_CONFIG *config)
AzureIoTClient 30:20a85b733111 676 {
AzureIoTClient 51:269e65571b39 677 AMQP_DEVICE_INSTANCE *instance;
AzureIoTClient 30:20a85b733111 678
AzureIoTClient 34:51d158b409d2 679 // Codes_SRS_DEVICE_09_001: [If config, authorization_module or iothub_host_fqdn or on_state_changed_callback are NULL then device_create shall fail and return NULL]
AzureIoTClient 34:51d158b409d2 680 if (config == NULL)
AzureIoTClient 34:51d158b409d2 681 {
AzureIoTClient 34:51d158b409d2 682 LogError("Failed creating the device instance (config is NULL)");
AzureIoTClient 34:51d158b409d2 683 instance = NULL;
AzureIoTClient 34:51d158b409d2 684 }
AzureIoTClient 34:51d158b409d2 685 else if (config->iothub_host_fqdn == NULL)
AzureIoTClient 34:51d158b409d2 686 {
AzureIoTClient 34:51d158b409d2 687 LogError("Failed creating the device instance (config->iothub_host_fqdn is NULL)");
AzureIoTClient 34:51d158b409d2 688 instance = NULL;
AzureIoTClient 34:51d158b409d2 689 }
AzureIoTClient 34:51d158b409d2 690 else if (config->on_state_changed_callback == NULL)
AzureIoTClient 34:51d158b409d2 691 {
AzureIoTClient 34:51d158b409d2 692 LogError("Failed creating the device instance (config->on_state_changed_callback is NULL)");
AzureIoTClient 34:51d158b409d2 693 instance = NULL;
AzureIoTClient 34:51d158b409d2 694 }
AzureIoTClient 34:51d158b409d2 695 else if (config->authorization_module == NULL)
AzureIoTClient 34:51d158b409d2 696 {
AzureIoTClient 34:51d158b409d2 697 LogError("Failed creating the device instance (config->authorization_module is NULL)");
AzureIoTClient 34:51d158b409d2 698 instance = NULL;
AzureIoTClient 34:51d158b409d2 699 }
AzureIoTClient 34:51d158b409d2 700 // Codes_SRS_DEVICE_09_002: [device_create shall allocate memory for the device instance structure]
AzureIoTClient 51:269e65571b39 701 else if ((instance = (AMQP_DEVICE_INSTANCE*)malloc(sizeof(AMQP_DEVICE_INSTANCE))) == NULL)
AzureIoTClient 34:51d158b409d2 702 {
AzureIoTClient 34:51d158b409d2 703 // Codes_SRS_DEVICE_09_003: [If malloc fails, device_create shall fail and return NULL]
AzureIoTClient 34:51d158b409d2 704 LogError("Failed creating the device instance (malloc failed)");
AzureIoTClient 34:51d158b409d2 705 }
AzureIoTClient 34:51d158b409d2 706 else
AzureIoTClient 34:51d158b409d2 707 {
AzureIoTClient 34:51d158b409d2 708 int result;
AzureIoTClient 30:20a85b733111 709
AzureIoTClient 51:269e65571b39 710 memset(instance, 0, sizeof(AMQP_DEVICE_INSTANCE));
AzureIoTClient 30:20a85b733111 711
AzureIoTClient 34:51d158b409d2 712 // Codes_SRS_DEVICE_09_004: [All `config` parameters shall be saved into `instance`]
AzureIoTClient 34:51d158b409d2 713 if ((instance->config = clone_device_config(config)) == NULL)
AzureIoTClient 34:51d158b409d2 714 {
AzureIoTClient 34:51d158b409d2 715 // Codes_SRS_DEVICE_09_005: [If any `config` parameters fail to be saved into `instance`, device_create shall fail and return NULL]
AzureIoTClient 34:51d158b409d2 716 LogError("Failed creating the device instance for device '%s' (failed copying the configuration)", config->device_id);
AzureIoTClient 34:51d158b409d2 717 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 718 }
AzureIoTClient 34:51d158b409d2 719 // Codes_SRS_DEVICE_09_006: [If `instance->authentication_mode` is DEVICE_AUTH_MODE_CBS, `instance->authentication_handle` shall be set using authentication_create()]
AzureIoTClient 34:51d158b409d2 720 else if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS &&
AzureIoTClient 34:51d158b409d2 721 create_authentication_instance(instance) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 722 {
AzureIoTClient 34:51d158b409d2 723 // Codes_SRS_DEVICE_09_007: [If the AUTHENTICATION_HANDLE fails to be created, device_create shall fail and return NULL]
AzureIoTClient 34:51d158b409d2 724 LogError("Failed creating the device instance for device '%s' (failed creating the authentication instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 725 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 726 }
AzureIoTClient 36:f78f9a56869e 727 // Codes_SRS_DEVICE_09_008: [`instance->messenger_handle` shall be set using telemetry_messenger_create()]
AzureIoTClient 39:e98d5df6dc74 728 else if (create_telemetry_messenger_instance(instance, config->product_info) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 729 {
AzureIoTClient 36:f78f9a56869e 730 // Codes_SRS_DEVICE_09_009: [If the TELEMETRY_MESSENGER_HANDLE fails to be created, device_create shall fail and return NULL]
AzureIoTClient 34:51d158b409d2 731 LogError("Failed creating the device instance for device '%s' (failed creating the messenger instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 732 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 733 }
AzureIoTClient 41:71c01aa3df1a 734 // Codes_SRS_DEVICE_09_122: [`instance->twin_messenger_handle` shall be set using twin_messenger_create()]
AzureIoTClient 41:71c01aa3df1a 735 else if (create_twin_messenger(instance) != RESULT_OK)
AzureIoTClient 41:71c01aa3df1a 736 {
AzureIoTClient 41:71c01aa3df1a 737 // Codes_SRS_DEVICE_09_123: [If the TWIN_MESSENGER_HANDLE fails to be created, device_create shall fail and return NULL]
AzureIoTClient 41:71c01aa3df1a 738 LogError("Failed creating the twin messenger for device '%s'", instance->config->device_id);
AzureIoTClient 41:71c01aa3df1a 739 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 740 }
AzureIoTClient 34:51d158b409d2 741 else
AzureIoTClient 34:51d158b409d2 742 {
AzureIoTClient 34:51d158b409d2 743 instance->auth_state = AUTHENTICATION_STATE_STOPPED;
AzureIoTClient 41:71c01aa3df1a 744 instance->msgr_state = TELEMETRY_MESSENGER_STATE_STOPPED;
AzureIoTClient 41:71c01aa3df1a 745 instance->twin_msgr_state = TWIN_MESSENGER_STATE_STOPPED;
AzureIoTClient 34:51d158b409d2 746 instance->state = DEVICE_STATE_STOPPED;
AzureIoTClient 34:51d158b409d2 747 instance->auth_state_last_changed_time = INDEFINITE_TIME;
AzureIoTClient 34:51d158b409d2 748 instance->auth_state_change_timeout_secs = DEFAULT_AUTH_STATE_CHANGED_TIMEOUT_SECS;
AzureIoTClient 34:51d158b409d2 749 instance->msgr_state_last_changed_time = INDEFINITE_TIME;
AzureIoTClient 34:51d158b409d2 750 instance->msgr_state_change_timeout_secs = DEFAULT_MSGR_STATE_CHANGED_TIMEOUT_SECS;
AzureIoTClient 41:71c01aa3df1a 751 instance->twin_msgr_state_last_changed_time = INDEFINITE_TIME;
AzureIoTClient 41:71c01aa3df1a 752 instance->twin_msgr_state_change_timeout_secs = DEFAULT_MSGR_STATE_CHANGED_TIMEOUT_SECS;
AzureIoTClient 30:20a85b733111 753
AzureIoTClient 34:51d158b409d2 754 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 755 }
AzureIoTClient 30:20a85b733111 756
AzureIoTClient 34:51d158b409d2 757 if (result != RESULT_OK)
AzureIoTClient 34:51d158b409d2 758 {
AzureIoTClient 34:51d158b409d2 759 // Codes_SRS_DEVICE_09_010: [If device_create fails it shall release all memory it has allocated]
AzureIoTClient 34:51d158b409d2 760 internal_destroy_device(instance);
AzureIoTClient 34:51d158b409d2 761 instance = NULL;
AzureIoTClient 34:51d158b409d2 762 }
AzureIoTClient 34:51d158b409d2 763 }
AzureIoTClient 30:20a85b733111 764
AzureIoTClient 34:51d158b409d2 765 // Codes_SRS_DEVICE_09_011: [If device_create succeeds it shall return a handle to its `instance` structure]
AzureIoTClient 51:269e65571b39 766 return (AMQP_DEVICE_HANDLE)instance;
AzureIoTClient 30:20a85b733111 767 }
AzureIoTClient 30:20a85b733111 768
AzureIoTClient 51:269e65571b39 769 int device_start_async(AMQP_DEVICE_HANDLE handle, SESSION_HANDLE session_handle, CBS_HANDLE cbs_handle)
AzureIoTClient 30:20a85b733111 770 {
AzureIoTClient 34:51d158b409d2 771 int result;
AzureIoTClient 30:20a85b733111 772
AzureIoTClient 34:51d158b409d2 773 // Codes_SRS_DEVICE_09_017: [If `handle` is NULL, device_start_async shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 774 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 775 {
AzureIoTClient 34:51d158b409d2 776 LogError("Failed starting device (handle is NULL)");
AzureIoTClient 34:51d158b409d2 777 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 778 }
AzureIoTClient 34:51d158b409d2 779 else
AzureIoTClient 34:51d158b409d2 780 {
AzureIoTClient 51:269e65571b39 781 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 782
AzureIoTClient 34:51d158b409d2 783 // Codes_SRS_DEVICE_09_018: [If the device state is not DEVICE_STATE_STOPPED, device_start_async shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 784 if (instance->state != DEVICE_STATE_STOPPED)
AzureIoTClient 34:51d158b409d2 785 {
AzureIoTClient 34:51d158b409d2 786 LogError("Failed starting device (device is not stopped)");
AzureIoTClient 34:51d158b409d2 787 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 788 }
AzureIoTClient 34:51d158b409d2 789 // Codes_SRS_DEVICE_09_019: [If `session_handle` is NULL, device_start_async shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 790 else if (session_handle == NULL)
AzureIoTClient 34:51d158b409d2 791 {
AzureIoTClient 34:51d158b409d2 792 LogError("Failed starting device (session_handle is NULL)");
AzureIoTClient 34:51d158b409d2 793 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 794 }
AzureIoTClient 34:51d158b409d2 795 // Codes_SRS_DEVICE_09_020: [If using CBS authentication and `cbs_handle` is NULL, device_start_async shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 796 else if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS && cbs_handle == NULL)
AzureIoTClient 34:51d158b409d2 797 {
AzureIoTClient 34:51d158b409d2 798 LogError("Failed starting device (device using CBS authentication, but cbs_handle is NULL)");
AzureIoTClient 34:51d158b409d2 799 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 800 }
AzureIoTClient 34:51d158b409d2 801 else
AzureIoTClient 34:51d158b409d2 802 {
AzureIoTClient 34:51d158b409d2 803 // Codes_SRS_DEVICE_09_021: [`session_handle` and `cbs_handle` shall be saved into the `instance`]
AzureIoTClient 34:51d158b409d2 804 instance->session_handle = session_handle;
AzureIoTClient 34:51d158b409d2 805 instance->cbs_handle = cbs_handle;
AzureIoTClient 30:20a85b733111 806
AzureIoTClient 34:51d158b409d2 807 // Codes_SRS_DEVICE_09_022: [The device state shall be updated to DEVICE_STATE_STARTING, and state changed callback invoked]
AzureIoTClient 34:51d158b409d2 808 update_state(instance, DEVICE_STATE_STARTING);
AzureIoTClient 30:20a85b733111 809
AzureIoTClient 34:51d158b409d2 810 // Codes_SRS_DEVICE_09_023: [If no failures occur, device_start_async shall return 0]
AzureIoTClient 34:51d158b409d2 811 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 812 }
AzureIoTClient 34:51d158b409d2 813 }
AzureIoTClient 30:20a85b733111 814
AzureIoTClient 34:51d158b409d2 815 return result;
AzureIoTClient 30:20a85b733111 816 }
AzureIoTClient 30:20a85b733111 817
AzureIoTClient 30:20a85b733111 818 // @brief
AzureIoTClient 30:20a85b733111 819 // stops a device instance (stops messenger and authentication) synchronously.
AzureIoTClient 30:20a85b733111 820 // @returns
AzureIoTClient 30:20a85b733111 821 // 0 if the function succeeds, non-zero otherwise.
AzureIoTClient 51:269e65571b39 822 int device_stop(AMQP_DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 823 {
AzureIoTClient 34:51d158b409d2 824 int result;
AzureIoTClient 30:20a85b733111 825
AzureIoTClient 34:51d158b409d2 826 // Codes_SRS_DEVICE_09_024: [If `handle` is NULL, device_stop shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 827 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 828 {
AzureIoTClient 34:51d158b409d2 829 LogError("Failed stopping device (handle is NULL)");
AzureIoTClient 34:51d158b409d2 830 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 831 }
AzureIoTClient 34:51d158b409d2 832 else
AzureIoTClient 34:51d158b409d2 833 {
AzureIoTClient 51:269e65571b39 834 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 835
AzureIoTClient 34:51d158b409d2 836 // Codes_SRS_DEVICE_09_025: [If the device state is already DEVICE_STATE_STOPPED or DEVICE_STATE_STOPPING, device_stop shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 837 if (instance->state == DEVICE_STATE_STOPPED || instance->state == DEVICE_STATE_STOPPING)
AzureIoTClient 34:51d158b409d2 838 {
AzureIoTClient 34:51d158b409d2 839 LogError("Failed stopping device '%s' (device is already stopped or stopping)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 840 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 841 }
AzureIoTClient 34:51d158b409d2 842 else
AzureIoTClient 34:51d158b409d2 843 {
AzureIoTClient 34:51d158b409d2 844 // Codes_SRS_DEVICE_09_026: [The device state shall be updated to DEVICE_STATE_STOPPING, and state changed callback invoked]
AzureIoTClient 34:51d158b409d2 845 update_state(instance, DEVICE_STATE_STOPPING);
AzureIoTClient 30:20a85b733111 846
AzureIoTClient 36:f78f9a56869e 847 // Codes_SRS_DEVICE_09_027: [If `instance->messenger_handle` state is not TELEMETRY_MESSENGER_STATE_STOPPED, messenger_stop shall be invoked]
AzureIoTClient 56:8704100b3b54 848 if (instance->msgr_state != TELEMETRY_MESSENGER_STATE_STOPPED &&
AzureIoTClient 36:f78f9a56869e 849 instance->msgr_state != TELEMETRY_MESSENGER_STATE_STOPPING &&
AzureIoTClient 36:f78f9a56869e 850 telemetry_messenger_stop(instance->messenger_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 851 {
AzureIoTClient 34:51d158b409d2 852 // Codes_SRS_DEVICE_09_028: [If messenger_stop fails, the `instance` state shall be updated to DEVICE_STATE_ERROR_MSG and the function shall return non-zero result]
AzureIoTClient 39:e98d5df6dc74 853 LogError("Failed stopping device '%s' (telemetry_messenger_stop failed)", instance->config->device_id);
AzureIoTClient 39:e98d5df6dc74 854 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 855 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 39:e98d5df6dc74 856 }
AzureIoTClient 41:71c01aa3df1a 857 // Codes_SRS_DEVICE_09_131: [If `instance->twin_messenger_handle` state is not TWIN_MESSENGER_STATE_STOPPED, twin_messenger_stop shall be invoked]
AzureIoTClient 39:e98d5df6dc74 858 else if (instance->twin_msgr_state != TWIN_MESSENGER_STATE_STOPPED &&
AzureIoTClient 39:e98d5df6dc74 859 instance->twin_msgr_state != TWIN_MESSENGER_STATE_STOPPING &&
AzureIoTClient 39:e98d5df6dc74 860 twin_messenger_stop(instance->twin_messenger_handle) != RESULT_OK)
AzureIoTClient 39:e98d5df6dc74 861 {
AzureIoTClient 41:71c01aa3df1a 862 // Codes_SRS_DEVICE_09_132: [If twin_messenger_stop fails, the `instance` state shall be updated to DEVICE_STATE_ERROR_MSG and the function shall return non-zero result]
AzureIoTClient 41:71c01aa3df1a 863 LogError("Failed stopping device '%s' (twin_messenger_stop failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 864 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 865 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 866 }
AzureIoTClient 34:51d158b409d2 867 // Codes_SRS_DEVICE_09_029: [If CBS authentication is used, if `instance->authentication_handle` state is not AUTHENTICATION_STATE_STOPPED, authentication_stop shall be invoked]
AzureIoTClient 34:51d158b409d2 868 else if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS &&
AzureIoTClient 34:51d158b409d2 869 instance->auth_state != AUTHENTICATION_STATE_STOPPED &&
AzureIoTClient 34:51d158b409d2 870 authentication_stop(instance->authentication_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 871 {
AzureIoTClient 34:51d158b409d2 872 // Codes_SRS_DEVICE_09_030: [If authentication_stop fails, the `instance` state shall be updated to DEVICE_STATE_ERROR_AUTH and the function shall return non-zero result]
AzureIoTClient 34:51d158b409d2 873 LogError("Failed stopping device '%s' (authentication_stop failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 874 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 875 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 876 }
AzureIoTClient 34:51d158b409d2 877 else
AzureIoTClient 34:51d158b409d2 878 {
AzureIoTClient 34:51d158b409d2 879 // Codes_SRS_DEVICE_09_031: [The device state shall be updated to DEVICE_STATE_STOPPED, and state changed callback invoked]
AzureIoTClient 34:51d158b409d2 880 update_state(instance, DEVICE_STATE_STOPPED);
AzureIoTClient 30:20a85b733111 881
AzureIoTClient 34:51d158b409d2 882 // Codes_SRS_DEVICE_09_032: [If no failures occur, device_stop shall return 0]
AzureIoTClient 34:51d158b409d2 883 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 884 }
AzureIoTClient 34:51d158b409d2 885 }
AzureIoTClient 34:51d158b409d2 886 }
AzureIoTClient 30:20a85b733111 887
AzureIoTClient 34:51d158b409d2 888 return result;
AzureIoTClient 30:20a85b733111 889 }
AzureIoTClient 30:20a85b733111 890
AzureIoTClient 51:269e65571b39 891 void device_do_work(AMQP_DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 892 {
AzureIoTClient 34:51d158b409d2 893 // Codes_SRS_DEVICE_09_033: [If `handle` is NULL, device_do_work shall return]
AzureIoTClient 34:51d158b409d2 894 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 895 {
AzureIoTClient 34:51d158b409d2 896 LogError("Failed to perform device_do_work (handle is NULL)");
AzureIoTClient 34:51d158b409d2 897 }
AzureIoTClient 34:51d158b409d2 898 else
AzureIoTClient 34:51d158b409d2 899 {
AzureIoTClient 34:51d158b409d2 900 // Cranking the state monster:
AzureIoTClient 51:269e65571b39 901 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 902
AzureIoTClient 34:51d158b409d2 903 if (instance->state == DEVICE_STATE_STARTING)
AzureIoTClient 34:51d158b409d2 904 {
AzureIoTClient 34:51d158b409d2 905 // Codes_SRS_DEVICE_09_034: [If CBS authentication is used and authentication state is AUTHENTICATION_STATE_STOPPED, authentication_start shall be invoked]
AzureIoTClient 34:51d158b409d2 906 if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS)
AzureIoTClient 34:51d158b409d2 907 {
AzureIoTClient 34:51d158b409d2 908 if (instance->auth_state == AUTHENTICATION_STATE_STOPPED)
AzureIoTClient 34:51d158b409d2 909 {
AzureIoTClient 34:51d158b409d2 910 if (authentication_start(instance->authentication_handle, instance->cbs_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 911 {
AzureIoTClient 34:51d158b409d2 912 // Codes_SRS_DEVICE_09_035: [If authentication_start fails, the device state shall be updated to DEVICE_STATE_ERROR_AUTH]
AzureIoTClient 34:51d158b409d2 913 LogError("Device '%s' failed to be authenticated (authentication_start failed)", instance->config->device_id);
AzureIoTClient 30:20a85b733111 914
AzureIoTClient 34:51d158b409d2 915 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 916 }
AzureIoTClient 34:51d158b409d2 917 }
AzureIoTClient 34:51d158b409d2 918 // Codes_SRS_DEVICE_09_036: [If authentication state is AUTHENTICATION_STATE_STARTING, the device shall track the time since last event change and timeout if needed]
AzureIoTClient 34:51d158b409d2 919 else if (instance->auth_state == AUTHENTICATION_STATE_STARTING)
AzureIoTClient 34:51d158b409d2 920 {
AzureIoTClient 34:51d158b409d2 921 int is_timed_out;
AzureIoTClient 34:51d158b409d2 922 if (is_timeout_reached(instance->auth_state_last_changed_time, instance->auth_state_change_timeout_secs, &is_timed_out) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 923 {
AzureIoTClient 34:51d158b409d2 924 LogError("Device '%s' failed verifying the timeout for authentication start (is_timeout_reached failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 925 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 926 }
AzureIoTClient 34:51d158b409d2 927 // Codes_SRS_DEVICE_09_037: [If authentication_start times out, the device state shall be updated to DEVICE_STATE_ERROR_AUTH_TIMEOUT]
AzureIoTClient 34:51d158b409d2 928 else if (is_timed_out == 1)
AzureIoTClient 34:51d158b409d2 929 {
AzureIoTClient 34:51d158b409d2 930 LogError("Device '%s' authentication did not complete starting within expected timeout (%d)", instance->config->device_id, instance->auth_state_change_timeout_secs);
AzureIoTClient 30:20a85b733111 931
AzureIoTClient 34:51d158b409d2 932 update_state(instance, DEVICE_STATE_ERROR_AUTH_TIMEOUT);
AzureIoTClient 34:51d158b409d2 933 }
AzureIoTClient 34:51d158b409d2 934 }
AzureIoTClient 34:51d158b409d2 935 else if (instance->auth_state == AUTHENTICATION_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 936 {
AzureIoTClient 34:51d158b409d2 937 // Codes_SRS_DEVICE_09_038: [If authentication state is AUTHENTICATION_STATE_ERROR and error code is AUTH_FAILED, the device state shall be updated to DEVICE_STATE_ERROR_AUTH]
AzureIoTClient 34:51d158b409d2 938 if (instance->auth_error_code == AUTHENTICATION_ERROR_AUTH_FAILED)
AzureIoTClient 34:51d158b409d2 939 {
AzureIoTClient 34:51d158b409d2 940 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 941 }
AzureIoTClient 34:51d158b409d2 942 // Codes_SRS_DEVICE_09_039: [If authentication state is AUTHENTICATION_STATE_ERROR and error code is TIMEOUT, the device state shall be updated to DEVICE_STATE_ERROR_AUTH_TIMEOUT]
AzureIoTClient 34:51d158b409d2 943 else // DEVICE_STATE_ERROR_TIMEOUT
AzureIoTClient 34:51d158b409d2 944 {
AzureIoTClient 34:51d158b409d2 945 update_state(instance, DEVICE_STATE_ERROR_AUTH_TIMEOUT);
AzureIoTClient 34:51d158b409d2 946 }
AzureIoTClient 34:51d158b409d2 947 }
AzureIoTClient 34:51d158b409d2 948 // There is no AUTHENTICATION_STATE_STOPPING
AzureIoTClient 34:51d158b409d2 949 }
AzureIoTClient 30:20a85b733111 950
AzureIoTClient 34:51d158b409d2 951 // Codes_SRS_DEVICE_09_040: [Messenger shall not be started if using CBS authentication and authentication start has not completed yet]
AzureIoTClient 41:71c01aa3df1a 952 // Codes_SRS_DEVICE_09_124: [TWIN Messenger shall not be started if using CBS authentication and authentication start has not completed yet]
AzureIoTClient 41:71c01aa3df1a 953 if (instance->config->authentication_mode == DEVICE_AUTH_MODE_X509 || instance->auth_state == AUTHENTICATION_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 954 {
AzureIoTClient 41:71c01aa3df1a 955 size_t number_of_messengers_started = 0;
AzureIoTClient 39:e98d5df6dc74 956
AzureIoTClient 36:f78f9a56869e 957 // Codes_SRS_DEVICE_09_041: [If messenger state is TELEMETRY_MESSENGER_STATE_STOPPED, messenger_start shall be invoked]
AzureIoTClient 36:f78f9a56869e 958 if (instance->msgr_state == TELEMETRY_MESSENGER_STATE_STOPPED)
AzureIoTClient 34:51d158b409d2 959 {
AzureIoTClient 34:51d158b409d2 960 // Codes_SRS_DEVICE_09_042: [If messenger_start fails, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 36:f78f9a56869e 961 if (telemetry_messenger_start(instance->messenger_handle, instance->session_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 962 {
AzureIoTClient 34:51d158b409d2 963 LogError("Device '%s' messenger failed to be started (messenger_start failed)", instance->config->device_id);
AzureIoTClient 30:20a85b733111 964
AzureIoTClient 34:51d158b409d2 965 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 966 }
AzureIoTClient 34:51d158b409d2 967 }
AzureIoTClient 36:f78f9a56869e 968 // Codes_SRS_DEVICE_09_043: [If messenger state is TELEMETRY_MESSENGER_STATE_STARTING, the device shall track the time since last event change and timeout if needed]
AzureIoTClient 36:f78f9a56869e 969 else if (instance->msgr_state == TELEMETRY_MESSENGER_STATE_STARTING)
AzureIoTClient 34:51d158b409d2 970 {
AzureIoTClient 34:51d158b409d2 971 int is_timed_out;
AzureIoTClient 34:51d158b409d2 972 if (is_timeout_reached(instance->msgr_state_last_changed_time, instance->msgr_state_change_timeout_secs, &is_timed_out) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 973 {
AzureIoTClient 34:51d158b409d2 974 LogError("Device '%s' failed verifying the timeout for messenger start (is_timeout_reached failed)", instance->config->device_id);
AzureIoTClient 30:20a85b733111 975
AzureIoTClient 34:51d158b409d2 976 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 977 }
AzureIoTClient 34:51d158b409d2 978 // Codes_SRS_DEVICE_09_044: [If messenger_start times out, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 34:51d158b409d2 979 else if (is_timed_out == 1)
AzureIoTClient 34:51d158b409d2 980 {
AzureIoTClient 34:51d158b409d2 981 LogError("Device '%s' messenger did not complete starting within expected timeout (%d)", instance->config->device_id, instance->msgr_state_change_timeout_secs);
AzureIoTClient 30:20a85b733111 982
AzureIoTClient 34:51d158b409d2 983 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 984 }
AzureIoTClient 34:51d158b409d2 985 }
AzureIoTClient 36:f78f9a56869e 986 // Codes_SRS_DEVICE_09_045: [If messenger state is TELEMETRY_MESSENGER_STATE_ERROR, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 36:f78f9a56869e 987 else if (instance->msgr_state == TELEMETRY_MESSENGER_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 988 {
AzureIoTClient 34:51d158b409d2 989 LogError("Device '%s' messenger failed to be started (messenger got into error state)", instance->config->device_id);
AzureIoTClient 56:8704100b3b54 990
AzureIoTClient 34:51d158b409d2 991 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 992 }
AzureIoTClient 36:f78f9a56869e 993 // Codes_SRS_DEVICE_09_046: [If messenger state is TELEMETRY_MESSENGER_STATE_STARTED, the device state shall be updated to DEVICE_STATE_STARTED]
AzureIoTClient 36:f78f9a56869e 994 else if (instance->msgr_state == TELEMETRY_MESSENGER_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 995 {
AzureIoTClient 41:71c01aa3df1a 996 number_of_messengers_started++;
AzureIoTClient 34:51d158b409d2 997 }
AzureIoTClient 39:e98d5df6dc74 998
AzureIoTClient 41:71c01aa3df1a 999 // Codes_SRS_DEVICE_09_125: [If TWIN messenger state is TWIN_MESSENGER_STATE_STOPPED, twin_messenger_start shall be invoked]
AzureIoTClient 41:71c01aa3df1a 1000 if (instance->twin_msgr_state == TWIN_MESSENGER_STATE_STOPPED)
AzureIoTClient 41:71c01aa3df1a 1001 {
AzureIoTClient 41:71c01aa3df1a 1002 if (twin_messenger_start(instance->twin_messenger_handle, instance->session_handle) != RESULT_OK)
AzureIoTClient 41:71c01aa3df1a 1003 {
AzureIoTClient 41:71c01aa3df1a 1004 // Codes_SRS_DEVICE_09_126: [If twin_messenger_start fails, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 41:71c01aa3df1a 1005 LogError("Device '%s' twin messenger failed to be started (messenger_start failed)", instance->config->device_id);
AzureIoTClient 39:e98d5df6dc74 1006
AzureIoTClient 41:71c01aa3df1a 1007 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 41:71c01aa3df1a 1008 }
AzureIoTClient 41:71c01aa3df1a 1009 }
AzureIoTClient 41:71c01aa3df1a 1010 else if (instance->twin_msgr_state == TWIN_MESSENGER_STATE_STARTING)
AzureIoTClient 41:71c01aa3df1a 1011 {
AzureIoTClient 41:71c01aa3df1a 1012 int is_timed_out;
AzureIoTClient 41:71c01aa3df1a 1013 if (is_timeout_reached(instance->twin_msgr_state_last_changed_time, instance->twin_msgr_state_change_timeout_secs, &is_timed_out) != RESULT_OK)
AzureIoTClient 41:71c01aa3df1a 1014 {
AzureIoTClient 41:71c01aa3df1a 1015 LogError("Device '%s' failed verifying the timeout for twin messenger start (is_timeout_reached failed)", instance->config->device_id);
AzureIoTClient 39:e98d5df6dc74 1016
AzureIoTClient 41:71c01aa3df1a 1017 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 41:71c01aa3df1a 1018 }
AzureIoTClient 41:71c01aa3df1a 1019 // Codes_SRS_DEVICE_09_127: [If TWIN messenger state is TWIN_MESSENGER_STATE_STARTING, the device shall track the time since last event change and timeout if needed]
AzureIoTClient 41:71c01aa3df1a 1020 else if (is_timed_out == 1)
AzureIoTClient 41:71c01aa3df1a 1021 {
AzureIoTClient 41:71c01aa3df1a 1022 // Codes_SRS_DEVICE_09_128: [If twin_messenger_start times out, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 41:71c01aa3df1a 1023 LogError("Device '%s' twin messenger did not complete starting within expected timeout (%d)", instance->config->device_id, instance->twin_msgr_state_change_timeout_secs);
AzureIoTClient 39:e98d5df6dc74 1024
AzureIoTClient 41:71c01aa3df1a 1025 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 41:71c01aa3df1a 1026 }
AzureIoTClient 41:71c01aa3df1a 1027 }
AzureIoTClient 41:71c01aa3df1a 1028 // Codes_SRS_DEVICE_09_129: [If TWIN messenger state is TWIN_MESSENGER_STATE_ERROR, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 41:71c01aa3df1a 1029 else if (instance->twin_msgr_state == TWIN_MESSENGER_STATE_ERROR)
AzureIoTClient 41:71c01aa3df1a 1030 {
AzureIoTClient 41:71c01aa3df1a 1031 LogError("Device '%s' twin messenger failed to be started (messenger got into error state)", instance->config->device_id);
AzureIoTClient 39:e98d5df6dc74 1032
AzureIoTClient 41:71c01aa3df1a 1033 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 41:71c01aa3df1a 1034 }
AzureIoTClient 41:71c01aa3df1a 1035 // Codes_SRS_DEVICE_09_130: [If TWIN messenger state is TWIN_MESSENGER_STATE_STARTED, the device state shall be updated to DEVICE_STATE_STARTED]
AzureIoTClient 41:71c01aa3df1a 1036 else if (instance->twin_msgr_state == TWIN_MESSENGER_STATE_STARTED)
AzureIoTClient 41:71c01aa3df1a 1037 {
AzureIoTClient 41:71c01aa3df1a 1038 number_of_messengers_started++;
AzureIoTClient 41:71c01aa3df1a 1039 }
AzureIoTClient 39:e98d5df6dc74 1040
AzureIoTClient 41:71c01aa3df1a 1041 if (number_of_messengers_started == 2)
AzureIoTClient 41:71c01aa3df1a 1042 {
AzureIoTClient 41:71c01aa3df1a 1043 update_state(instance, DEVICE_STATE_STARTED);
AzureIoTClient 41:71c01aa3df1a 1044 }
AzureIoTClient 34:51d158b409d2 1045 }
AzureIoTClient 34:51d158b409d2 1046 }
AzureIoTClient 34:51d158b409d2 1047 else if (instance->state == DEVICE_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 1048 {
AzureIoTClient 34:51d158b409d2 1049 // Codes_SRS_DEVICE_09_047: [If CBS authentication is used and authentication state is not AUTHENTICATION_STATE_STARTED, the device state shall be updated to DEVICE_STATE_ERROR_AUTH]
AzureIoTClient 34:51d158b409d2 1050 if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS &&
AzureIoTClient 34:51d158b409d2 1051 instance->auth_state != AUTHENTICATION_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 1052 {
AzureIoTClient 34:51d158b409d2 1053 LogError("Device '%s' is started but authentication reported unexpected state %d", instance->config->device_id, instance->auth_state);
AzureIoTClient 30:20a85b733111 1054
AzureIoTClient 34:51d158b409d2 1055 if (instance->auth_state != AUTHENTICATION_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 1056 {
AzureIoTClient 34:51d158b409d2 1057 if (instance->auth_error_code == AUTHENTICATION_ERROR_AUTH_FAILED)
AzureIoTClient 34:51d158b409d2 1058 {
AzureIoTClient 34:51d158b409d2 1059 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 1060 }
AzureIoTClient 34:51d158b409d2 1061 else // AUTHENTICATION_ERROR_AUTH_TIMEOUT
AzureIoTClient 34:51d158b409d2 1062 {
AzureIoTClient 34:51d158b409d2 1063 update_state(instance, DEVICE_STATE_ERROR_AUTH_TIMEOUT);
AzureIoTClient 34:51d158b409d2 1064 }
AzureIoTClient 34:51d158b409d2 1065 }
AzureIoTClient 34:51d158b409d2 1066 else
AzureIoTClient 34:51d158b409d2 1067 {
AzureIoTClient 34:51d158b409d2 1068 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 1069 }
AzureIoTClient 34:51d158b409d2 1070 }
AzureIoTClient 34:51d158b409d2 1071 else
AzureIoTClient 34:51d158b409d2 1072 {
AzureIoTClient 36:f78f9a56869e 1073 // Codes_SRS_DEVICE_09_048: [If messenger state is not TELEMETRY_MESSENGER_STATE_STARTED, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 36:f78f9a56869e 1074 if (instance->msgr_state != TELEMETRY_MESSENGER_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 1075 {
AzureIoTClient 34:51d158b409d2 1076 LogError("Device '%s' is started but messenger reported unexpected state %d", instance->config->device_id, instance->msgr_state);
AzureIoTClient 34:51d158b409d2 1077 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 1078 }
AzureIoTClient 39:e98d5df6dc74 1079
AzureIoTClient 41:71c01aa3df1a 1080 // Codes_SRS_DEVICE_09_133: [If TWIN messenger state is not TWIN_MESSENGER_STATE_STARTED, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 41:71c01aa3df1a 1081 if (instance->twin_msgr_state != TWIN_MESSENGER_STATE_STARTED)
AzureIoTClient 41:71c01aa3df1a 1082 {
AzureIoTClient 41:71c01aa3df1a 1083 LogError("Device '%s' is started but TWIN messenger reported unexpected state %d", instance->config->device_id, instance->msgr_state);
AzureIoTClient 41:71c01aa3df1a 1084 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 41:71c01aa3df1a 1085 }
AzureIoTClient 34:51d158b409d2 1086 }
AzureIoTClient 34:51d158b409d2 1087 }
AzureIoTClient 30:20a85b733111 1088
AzureIoTClient 34:51d158b409d2 1089 // Invoking the do_works():
AzureIoTClient 34:51d158b409d2 1090 if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS)
AzureIoTClient 34:51d158b409d2 1091 {
AzureIoTClient 34:51d158b409d2 1092 if (instance->auth_state != AUTHENTICATION_STATE_STOPPED && instance->auth_state != AUTHENTICATION_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 1093 {
AzureIoTClient 34:51d158b409d2 1094 // Codes_SRS_DEVICE_09_049: [If CBS is used for authentication and `instance->authentication_handle` state is not STOPPED or ERROR, authentication_do_work shall be invoked]
AzureIoTClient 34:51d158b409d2 1095 authentication_do_work(instance->authentication_handle);
AzureIoTClient 34:51d158b409d2 1096 }
AzureIoTClient 34:51d158b409d2 1097 }
AzureIoTClient 30:20a85b733111 1098
AzureIoTClient 36:f78f9a56869e 1099 if (instance->msgr_state != TELEMETRY_MESSENGER_STATE_STOPPED && instance->msgr_state != TELEMETRY_MESSENGER_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 1100 {
AzureIoTClient 39:e98d5df6dc74 1101 // Codes_SRS_DEVICE_09_050: [If `instance->messenger_handle` state is not STOPPED or ERROR, telemetry_messenger_do_work shall be invoked]
AzureIoTClient 36:f78f9a56869e 1102 telemetry_messenger_do_work(instance->messenger_handle);
AzureIoTClient 34:51d158b409d2 1103 }
AzureIoTClient 39:e98d5df6dc74 1104
AzureIoTClient 41:71c01aa3df1a 1105 if (instance->twin_msgr_state != TWIN_MESSENGER_STATE_STOPPED && instance->twin_msgr_state != TWIN_MESSENGER_STATE_ERROR)
AzureIoTClient 41:71c01aa3df1a 1106 {
AzureIoTClient 41:71c01aa3df1a 1107 // Codes_SRS_DEVICE_09_134: [If `instance->twin_messenger_handle` state is not STOPPED or ERROR, twin_messenger_do_work shall be invoked]
AzureIoTClient 41:71c01aa3df1a 1108 twin_messenger_do_work(instance->twin_messenger_handle);
AzureIoTClient 41:71c01aa3df1a 1109 }
AzureIoTClient 34:51d158b409d2 1110 }
AzureIoTClient 30:20a85b733111 1111 }
AzureIoTClient 30:20a85b733111 1112
AzureIoTClient 51:269e65571b39 1113 void device_destroy(AMQP_DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 1114 {
AzureIoTClient 34:51d158b409d2 1115 // Codes_SRS_DEVICE_09_012: [If `handle` is NULL, device_destroy shall return]
AzureIoTClient 34:51d158b409d2 1116 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 1117 {
AzureIoTClient 34:51d158b409d2 1118 LogError("Failed destroying device handle (handle is NULL)");
AzureIoTClient 34:51d158b409d2 1119 }
AzureIoTClient 34:51d158b409d2 1120 else
AzureIoTClient 34:51d158b409d2 1121 {
AzureIoTClient 51:269e65571b39 1122 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 34:51d158b409d2 1123 // Codes_SRS_DEVICE_09_013: [If the device is in state DEVICE_STATE_STARTED or DEVICE_STATE_STARTING, device_stop() shall be invoked]
AzureIoTClient 34:51d158b409d2 1124 if (instance->state == DEVICE_STATE_STARTED || instance->state == DEVICE_STATE_STARTING)
AzureIoTClient 34:51d158b409d2 1125 {
AzureIoTClient 51:269e65571b39 1126 (void)device_stop((AMQP_DEVICE_HANDLE)instance);
AzureIoTClient 34:51d158b409d2 1127 }
AzureIoTClient 30:20a85b733111 1128
AzureIoTClient 36:f78f9a56869e 1129 // Codes_SRS_DEVICE_09_014: [`instance->messenger_handle shall be destroyed using telemetry_messenger_destroy()`]
AzureIoTClient 34:51d158b409d2 1130 // Codes_SRS_DEVICE_09_015: [If created, `instance->authentication_handle` shall be destroyed using authentication_destroy()`]
AzureIoTClient 34:51d158b409d2 1131 // Codes_SRS_DEVICE_09_016: [The contents of `instance->config` shall be detroyed and then it shall be freed]
AzureIoTClient 51:269e65571b39 1132 internal_destroy_device((AMQP_DEVICE_INSTANCE*)handle);
AzureIoTClient 34:51d158b409d2 1133 }
AzureIoTClient 30:20a85b733111 1134 }
AzureIoTClient 30:20a85b733111 1135
AzureIoTClient 51:269e65571b39 1136 int device_send_event_async(AMQP_DEVICE_HANDLE handle, IOTHUB_MESSAGE_LIST* message, ON_DEVICE_D2C_EVENT_SEND_COMPLETE on_device_d2c_event_send_complete_callback, void* context)
AzureIoTClient 30:20a85b733111 1137 {
AzureIoTClient 34:51d158b409d2 1138 int result;
AzureIoTClient 30:20a85b733111 1139
AzureIoTClient 34:51d158b409d2 1140 // Codes_SRS_DEVICE_09_051: [If `handle` are `message` are NULL, device_send_event_async shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1141 if (handle == NULL || message == NULL)
AzureIoTClient 34:51d158b409d2 1142 {
AzureIoTClient 34:51d158b409d2 1143 LogError("Failed sending event (either handle (%p) or message (%p) are NULL)", handle, message);
AzureIoTClient 34:51d158b409d2 1144 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1145 }
AzureIoTClient 34:51d158b409d2 1146 else
AzureIoTClient 34:51d158b409d2 1147 {
AzureIoTClient 34:51d158b409d2 1148 DEVICE_SEND_EVENT_TASK* send_task;
AzureIoTClient 30:20a85b733111 1149
AzureIoTClient 34:51d158b409d2 1150 // Codes_SRS_DEVICE_09_052: [A structure (`send_task`) shall be created to track the send state of the message]
AzureIoTClient 34:51d158b409d2 1151 if ((send_task = (DEVICE_SEND_EVENT_TASK*)malloc(sizeof(DEVICE_SEND_EVENT_TASK))) == NULL)
AzureIoTClient 34:51d158b409d2 1152 {
AzureIoTClient 34:51d158b409d2 1153 // Codes_SRS_DEVICE_09_053: [If `send_task` fails to be created, device_send_event_async shall return a non-zero value]
AzureIoTClient 34:51d158b409d2 1154 LogError("Failed sending event (failed creating task to send event)");
AzureIoTClient 34:51d158b409d2 1155 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1156 }
AzureIoTClient 34:51d158b409d2 1157 else
AzureIoTClient 34:51d158b409d2 1158 {
AzureIoTClient 51:269e65571b39 1159 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1160
AzureIoTClient 34:51d158b409d2 1161 // Codes_SRS_DEVICE_09_054: [`send_task` shall contain the user callback and the context provided]
AzureIoTClient 34:51d158b409d2 1162 memset(send_task, 0, sizeof(DEVICE_SEND_EVENT_TASK));
AzureIoTClient 34:51d158b409d2 1163 send_task->on_event_send_complete_callback = on_device_d2c_event_send_complete_callback;
AzureIoTClient 34:51d158b409d2 1164 send_task->on_event_send_complete_context = context;
AzureIoTClient 56:8704100b3b54 1165
AzureIoTClient 36:f78f9a56869e 1166 // Codes_SRS_DEVICE_09_055: [The message shall be sent using telemetry_messenger_send_async, passing `on_event_send_complete_messenger_callback` and `send_task`]
AzureIoTClient 36:f78f9a56869e 1167 if (telemetry_messenger_send_async(instance->messenger_handle, message, on_event_send_complete_messenger_callback, (void*)send_task) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1168 {
AzureIoTClient 36:f78f9a56869e 1169 // Codes_SRS_DEVICE_09_056: [If telemetry_messenger_send_async fails, device_send_event_async shall return a non-zero value]
AzureIoTClient 36:f78f9a56869e 1170 LogError("Failed sending event (telemetry_messenger_send_async failed)");
AzureIoTClient 34:51d158b409d2 1171 // Codes_SRS_DEVICE_09_057: [If any failures occur, device_send_event_async shall release all memory it has allocated]
AzureIoTClient 34:51d158b409d2 1172 free(send_task);
AzureIoTClient 34:51d158b409d2 1173 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1174 }
AzureIoTClient 34:51d158b409d2 1175 else
AzureIoTClient 56:8704100b3b54 1176 {
AzureIoTClient 34:51d158b409d2 1177 // Codes_SRS_DEVICE_09_058: [If no failures occur, device_send_event_async shall return 0]
AzureIoTClient 34:51d158b409d2 1178 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1179 }
AzureIoTClient 34:51d158b409d2 1180 }
AzureIoTClient 34:51d158b409d2 1181 }
AzureIoTClient 30:20a85b733111 1182
AzureIoTClient 34:51d158b409d2 1183 return result;
AzureIoTClient 30:20a85b733111 1184 }
AzureIoTClient 30:20a85b733111 1185
AzureIoTClient 51:269e65571b39 1186 int device_get_send_status(AMQP_DEVICE_HANDLE handle, DEVICE_SEND_STATUS *send_status)
AzureIoTClient 30:20a85b733111 1187 {
AzureIoTClient 34:51d158b409d2 1188 int result;
AzureIoTClient 30:20a85b733111 1189
AzureIoTClient 30:20a85b733111 1190
AzureIoTClient 34:51d158b409d2 1191 // Codes_SRS_DEVICE_09_105: [If `handle` or `send_status` is NULL, device_get_send_status shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1192 if (handle == NULL || send_status == NULL)
AzureIoTClient 34:51d158b409d2 1193 {
AzureIoTClient 34:51d158b409d2 1194 LogError("Failed getting the device messenger send status (NULL parameter received; handle=%p, send_status=%p)", handle, send_status);
AzureIoTClient 34:51d158b409d2 1195 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1196 }
AzureIoTClient 34:51d158b409d2 1197 else
AzureIoTClient 34:51d158b409d2 1198 {
AzureIoTClient 51:269e65571b39 1199 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 36:f78f9a56869e 1200 TELEMETRY_MESSENGER_SEND_STATUS messenger_send_status;
AzureIoTClient 56:8704100b3b54 1201
AzureIoTClient 36:f78f9a56869e 1202 // Codes_SRS_DEVICE_09_106: [The status of `instance->messenger_handle` shall be obtained using telemetry_messenger_get_send_status]
AzureIoTClient 36:f78f9a56869e 1203 if (telemetry_messenger_get_send_status(instance->messenger_handle, &messenger_send_status) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1204 {
AzureIoTClient 36:f78f9a56869e 1205 // Codes_SRS_DEVICE_09_107: [If telemetry_messenger_get_send_status fails, device_get_send_status shall return a non-zero result]
AzureIoTClient 36:f78f9a56869e 1206 LogError("Failed getting the device messenger send status (telemetry_messenger_get_send_status failed)");
AzureIoTClient 34:51d158b409d2 1207 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1208 }
AzureIoTClient 34:51d158b409d2 1209 else
AzureIoTClient 34:51d158b409d2 1210 {
AzureIoTClient 36:f78f9a56869e 1211 // Codes_SRS_DEVICE_09_108: [If telemetry_messenger_get_send_status returns TELEMETRY_MESSENGER_SEND_STATUS_IDLE, device_get_send_status return status DEVICE_SEND_STATUS_IDLE]
AzureIoTClient 36:f78f9a56869e 1212 if (messenger_send_status == TELEMETRY_MESSENGER_SEND_STATUS_IDLE)
AzureIoTClient 34:51d158b409d2 1213 {
AzureIoTClient 34:51d158b409d2 1214 *send_status = DEVICE_SEND_STATUS_IDLE;
AzureIoTClient 34:51d158b409d2 1215 }
AzureIoTClient 36:f78f9a56869e 1216 // Codes_SRS_DEVICE_09_109: [If telemetry_messenger_get_send_status returns TELEMETRY_MESSENGER_SEND_STATUS_BUSY, device_get_send_status return status DEVICE_SEND_STATUS_BUSY]
AzureIoTClient 36:f78f9a56869e 1217 else // i.e., messenger_send_status == TELEMETRY_MESSENGER_SEND_STATUS_BUSY
AzureIoTClient 34:51d158b409d2 1218 {
AzureIoTClient 34:51d158b409d2 1219 *send_status = DEVICE_SEND_STATUS_BUSY;
AzureIoTClient 34:51d158b409d2 1220 }
AzureIoTClient 30:20a85b733111 1221
AzureIoTClient 34:51d158b409d2 1222 // Codes_SRS_DEVICE_09_110: [If device_get_send_status succeeds, it shall return zero as result]
AzureIoTClient 34:51d158b409d2 1223 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1224 }
AzureIoTClient 34:51d158b409d2 1225 }
AzureIoTClient 30:20a85b733111 1226
AzureIoTClient 34:51d158b409d2 1227 return result;
AzureIoTClient 30:20a85b733111 1228 }
AzureIoTClient 30:20a85b733111 1229
AzureIoTClient 51:269e65571b39 1230 int device_subscribe_message(AMQP_DEVICE_HANDLE handle, ON_DEVICE_C2D_MESSAGE_RECEIVED on_message_received_callback, void* context)
AzureIoTClient 30:20a85b733111 1231 {
AzureIoTClient 34:51d158b409d2 1232 int result;
AzureIoTClient 30:20a85b733111 1233
AzureIoTClient 34:51d158b409d2 1234 // Codes_SRS_DEVICE_09_066: [If `handle` or `on_message_received_callback` or `context` is NULL, device_subscribe_message shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1235 if (handle == NULL || on_message_received_callback == NULL || context == NULL)
AzureIoTClient 34:51d158b409d2 1236 {
AzureIoTClient 34:51d158b409d2 1237 LogError("Failed subscribing to C2D messages (either handle (%p), on_message_received_callback (%p) or context (%p) is NULL)",
AzureIoTClient 34:51d158b409d2 1238 handle, on_message_received_callback, context);
AzureIoTClient 34:51d158b409d2 1239 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1240 }
AzureIoTClient 34:51d158b409d2 1241 else
AzureIoTClient 34:51d158b409d2 1242 {
AzureIoTClient 51:269e65571b39 1243 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1244
AzureIoTClient 36:f78f9a56869e 1245 // Codes_SRS_DEVICE_09_067: [telemetry_messenger_subscribe_for_messages shall be invoked passing `on_messenger_message_received_callback` and the user callback and context]
AzureIoTClient 36:f78f9a56869e 1246 if (telemetry_messenger_subscribe_for_messages(instance->messenger_handle, on_messenger_message_received_callback, handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1247 {
AzureIoTClient 36:f78f9a56869e 1248 // Codes_SRS_DEVICE_09_068: [If telemetry_messenger_subscribe_for_messages fails, device_subscribe_message shall return a non-zero result]
AzureIoTClient 36:f78f9a56869e 1249 LogError("Failed subscribing to C2D messages (telemetry_messenger_subscribe_for_messages failed)");
AzureIoTClient 34:51d158b409d2 1250 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1251 }
AzureIoTClient 34:51d158b409d2 1252 else
AzureIoTClient 34:51d158b409d2 1253 {
AzureIoTClient 34:51d158b409d2 1254 instance->on_message_received_callback = on_message_received_callback;
AzureIoTClient 34:51d158b409d2 1255 instance->on_message_received_context = context;
AzureIoTClient 30:20a85b733111 1256
AzureIoTClient 34:51d158b409d2 1257 // Codes_SRS_DEVICE_09_069: [If no failures occur, device_subscribe_message shall return 0]
AzureIoTClient 34:51d158b409d2 1258 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1259 }
AzureIoTClient 34:51d158b409d2 1260 }
AzureIoTClient 30:20a85b733111 1261
AzureIoTClient 34:51d158b409d2 1262 return result;
AzureIoTClient 30:20a85b733111 1263 }
AzureIoTClient 30:20a85b733111 1264
AzureIoTClient 51:269e65571b39 1265 int device_unsubscribe_message(AMQP_DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 1266 {
AzureIoTClient 34:51d158b409d2 1267 int result;
AzureIoTClient 30:20a85b733111 1268
AzureIoTClient 34:51d158b409d2 1269 // Codes_SRS_DEVICE_09_076: [If `handle` is NULL, device_unsubscribe_message shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1270 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 1271 {
AzureIoTClient 34:51d158b409d2 1272 LogError("Failed unsubscribing to C2D messages (handle is NULL)");
AzureIoTClient 34:51d158b409d2 1273 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1274 }
AzureIoTClient 34:51d158b409d2 1275 else
AzureIoTClient 34:51d158b409d2 1276 {
AzureIoTClient 51:269e65571b39 1277 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1278
AzureIoTClient 36:f78f9a56869e 1279 // Codes_SRS_DEVICE_09_077: [telemetry_messenger_unsubscribe_for_messages shall be invoked passing `instance->messenger_handle`]
AzureIoTClient 36:f78f9a56869e 1280 if (telemetry_messenger_unsubscribe_for_messages(instance->messenger_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1281 {
AzureIoTClient 36:f78f9a56869e 1282 // Codes_SRS_DEVICE_09_078: [If telemetry_messenger_unsubscribe_for_messages fails, device_unsubscribe_message shall return a non-zero result]
AzureIoTClient 36:f78f9a56869e 1283 LogError("Failed unsubscribing to C2D messages (telemetry_messenger_unsubscribe_for_messages failed)");
AzureIoTClient 34:51d158b409d2 1284 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1285 }
AzureIoTClient 34:51d158b409d2 1286 else
AzureIoTClient 34:51d158b409d2 1287 {
AzureIoTClient 34:51d158b409d2 1288 // Codes_SRS_DEVICE_09_079: [If no failures occur, device_unsubscribe_message shall return 0]
AzureIoTClient 34:51d158b409d2 1289 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1290 }
AzureIoTClient 34:51d158b409d2 1291 }
AzureIoTClient 34:51d158b409d2 1292 return result;
AzureIoTClient 30:20a85b733111 1293 }
AzureIoTClient 30:20a85b733111 1294
AzureIoTClient 51:269e65571b39 1295 int device_send_message_disposition(AMQP_DEVICE_HANDLE device_handle, DEVICE_MESSAGE_DISPOSITION_INFO* disposition_info, DEVICE_MESSAGE_DISPOSITION_RESULT disposition_result)
AzureIoTClient 30:20a85b733111 1296 {
AzureIoTClient 34:51d158b409d2 1297 int result;
AzureIoTClient 30:20a85b733111 1298
AzureIoTClient 34:51d158b409d2 1299 // Codes_SRS_DEVICE_09_111: [If `device_handle` or `disposition_info` are NULL, device_send_message_disposition() shall fail and return __FAILURE__]
AzureIoTClient 34:51d158b409d2 1300 if (device_handle == NULL || disposition_info == NULL)
AzureIoTClient 34:51d158b409d2 1301 {
AzureIoTClient 34:51d158b409d2 1302 LogError("Failed sending message disposition (either device_handle (%p) or disposition_info (%p) are NULL)", device_handle, disposition_info);
AzureIoTClient 34:51d158b409d2 1303 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1304 }
AzureIoTClient 56:8704100b3b54 1305 // Codes_SRS_DEVICE_09_112: [If `disposition_info->source` is NULL, device_send_message_disposition() shall fail and return __FAILURE__]
AzureIoTClient 34:51d158b409d2 1306 else if (disposition_info->source == NULL)
AzureIoTClient 34:51d158b409d2 1307 {
AzureIoTClient 34:51d158b409d2 1308 LogError("Failed sending message disposition (disposition_info->source is NULL)");
AzureIoTClient 34:51d158b409d2 1309 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1310 }
AzureIoTClient 34:51d158b409d2 1311 else
AzureIoTClient 34:51d158b409d2 1312 {
AzureIoTClient 51:269e65571b39 1313 AMQP_DEVICE_INSTANCE* device = (AMQP_DEVICE_INSTANCE*)device_handle;
AzureIoTClient 36:f78f9a56869e 1314 TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO* messenger_disposition_info;
AzureIoTClient 30:20a85b733111 1315
AzureIoTClient 56:8704100b3b54 1316 // Codes_SRS_DEVICE_09_113: [A TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO instance shall be created with a copy of the `source` and `message_id` contained in `disposition_info`]
AzureIoTClient 34:51d158b409d2 1317 if ((messenger_disposition_info = create_messenger_disposition_info(disposition_info)) == NULL)
AzureIoTClient 34:51d158b409d2 1318 {
AzureIoTClient 56:8704100b3b54 1319 // Codes_SRS_DEVICE_09_114: [If the TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO fails to be created, device_send_message_disposition() shall fail and return __FAILURE__]
AzureIoTClient 36:f78f9a56869e 1320 LogError("Failed sending message disposition (failed to create TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO)");
AzureIoTClient 34:51d158b409d2 1321 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1322 }
AzureIoTClient 34:51d158b409d2 1323 else
AzureIoTClient 34:51d158b409d2 1324 {
AzureIoTClient 36:f78f9a56869e 1325 TELEMETRY_MESSENGER_DISPOSITION_RESULT messenger_disposition_result = get_messenger_message_disposition_result_from(disposition_result);
AzureIoTClient 30:20a85b733111 1326
AzureIoTClient 56:8704100b3b54 1327 // Codes_SRS_DEVICE_09_115: [`telemetry_messenger_send_message_disposition()` shall be invoked passing the TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO instance and the corresponding TELEMETRY_MESSENGER_DISPOSITION_RESULT]
AzureIoTClient 36:f78f9a56869e 1328 if (telemetry_messenger_send_message_disposition(device->messenger_handle, messenger_disposition_info, messenger_disposition_result) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1329 {
AzureIoTClient 56:8704100b3b54 1330 // Codes_SRS_DEVICE_09_116: [If `telemetry_messenger_send_message_disposition()` fails, device_send_message_disposition() shall fail and return __FAILURE__]
AzureIoTClient 36:f78f9a56869e 1331 LogError("Failed sending message disposition (telemetry_messenger_send_message_disposition failed)");
AzureIoTClient 34:51d158b409d2 1332 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1333 }
AzureIoTClient 34:51d158b409d2 1334 else
AzureIoTClient 34:51d158b409d2 1335 {
AzureIoTClient 56:8704100b3b54 1336 // Codes_SRS_DEVICE_09_118: [If no failures occurr, device_send_message_disposition() shall return 0]
AzureIoTClient 34:51d158b409d2 1337 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1338 }
AzureIoTClient 30:20a85b733111 1339
AzureIoTClient 56:8704100b3b54 1340 // Codes_SRS_DEVICE_09_117: [device_send_message_disposition() shall destroy the TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO instance]
AzureIoTClient 34:51d158b409d2 1341 destroy_messenger_disposition_info(messenger_disposition_info);
AzureIoTClient 34:51d158b409d2 1342 }
AzureIoTClient 34:51d158b409d2 1343 }
AzureIoTClient 30:20a85b733111 1344
AzureIoTClient 34:51d158b409d2 1345 return result;
AzureIoTClient 30:20a85b733111 1346 }
AzureIoTClient 30:20a85b733111 1347
AzureIoTClient 51:269e65571b39 1348 int device_set_retry_policy(AMQP_DEVICE_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY policy, size_t retry_timeout_limit_in_seconds)
AzureIoTClient 30:20a85b733111 1349 {
AzureIoTClient 34:51d158b409d2 1350 (void)retry_timeout_limit_in_seconds;
AzureIoTClient 34:51d158b409d2 1351 (void)policy;
AzureIoTClient 34:51d158b409d2 1352 int result;
AzureIoTClient 30:20a85b733111 1353
AzureIoTClient 34:51d158b409d2 1354 // Codes_SRS_DEVICE_09_080: [If `handle` is NULL, device_set_retry_policy shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1355 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 1356 {
AzureIoTClient 34:51d158b409d2 1357 LogError("Failed setting retry policy (handle is NULL)");
AzureIoTClient 34:51d158b409d2 1358 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1359 }
AzureIoTClient 34:51d158b409d2 1360 else
AzureIoTClient 34:51d158b409d2 1361 {
AzureIoTClient 34:51d158b409d2 1362 // Codes_SRS_DEVICE_09_081: [device_set_retry_policy shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1363 LogError("Failed setting retry policy (functionality not supported)");
AzureIoTClient 34:51d158b409d2 1364 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1365 }
AzureIoTClient 30:20a85b733111 1366
AzureIoTClient 34:51d158b409d2 1367 return result;
AzureIoTClient 30:20a85b733111 1368 }
AzureIoTClient 30:20a85b733111 1369
AzureIoTClient 51:269e65571b39 1370 int device_set_option(AMQP_DEVICE_HANDLE handle, const char* name, void* value)
AzureIoTClient 30:20a85b733111 1371 {
AzureIoTClient 34:51d158b409d2 1372 int result;
AzureIoTClient 30:20a85b733111 1373
AzureIoTClient 34:51d158b409d2 1374 // Codes_SRS_DEVICE_09_082: [If `handle` or `name` or `value` are NULL, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1375 if (handle == NULL || name == NULL || value == NULL)
AzureIoTClient 34:51d158b409d2 1376 {
AzureIoTClient 34:51d158b409d2 1377 LogError("failed setting device option (one of the followin are NULL: _handle=%p, name=%p, value=%p)",
AzureIoTClient 34:51d158b409d2 1378 handle, name, value);
AzureIoTClient 34:51d158b409d2 1379 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1380 }
AzureIoTClient 34:51d158b409d2 1381 else
AzureIoTClient 34:51d158b409d2 1382 {
AzureIoTClient 51:269e65571b39 1383 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1384
AzureIoTClient 34:51d158b409d2 1385 if (strcmp(DEVICE_OPTION_CBS_REQUEST_TIMEOUT_SECS, name) == 0 ||
AzureIoTClient 34:51d158b409d2 1386 strcmp(DEVICE_OPTION_SAS_TOKEN_REFRESH_TIME_SECS, name) == 0 ||
AzureIoTClient 34:51d158b409d2 1387 strcmp(DEVICE_OPTION_SAS_TOKEN_LIFETIME_SECS, name) == 0)
AzureIoTClient 34:51d158b409d2 1388 {
AzureIoTClient 34:51d158b409d2 1389 // Codes_SRS_DEVICE_09_083: [If `name` refers to authentication but CBS authentication is not used, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1390 if (instance->authentication_handle == NULL)
AzureIoTClient 34:51d158b409d2 1391 {
AzureIoTClient 34:51d158b409d2 1392 LogError("failed setting option for device '%s' (cannot set authentication option '%s'; not using CBS authentication)", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1393 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1394 }
AzureIoTClient 34:51d158b409d2 1395 // Codes_SRS_DEVICE_09_084: [If `name` refers to authentication, it shall be passed along with `value` to authentication_set_option]
AzureIoTClient 34:51d158b409d2 1396 else if(authentication_set_option(instance->authentication_handle, name, value) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1397 {
AzureIoTClient 34:51d158b409d2 1398 // Codes_SRS_DEVICE_09_085: [If authentication_set_option fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1399 LogError("failed setting option for device '%s' (failed setting authentication option '%s')", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1400 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1401 }
AzureIoTClient 34:51d158b409d2 1402 else
AzureIoTClient 34:51d158b409d2 1403 {
AzureIoTClient 34:51d158b409d2 1404 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1405 }
AzureIoTClient 34:51d158b409d2 1406 }
AzureIoTClient 34:51d158b409d2 1407 else if (strcmp(DEVICE_OPTION_EVENT_SEND_TIMEOUT_SECS, name) == 0)
AzureIoTClient 34:51d158b409d2 1408 {
AzureIoTClient 36:f78f9a56869e 1409 // Codes_SRS_DEVICE_09_086: [If `name` refers to messenger module, it shall be passed along with `value` to telemetry_messenger_set_option]
AzureIoTClient 51:269e65571b39 1410 if (telemetry_messenger_set_option(instance->messenger_handle, TELEMETRY_MESSENGER_OPTION_EVENT_SEND_TIMEOUT_SECS, value) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1411 {
AzureIoTClient 36:f78f9a56869e 1412 // Codes_SRS_DEVICE_09_087: [If telemetry_messenger_set_option fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1413 LogError("failed setting option for device '%s' (failed setting messenger option '%s')", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1414 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1415 }
AzureIoTClient 34:51d158b409d2 1416 else
AzureIoTClient 34:51d158b409d2 1417 {
AzureIoTClient 34:51d158b409d2 1418 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1419 }
AzureIoTClient 34:51d158b409d2 1420 }
AzureIoTClient 34:51d158b409d2 1421 else if (strcmp(DEVICE_OPTION_SAVED_AUTH_OPTIONS, name) == 0)
AzureIoTClient 34:51d158b409d2 1422 {
AzureIoTClient 34:51d158b409d2 1423 // Codes_SRS_DEVICE_09_088: [If `name` is DEVICE_OPTION_SAVED_AUTH_OPTIONS but CBS authentication is not being used, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1424 if (instance->authentication_handle == NULL)
AzureIoTClient 34:51d158b409d2 1425 {
AzureIoTClient 34:51d158b409d2 1426 LogError("failed setting option for device '%s' (cannot set authentication option '%s'; not using CBS authentication)", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1427 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1428 }
AzureIoTClient 34:51d158b409d2 1429 else if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, instance->authentication_handle) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1430 {
AzureIoTClient 34:51d158b409d2 1431 // Codes_SRS_DEVICE_09_091: [If any call to OptionHandler_FeedOptions fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1432 LogError("failed setting option for device '%s' (OptionHandler_FeedOptions failed for authentication instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1433 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1434 }
AzureIoTClient 34:51d158b409d2 1435 else
AzureIoTClient 34:51d158b409d2 1436 {
AzureIoTClient 34:51d158b409d2 1437 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1438 }
AzureIoTClient 34:51d158b409d2 1439 }
AzureIoTClient 34:51d158b409d2 1440 else if (strcmp(DEVICE_OPTION_SAVED_MESSENGER_OPTIONS, name) == 0)
AzureIoTClient 34:51d158b409d2 1441 {
AzureIoTClient 34:51d158b409d2 1442 // Codes_SRS_DEVICE_09_089: [If `name` is DEVICE_OPTION_SAVED_MESSENGER_OPTIONS, `value` shall be fed to `instance->messenger_handle` using OptionHandler_FeedOptions]
AzureIoTClient 34:51d158b409d2 1443 if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, instance->messenger_handle) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1444 {
AzureIoTClient 34:51d158b409d2 1445 // Codes_SRS_DEVICE_09_091: [If any call to OptionHandler_FeedOptions fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1446 LogError("failed setting option for device '%s' (OptionHandler_FeedOptions failed for messenger instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1447 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1448 }
AzureIoTClient 34:51d158b409d2 1449 else
AzureIoTClient 34:51d158b409d2 1450 {
AzureIoTClient 34:51d158b409d2 1451 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1452 }
AzureIoTClient 34:51d158b409d2 1453 }
AzureIoTClient 34:51d158b409d2 1454 else if (strcmp(DEVICE_OPTION_SAVED_OPTIONS, name) == 0)
AzureIoTClient 34:51d158b409d2 1455 {
AzureIoTClient 34:51d158b409d2 1456 // Codes_SRS_DEVICE_09_090: [If `name` is DEVICE_OPTION_SAVED_OPTIONS, `value` shall be fed to `instance` using OptionHandler_FeedOptions]
AzureIoTClient 34:51d158b409d2 1457 if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, handle) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1458 {
AzureIoTClient 34:51d158b409d2 1459 // Codes_SRS_DEVICE_09_091: [If any call to OptionHandler_FeedOptions fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1460 LogError("failed setting option for device '%s' (OptionHandler_FeedOptions failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1461 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1462 }
AzureIoTClient 34:51d158b409d2 1463 else
AzureIoTClient 34:51d158b409d2 1464 {
AzureIoTClient 34:51d158b409d2 1465 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1466 }
AzureIoTClient 34:51d158b409d2 1467 }
AzureIoTClient 34:51d158b409d2 1468 else
AzureIoTClient 34:51d158b409d2 1469 {
AzureIoTClient 34:51d158b409d2 1470 // Codes_SRS_DEVICE_09_092: [If no failures occur, device_set_option shall return 0]
AzureIoTClient 34:51d158b409d2 1471 LogError("failed setting option for device '%s' (option with name '%s' is not suppported)", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1472 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1473 }
AzureIoTClient 34:51d158b409d2 1474 }
AzureIoTClient 30:20a85b733111 1475
AzureIoTClient 34:51d158b409d2 1476 return result;
AzureIoTClient 30:20a85b733111 1477 }
AzureIoTClient 30:20a85b733111 1478
AzureIoTClient 51:269e65571b39 1479 OPTIONHANDLER_HANDLE device_retrieve_options(AMQP_DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 1480 {
AzureIoTClient 34:51d158b409d2 1481 OPTIONHANDLER_HANDLE result;
AzureIoTClient 30:20a85b733111 1482
AzureIoTClient 34:51d158b409d2 1483 // Codes_SRS_DEVICE_09_093: [If `handle` is NULL, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1484 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 1485 {
AzureIoTClient 34:51d158b409d2 1486 LogError("Failed to retrieve options from device instance (handle is NULL)");
AzureIoTClient 34:51d158b409d2 1487 result = NULL;
AzureIoTClient 34:51d158b409d2 1488 }
AzureIoTClient 34:51d158b409d2 1489 else
AzureIoTClient 34:51d158b409d2 1490 {
AzureIoTClient 34:51d158b409d2 1491 // Codes_SRS_DEVICE_09_094: [A OPTIONHANDLER_HANDLE instance, aka `options` shall be created using OptionHandler_Create]
AzureIoTClient 34:51d158b409d2 1492 OPTIONHANDLER_HANDLE options = OptionHandler_Create(device_clone_option, device_destroy_option, (pfSetOption)device_set_option);
AzureIoTClient 30:20a85b733111 1493
AzureIoTClient 34:51d158b409d2 1494 if (options == NULL)
AzureIoTClient 34:51d158b409d2 1495 {
AzureIoTClient 34:51d158b409d2 1496 // Codes_SRS_DEVICE_09_095: [If OptionHandler_Create fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1497 LogError("Failed to retrieve options from device instance (OptionHandler_Create failed)");
AzureIoTClient 34:51d158b409d2 1498 result = NULL;
AzureIoTClient 34:51d158b409d2 1499 }
AzureIoTClient 34:51d158b409d2 1500 else
AzureIoTClient 34:51d158b409d2 1501 {
AzureIoTClient 51:269e65571b39 1502 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1503
AzureIoTClient 34:51d158b409d2 1504 OPTIONHANDLER_HANDLE dependency_options = NULL;
AzureIoTClient 30:20a85b733111 1505
AzureIoTClient 34:51d158b409d2 1506 // Codes_SRS_DEVICE_09_096: [If CBS authentication is used, `instance->authentication_handle` options shall be retrieved using authentication_retrieve_options]
AzureIoTClient 34:51d158b409d2 1507 if (instance->authentication_handle != NULL &&
AzureIoTClient 34:51d158b409d2 1508 (dependency_options = authentication_retrieve_options(instance->authentication_handle)) == NULL)
AzureIoTClient 34:51d158b409d2 1509 {
AzureIoTClient 34:51d158b409d2 1510 // Codes_SRS_DEVICE_09_097: [If authentication_retrieve_options fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1511 LogError("Failed to retrieve options from device '%s' (failed to retrieve options from authentication instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1512 result = NULL;
AzureIoTClient 34:51d158b409d2 1513 }
AzureIoTClient 34:51d158b409d2 1514 // Codes_SRS_DEVICE_09_098: [The authentication options shall be added to `options` using OptionHandler_AddOption as DEVICE_OPTION_SAVED_AUTH_OPTIONS]
AzureIoTClient 34:51d158b409d2 1515 else if (instance->authentication_handle != NULL &&
AzureIoTClient 34:51d158b409d2 1516 OptionHandler_AddOption(options, DEVICE_OPTION_SAVED_AUTH_OPTIONS, (const void*)dependency_options) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1517 {
AzureIoTClient 34:51d158b409d2 1518 // Codes_SRS_DEVICE_09_102: [If any call to OptionHandler_AddOption fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1519 LogError("Failed to retrieve options from device '%s' (OptionHandler_AddOption failed for option '%s')", instance->config->device_id, DEVICE_OPTION_SAVED_AUTH_OPTIONS);
AzureIoTClient 34:51d158b409d2 1520 result = NULL;
AzureIoTClient 34:51d158b409d2 1521 }
AzureIoTClient 36:f78f9a56869e 1522 // Codes_SRS_DEVICE_09_099: [`instance->messenger_handle` options shall be retrieved using telemetry_messenger_retrieve_options]
AzureIoTClient 36:f78f9a56869e 1523 else if ((dependency_options = telemetry_messenger_retrieve_options(instance->messenger_handle)) == NULL)
AzureIoTClient 34:51d158b409d2 1524 {
AzureIoTClient 36:f78f9a56869e 1525 // Codes_SRS_DEVICE_09_100: [If telemetry_messenger_retrieve_options fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1526 LogError("Failed to retrieve options from device '%s' (failed to retrieve options from messenger instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1527 result = NULL;
AzureIoTClient 34:51d158b409d2 1528 }
AzureIoTClient 34:51d158b409d2 1529 // Codes_SRS_DEVICE_09_101: [The messenger options shall be added to `options` using OptionHandler_AddOption as DEVICE_OPTION_SAVED_MESSENGER_OPTIONS]
AzureIoTClient 34:51d158b409d2 1530 else if (OptionHandler_AddOption(options, DEVICE_OPTION_SAVED_MESSENGER_OPTIONS, (const void*)dependency_options) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1531 {
AzureIoTClient 34:51d158b409d2 1532 // Codes_SRS_DEVICE_09_102: [If any call to OptionHandler_AddOption fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1533 LogError("Failed to retrieve options from device '%s' (OptionHandler_AddOption failed for option '%s')", instance->config->device_id, DEVICE_OPTION_SAVED_MESSENGER_OPTIONS);
AzureIoTClient 34:51d158b409d2 1534 result = NULL;
AzureIoTClient 34:51d158b409d2 1535 }
AzureIoTClient 34:51d158b409d2 1536 else
AzureIoTClient 34:51d158b409d2 1537 {
AzureIoTClient 34:51d158b409d2 1538 // Codes_SRS_DEVICE_09_104: [If no failures occur, a handle to `options` shall be return]
AzureIoTClient 34:51d158b409d2 1539 result = options;
AzureIoTClient 34:51d158b409d2 1540 }
AzureIoTClient 30:20a85b733111 1541
AzureIoTClient 34:51d158b409d2 1542 if (result == NULL)
AzureIoTClient 34:51d158b409d2 1543 {
AzureIoTClient 34:51d158b409d2 1544 // Codes_SRS_DEVICE_09_103: [If any failure occurs, any memory allocated by device_retrieve_options shall be destroyed]
AzureIoTClient 34:51d158b409d2 1545 OptionHandler_Destroy(options);
AzureIoTClient 34:51d158b409d2 1546 }
AzureIoTClient 34:51d158b409d2 1547 }
AzureIoTClient 34:51d158b409d2 1548 }
AzureIoTClient 30:20a85b733111 1549
AzureIoTClient 34:51d158b409d2 1550 return result;
AzureIoTClient 30:20a85b733111 1551 }
AzureIoTClient 39:e98d5df6dc74 1552
AzureIoTClient 51:269e65571b39 1553 int device_send_twin_update_async(AMQP_DEVICE_HANDLE handle, CONSTBUFFER_HANDLE data, DEVICE_SEND_TWIN_UPDATE_COMPLETE_CALLBACK on_send_twin_update_complete_callback, void* context)
AzureIoTClient 39:e98d5df6dc74 1554 {
AzureIoTClient 41:71c01aa3df1a 1555 int result;
AzureIoTClient 39:e98d5df6dc74 1556
AzureIoTClient 41:71c01aa3df1a 1557 // Codes_SRS_DEVICE_09_135: [If `handle` or `data` are NULL, device_send_twin_update_async shall return a non-zero result]
AzureIoTClient 41:71c01aa3df1a 1558 if (handle == NULL || data == NULL)
AzureIoTClient 41:71c01aa3df1a 1559 {
AzureIoTClient 41:71c01aa3df1a 1560 LogError("Invalid argument (handle=%p, data=%p)", handle, data);
AzureIoTClient 41:71c01aa3df1a 1561 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1562 }
AzureIoTClient 41:71c01aa3df1a 1563 else
AzureIoTClient 41:71c01aa3df1a 1564 {
AzureIoTClient 51:269e65571b39 1565 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 41:71c01aa3df1a 1566 DEVICE_SEND_TWIN_UPDATE_CONTEXT* twin_ctx;
AzureIoTClient 39:e98d5df6dc74 1567
AzureIoTClient 41:71c01aa3df1a 1568 // Codes_SRS_DEVICE_09_136: [A structure (`twin_ctx`) shall be created to track the send state of the twin report]
AzureIoTClient 41:71c01aa3df1a 1569 if ((twin_ctx = (DEVICE_SEND_TWIN_UPDATE_CONTEXT*)malloc(sizeof(DEVICE_SEND_TWIN_UPDATE_CONTEXT))) == NULL)
AzureIoTClient 41:71c01aa3df1a 1570 {
AzureIoTClient 41:71c01aa3df1a 1571 // Codes_SRS_DEVICE_09_137: [If `twin_ctx` fails to be created, device_send_twin_update_async shall return a non-zero value]
AzureIoTClient 41:71c01aa3df1a 1572 LogError("Cannot send twin update (failed creating TWIN context)");
AzureIoTClient 41:71c01aa3df1a 1573 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1574 }
AzureIoTClient 41:71c01aa3df1a 1575 else
AzureIoTClient 41:71c01aa3df1a 1576 {
AzureIoTClient 41:71c01aa3df1a 1577 twin_ctx->on_send_twin_update_complete_callback = on_send_twin_update_complete_callback;
AzureIoTClient 41:71c01aa3df1a 1578 twin_ctx->context = context;
AzureIoTClient 39:e98d5df6dc74 1579
AzureIoTClient 41:71c01aa3df1a 1580 // Codes_SRS_DEVICE_09_138: [The twin report shall be sent using twin_messenger_report_state_async, passing `on_report_state_complete_callback` and `twin_ctx`]
AzureIoTClient 41:71c01aa3df1a 1581 if (twin_messenger_report_state_async(instance->twin_messenger_handle, data, on_report_state_complete_callback, (const void*)twin_ctx) != 0)
AzureIoTClient 41:71c01aa3df1a 1582 {
AzureIoTClient 41:71c01aa3df1a 1583 // Codes_SRS_DEVICE_09_139: [If twin_messenger_report_state_async fails, device_send_twin_update_async shall return a non-zero value]
AzureIoTClient 41:71c01aa3df1a 1584 LogError("Cannot send twin update (failed creating TWIN messenger)");
AzureIoTClient 41:71c01aa3df1a 1585 free(twin_ctx);
AzureIoTClient 41:71c01aa3df1a 1586 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1587 }
AzureIoTClient 41:71c01aa3df1a 1588 else
AzureIoTClient 41:71c01aa3df1a 1589 {
AzureIoTClient 41:71c01aa3df1a 1590 // Codes_SRS_DEVICE_09_140: [If no failures occur, device_send_twin_update_async shall return 0]
AzureIoTClient 41:71c01aa3df1a 1591 result = RESULT_OK;
AzureIoTClient 41:71c01aa3df1a 1592 }
AzureIoTClient 41:71c01aa3df1a 1593 }
AzureIoTClient 41:71c01aa3df1a 1594 }
AzureIoTClient 39:e98d5df6dc74 1595
AzureIoTClient 41:71c01aa3df1a 1596 return result;
AzureIoTClient 39:e98d5df6dc74 1597 }
AzureIoTClient 39:e98d5df6dc74 1598
AzureIoTClient 51:269e65571b39 1599 int device_subscribe_for_twin_updates(AMQP_DEVICE_HANDLE handle, DEVICE_TWIN_UPDATE_RECEIVED_CALLBACK on_device_twin_update_received_callback, void* context)
AzureIoTClient 39:e98d5df6dc74 1600 {
AzureIoTClient 41:71c01aa3df1a 1601 int result;
AzureIoTClient 39:e98d5df6dc74 1602
AzureIoTClient 41:71c01aa3df1a 1603 // Codes_SRS_DEVICE_09_143: [If `handle` or `on_device_twin_update_received_callback` are NULL, device_subscribe_for_twin_updates shall return a non-zero result]
AzureIoTClient 41:71c01aa3df1a 1604 if (handle == NULL || on_device_twin_update_received_callback == NULL)
AzureIoTClient 41:71c01aa3df1a 1605 {
AzureIoTClient 41:71c01aa3df1a 1606 LogError("Invalid argument (handle=%p, on_device_twin_update_received_callback=%p)", handle, on_device_twin_update_received_callback);
AzureIoTClient 41:71c01aa3df1a 1607 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1608 }
AzureIoTClient 41:71c01aa3df1a 1609 else
AzureIoTClient 41:71c01aa3df1a 1610 {
AzureIoTClient 51:269e65571b39 1611 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 39:e98d5df6dc74 1612
AzureIoTClient 41:71c01aa3df1a 1613 DEVICE_TWIN_UPDATE_RECEIVED_CALLBACK previous_callback = instance->on_device_twin_update_received_callback;
AzureIoTClient 41:71c01aa3df1a 1614 void* previous_context = instance->on_device_twin_update_received_context;
AzureIoTClient 39:e98d5df6dc74 1615
AzureIoTClient 41:71c01aa3df1a 1616 instance->on_device_twin_update_received_callback = on_device_twin_update_received_callback;
AzureIoTClient 41:71c01aa3df1a 1617 instance->on_device_twin_update_received_context = context;
AzureIoTClient 39:e98d5df6dc74 1618
AzureIoTClient 41:71c01aa3df1a 1619 // Codes_SRS_DEVICE_09_144: [twin_messenger_subscribe shall be invoked passing `on_twin_state_update_callback`]
AzureIoTClient 41:71c01aa3df1a 1620 if (twin_messenger_subscribe(instance->twin_messenger_handle, on_twin_state_update_callback, (void*)instance) != 0)
AzureIoTClient 41:71c01aa3df1a 1621 {
AzureIoTClient 41:71c01aa3df1a 1622 // Codes_SRS_DEVICE_09_145: [If twin_messenger_subscribe fails, device_subscribe_for_twin_updates shall return a non-zero value]
AzureIoTClient 41:71c01aa3df1a 1623 LogError("Failed subscribing for device twin updates");
AzureIoTClient 41:71c01aa3df1a 1624 instance->on_device_twin_update_received_callback = previous_callback;
AzureIoTClient 41:71c01aa3df1a 1625 instance->on_device_twin_update_received_context = previous_context;
AzureIoTClient 41:71c01aa3df1a 1626 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1627 }
AzureIoTClient 41:71c01aa3df1a 1628 else
AzureIoTClient 41:71c01aa3df1a 1629 {
AzureIoTClient 41:71c01aa3df1a 1630 // Codes_SRS_DEVICE_09_146: [If no failures occur, device_subscribe_for_twin_updates shall return 0]
AzureIoTClient 41:71c01aa3df1a 1631 result = RESULT_OK;
AzureIoTClient 41:71c01aa3df1a 1632 }
AzureIoTClient 41:71c01aa3df1a 1633 }
AzureIoTClient 39:e98d5df6dc74 1634
AzureIoTClient 41:71c01aa3df1a 1635 return result;
AzureIoTClient 39:e98d5df6dc74 1636 }
AzureIoTClient 39:e98d5df6dc74 1637
AzureIoTClient 51:269e65571b39 1638 int device_unsubscribe_for_twin_updates(AMQP_DEVICE_HANDLE handle)
AzureIoTClient 39:e98d5df6dc74 1639 {
AzureIoTClient 41:71c01aa3df1a 1640 int result;
AzureIoTClient 39:e98d5df6dc74 1641
AzureIoTClient 39:e98d5df6dc74 1642
AzureIoTClient 41:71c01aa3df1a 1643 // Codes_SRS_DEVICE_09_147: [If `handle` is NULL, device_unsubscribe_for_twin_updates shall return a non-zero result]
AzureIoTClient 41:71c01aa3df1a 1644 if (handle == NULL)
AzureIoTClient 41:71c01aa3df1a 1645 {
AzureIoTClient 41:71c01aa3df1a 1646 LogError("Invalid argument (handle is NULL)");
AzureIoTClient 41:71c01aa3df1a 1647 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1648 }
AzureIoTClient 41:71c01aa3df1a 1649 else
AzureIoTClient 41:71c01aa3df1a 1650 {
AzureIoTClient 51:269e65571b39 1651 AMQP_DEVICE_INSTANCE* instance = (AMQP_DEVICE_INSTANCE*)handle;
AzureIoTClient 39:e98d5df6dc74 1652
AzureIoTClient 41:71c01aa3df1a 1653 // Codes_SRS_DEVICE_09_148: [twin_messenger_unsubscribe shall be invoked passing `on_twin_state_update_callback`]
AzureIoTClient 41:71c01aa3df1a 1654 if (twin_messenger_unsubscribe(instance->twin_messenger_handle) != 0)
AzureIoTClient 41:71c01aa3df1a 1655 {
AzureIoTClient 41:71c01aa3df1a 1656 // Codes_SRS_DEVICE_09_149: [If twin_messenger_unsubscribe fails, device_unsubscribe_for_twin_updates shall return a non-zero value]
AzureIoTClient 41:71c01aa3df1a 1657 LogError("Failed unsubscribing for device twin updates");
AzureIoTClient 41:71c01aa3df1a 1658 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1659 }
AzureIoTClient 41:71c01aa3df1a 1660 else
AzureIoTClient 41:71c01aa3df1a 1661 {
AzureIoTClient 41:71c01aa3df1a 1662 instance->on_device_twin_update_received_callback = NULL;
AzureIoTClient 41:71c01aa3df1a 1663 instance->on_device_twin_update_received_context = NULL;
AzureIoTClient 41:71c01aa3df1a 1664 // Codes_SRS_DEVICE_09_150: [If no failures occur, device_unsubscribe_for_twin_updates shall return 0]
AzureIoTClient 41:71c01aa3df1a 1665 result = RESULT_OK;
AzureIoTClient 41:71c01aa3df1a 1666 }
AzureIoTClient 41:71c01aa3df1a 1667 }
AzureIoTClient 39:e98d5df6dc74 1668
AzureIoTClient 41:71c01aa3df1a 1669 return result;
AzureIoTClient 56:8704100b3b54 1670 }