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:
Mon Sep 11 09:22:16 2017 -0700
Revision:
41:71c01aa3df1a
Parent:
39:e98d5df6dc74
Child:
48:06c522453dd6
1.1.23

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 30:20a85b733111 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 30:20a85b733111 10 #include "iothubtransport_amqp_cbs_auth.h"
AzureIoTClient 30:20a85b733111 11 #include "iothubtransport_amqp_device.h"
AzureIoTClient 39:e98d5df6dc74 12 #include "iothubtransport_amqp_telemetry_messenger.h"
AzureIoTClient 39:e98d5df6dc74 13 #include "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 30:20a85b733111 59 } 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 30:20a85b733111 74 static void update_state(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 34:51d158b409d2 192 {
AzureIoTClient 34:51d158b409d2 193 DEVICE_INSTANCE* instance = (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 34:51d158b409d2 206 DEVICE_INSTANCE* instance = (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 34:51d158b409d2 224 DEVICE_INSTANCE* instance = (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 41:71c01aa3df1a 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 41:71c01aa3df1a 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 41:71c01aa3df1a 288 DEVICE_INSTANCE* instance = (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 41:71c01aa3df1a 310 DEVICE_INSTANCE* instance = (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 34:51d158b409d2 367 messenger_disposition_info->message_id = 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 34:51d158b409d2 418 DEVICE_INSTANCE* device_instance = (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 34:51d158b409d2 499 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 500 }
AzureIoTClient 30:20a85b733111 501
AzureIoTClient 34:51d158b409d2 502 if (result != RESULT_OK)
AzureIoTClient 34:51d158b409d2 503 {
AzureIoTClient 34:51d158b409d2 504 destroy_device_config(new_config);
AzureIoTClient 34:51d158b409d2 505 new_config = NULL;
AzureIoTClient 34:51d158b409d2 506 }
AzureIoTClient 34:51d158b409d2 507 }
AzureIoTClient 30:20a85b733111 508
AzureIoTClient 34:51d158b409d2 509 return new_config;
AzureIoTClient 30:20a85b733111 510 }
AzureIoTClient 30:20a85b733111 511
AzureIoTClient 30:20a85b733111 512 static void set_authentication_config(DEVICE_INSTANCE* device_instance, AUTHENTICATION_CONFIG* auth_config)
AzureIoTClient 30:20a85b733111 513 {
AzureIoTClient 34:51d158b409d2 514 DEVICE_CONFIG *device_config = device_instance->config;
AzureIoTClient 30:20a85b733111 515
AzureIoTClient 34:51d158b409d2 516 auth_config->device_id = device_config->device_id;
AzureIoTClient 34:51d158b409d2 517 auth_config->iothub_host_fqdn = device_config->iothub_host_fqdn;
AzureIoTClient 34:51d158b409d2 518 auth_config->on_error_callback = on_authentication_error_callback;
AzureIoTClient 34:51d158b409d2 519 auth_config->on_error_callback_context = device_instance;
AzureIoTClient 34:51d158b409d2 520 auth_config->on_state_changed_callback = on_authentication_state_changed_callback;
AzureIoTClient 34:51d158b409d2 521 auth_config->on_state_changed_callback_context = device_instance;
AzureIoTClient 34:51d158b409d2 522 auth_config->authorization_module = device_config->authorization_module;
AzureIoTClient 30:20a85b733111 523 }
AzureIoTClient 30:20a85b733111 524
AzureIoTClient 30:20a85b733111 525 // Create and Destroy Helpers
AzureIoTClient 30:20a85b733111 526 static void internal_destroy_device(DEVICE_INSTANCE* instance)
AzureIoTClient 30:20a85b733111 527 {
AzureIoTClient 34:51d158b409d2 528 if (instance != NULL)
AzureIoTClient 34:51d158b409d2 529 {
AzureIoTClient 34:51d158b409d2 530 if (instance->messenger_handle != NULL)
AzureIoTClient 34:51d158b409d2 531 {
AzureIoTClient 36:f78f9a56869e 532 telemetry_messenger_destroy(instance->messenger_handle);
AzureIoTClient 34:51d158b409d2 533 }
AzureIoTClient 30:20a85b733111 534
AzureIoTClient 41:71c01aa3df1a 535 if (instance->twin_messenger_handle != NULL)
AzureIoTClient 41:71c01aa3df1a 536 {
AzureIoTClient 41:71c01aa3df1a 537 twin_messenger_destroy(instance->twin_messenger_handle);
AzureIoTClient 41:71c01aa3df1a 538 }
AzureIoTClient 39:e98d5df6dc74 539
AzureIoTClient 34:51d158b409d2 540 if (instance->authentication_handle != NULL)
AzureIoTClient 34:51d158b409d2 541 {
AzureIoTClient 34:51d158b409d2 542 authentication_destroy(instance->authentication_handle);
AzureIoTClient 34:51d158b409d2 543 }
AzureIoTClient 30:20a85b733111 544
AzureIoTClient 34:51d158b409d2 545 destroy_device_config(instance->config);
AzureIoTClient 34:51d158b409d2 546 free(instance);
AzureIoTClient 34:51d158b409d2 547 }
AzureIoTClient 30:20a85b733111 548 }
AzureIoTClient 30:20a85b733111 549
AzureIoTClient 30:20a85b733111 550 static int create_authentication_instance(DEVICE_INSTANCE *instance)
AzureIoTClient 30:20a85b733111 551 {
AzureIoTClient 34:51d158b409d2 552 int result;
AzureIoTClient 34:51d158b409d2 553 AUTHENTICATION_CONFIG auth_config;
AzureIoTClient 30:20a85b733111 554
AzureIoTClient 34:51d158b409d2 555 set_authentication_config(instance, &auth_config);
AzureIoTClient 30:20a85b733111 556
AzureIoTClient 34:51d158b409d2 557 if ((instance->authentication_handle = authentication_create(&auth_config)) == NULL)
AzureIoTClient 34:51d158b409d2 558 {
AzureIoTClient 34:51d158b409d2 559 LogError("Failed creating the AUTHENTICATION_HANDLE (authentication_create failed)");
AzureIoTClient 34:51d158b409d2 560 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 561 }
AzureIoTClient 34:51d158b409d2 562 else
AzureIoTClient 34:51d158b409d2 563 {
AzureIoTClient 34:51d158b409d2 564 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 565 }
AzureIoTClient 30:20a85b733111 566
AzureIoTClient 34:51d158b409d2 567 return result;
AzureIoTClient 30:20a85b733111 568 }
AzureIoTClient 30:20a85b733111 569
AzureIoTClient 39:e98d5df6dc74 570 static int create_telemetry_messenger_instance(DEVICE_INSTANCE* instance, const char* pi)
AzureIoTClient 30:20a85b733111 571 {
AzureIoTClient 34:51d158b409d2 572 int result;
AzureIoTClient 30:20a85b733111 573
AzureIoTClient 36:f78f9a56869e 574 TELEMETRY_MESSENGER_CONFIG messenger_config;
AzureIoTClient 34:51d158b409d2 575 messenger_config.device_id = instance->config->device_id;
AzureIoTClient 34:51d158b409d2 576 messenger_config.iothub_host_fqdn = instance->config->iothub_host_fqdn;
AzureIoTClient 34:51d158b409d2 577 messenger_config.on_state_changed_callback = on_messenger_state_changed_callback;
AzureIoTClient 34:51d158b409d2 578 messenger_config.on_state_changed_context = instance;
AzureIoTClient 30:20a85b733111 579
AzureIoTClient 36:f78f9a56869e 580 if ((instance->messenger_handle = telemetry_messenger_create(&messenger_config, pi)) == NULL)
AzureIoTClient 34:51d158b409d2 581 {
AzureIoTClient 36:f78f9a56869e 582 LogError("Failed creating the TELEMETRY_MESSENGER_HANDLE (messenger_create failed)");
AzureIoTClient 34:51d158b409d2 583 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 584 }
AzureIoTClient 34:51d158b409d2 585 else
AzureIoTClient 34:51d158b409d2 586 {
AzureIoTClient 34:51d158b409d2 587 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 588 }
AzureIoTClient 30:20a85b733111 589
AzureIoTClient 34:51d158b409d2 590 return result;
AzureIoTClient 30:20a85b733111 591 }
AzureIoTClient 30:20a85b733111 592
AzureIoTClient 39:e98d5df6dc74 593 static int create_twin_messenger(DEVICE_INSTANCE* instance)
AzureIoTClient 39:e98d5df6dc74 594 {
AzureIoTClient 41:71c01aa3df1a 595 int result;
AzureIoTClient 41:71c01aa3df1a 596 TWIN_MESSENGER_CONFIG twin_msgr_config;
AzureIoTClient 39:e98d5df6dc74 597
AzureIoTClient 41:71c01aa3df1a 598 twin_msgr_config.client_version = instance->config->product_info;
AzureIoTClient 41:71c01aa3df1a 599 twin_msgr_config.device_id = instance->config->device_id;
AzureIoTClient 41:71c01aa3df1a 600 twin_msgr_config.iothub_host_fqdn = instance->config->iothub_host_fqdn;
AzureIoTClient 41:71c01aa3df1a 601 twin_msgr_config.on_state_changed_callback = on_twin_messenger_state_changed_callback;
AzureIoTClient 41:71c01aa3df1a 602 twin_msgr_config.on_state_changed_context = (void*)instance;
AzureIoTClient 39:e98d5df6dc74 603
AzureIoTClient 41:71c01aa3df1a 604 if ((instance->twin_messenger_handle = twin_messenger_create(&twin_msgr_config)) == NULL)
AzureIoTClient 41:71c01aa3df1a 605 {
AzureIoTClient 41:71c01aa3df1a 606 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 607 }
AzureIoTClient 41:71c01aa3df1a 608 else
AzureIoTClient 41:71c01aa3df1a 609 {
AzureIoTClient 41:71c01aa3df1a 610 result = RESULT_OK;
AzureIoTClient 41:71c01aa3df1a 611 }
AzureIoTClient 39:e98d5df6dc74 612
AzureIoTClient 41:71c01aa3df1a 613 return result;
AzureIoTClient 39:e98d5df6dc74 614 }
AzureIoTClient 39:e98d5df6dc74 615
AzureIoTClient 39:e98d5df6dc74 616
AzureIoTClient 30:20a85b733111 617 // ---------- Set/Retrieve Options Helpers ----------//
AzureIoTClient 39:e98d5df6dc74 618
AzureIoTClient 30:20a85b733111 619 static void* device_clone_option(const char* name, const void* value)
AzureIoTClient 30:20a85b733111 620 {
AzureIoTClient 34:51d158b409d2 621 void* result;
AzureIoTClient 30:20a85b733111 622
AzureIoTClient 34:51d158b409d2 623 if (name == NULL || value == NULL)
AzureIoTClient 34:51d158b409d2 624 {
AzureIoTClient 34:51d158b409d2 625 LogError("Failed to clone device option (either name (%p) or value (%p) is NULL)", name, value);
AzureIoTClient 34:51d158b409d2 626 result = NULL;
AzureIoTClient 34:51d158b409d2 627 }
AzureIoTClient 34:51d158b409d2 628 else
AzureIoTClient 34:51d158b409d2 629 {
AzureIoTClient 34:51d158b409d2 630 if (strcmp(DEVICE_OPTION_SAVED_AUTH_OPTIONS, name) == 0 ||
AzureIoTClient 34:51d158b409d2 631 strcmp(DEVICE_OPTION_SAVED_MESSENGER_OPTIONS, name) == 0)
AzureIoTClient 34:51d158b409d2 632 {
AzureIoTClient 34:51d158b409d2 633 if ((result = (void*)OptionHandler_Clone((OPTIONHANDLER_HANDLE)value)) == NULL)
AzureIoTClient 34:51d158b409d2 634 {
AzureIoTClient 34:51d158b409d2 635 LogError("Failed to clone device option (OptionHandler_Clone failed for option %s)", name);
AzureIoTClient 34:51d158b409d2 636 }
AzureIoTClient 34:51d158b409d2 637 }
AzureIoTClient 34:51d158b409d2 638 else
AzureIoTClient 34:51d158b409d2 639 {
AzureIoTClient 34:51d158b409d2 640 LogError("Failed to clone device option (option with name '%s' is not suppported)", name);
AzureIoTClient 34:51d158b409d2 641 result = NULL;
AzureIoTClient 34:51d158b409d2 642 }
AzureIoTClient 34:51d158b409d2 643 }
AzureIoTClient 30:20a85b733111 644
AzureIoTClient 34:51d158b409d2 645 return result;
AzureIoTClient 30:20a85b733111 646 }
AzureIoTClient 30:20a85b733111 647
AzureIoTClient 30:20a85b733111 648 static void device_destroy_option(const char* name, const void* value)
AzureIoTClient 30:20a85b733111 649 {
AzureIoTClient 34:51d158b409d2 650 if (name == NULL || value == NULL)
AzureIoTClient 34:51d158b409d2 651 {
AzureIoTClient 34:51d158b409d2 652 LogError("Failed to destroy device option (either name (%p) or value (%p) is NULL)", name, value);
AzureIoTClient 34:51d158b409d2 653 }
AzureIoTClient 34:51d158b409d2 654 else
AzureIoTClient 34:51d158b409d2 655 {
AzureIoTClient 34:51d158b409d2 656 if (strcmp(name, DEVICE_OPTION_SAVED_AUTH_OPTIONS) == 0 ||
AzureIoTClient 34:51d158b409d2 657 strcmp(name, DEVICE_OPTION_SAVED_MESSENGER_OPTIONS) == 0)
AzureIoTClient 34:51d158b409d2 658 {
AzureIoTClient 34:51d158b409d2 659 OptionHandler_Destroy((OPTIONHANDLER_HANDLE)value);
AzureIoTClient 34:51d158b409d2 660 }
AzureIoTClient 34:51d158b409d2 661 else
AzureIoTClient 34:51d158b409d2 662 {
AzureIoTClient 34:51d158b409d2 663 LogError("Failed to clone device option (option with name '%s' is not suppported)", name);
AzureIoTClient 34:51d158b409d2 664 }
AzureIoTClient 34:51d158b409d2 665 }
AzureIoTClient 30:20a85b733111 666 }
AzureIoTClient 30:20a85b733111 667
AzureIoTClient 39:e98d5df6dc74 668
AzureIoTClient 39:e98d5df6dc74 669 //---------- Public APIs ----------//
AzureIoTClient 39:e98d5df6dc74 670
AzureIoTClient 30:20a85b733111 671 DEVICE_HANDLE device_create(DEVICE_CONFIG *config)
AzureIoTClient 30:20a85b733111 672 {
AzureIoTClient 34:51d158b409d2 673 DEVICE_INSTANCE *instance;
AzureIoTClient 30:20a85b733111 674
AzureIoTClient 34:51d158b409d2 675 // 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 676 if (config == NULL)
AzureIoTClient 34:51d158b409d2 677 {
AzureIoTClient 34:51d158b409d2 678 LogError("Failed creating the device instance (config is NULL)");
AzureIoTClient 34:51d158b409d2 679 instance = NULL;
AzureIoTClient 34:51d158b409d2 680 }
AzureIoTClient 34:51d158b409d2 681 else if (config->iothub_host_fqdn == NULL)
AzureIoTClient 34:51d158b409d2 682 {
AzureIoTClient 34:51d158b409d2 683 LogError("Failed creating the device instance (config->iothub_host_fqdn is NULL)");
AzureIoTClient 34:51d158b409d2 684 instance = NULL;
AzureIoTClient 34:51d158b409d2 685 }
AzureIoTClient 34:51d158b409d2 686 else if (config->on_state_changed_callback == NULL)
AzureIoTClient 34:51d158b409d2 687 {
AzureIoTClient 34:51d158b409d2 688 LogError("Failed creating the device instance (config->on_state_changed_callback is NULL)");
AzureIoTClient 34:51d158b409d2 689 instance = NULL;
AzureIoTClient 34:51d158b409d2 690 }
AzureIoTClient 34:51d158b409d2 691 else if (config->authorization_module == NULL)
AzureIoTClient 34:51d158b409d2 692 {
AzureIoTClient 34:51d158b409d2 693 LogError("Failed creating the device instance (config->authorization_module is NULL)");
AzureIoTClient 34:51d158b409d2 694 instance = NULL;
AzureIoTClient 34:51d158b409d2 695 }
AzureIoTClient 34:51d158b409d2 696 // Codes_SRS_DEVICE_09_002: [device_create shall allocate memory for the device instance structure]
AzureIoTClient 34:51d158b409d2 697 else if ((instance = (DEVICE_INSTANCE*)malloc(sizeof(DEVICE_INSTANCE))) == NULL)
AzureIoTClient 34:51d158b409d2 698 {
AzureIoTClient 34:51d158b409d2 699 // Codes_SRS_DEVICE_09_003: [If malloc fails, device_create shall fail and return NULL]
AzureIoTClient 34:51d158b409d2 700 LogError("Failed creating the device instance (malloc failed)");
AzureIoTClient 34:51d158b409d2 701 }
AzureIoTClient 34:51d158b409d2 702 else
AzureIoTClient 34:51d158b409d2 703 {
AzureIoTClient 34:51d158b409d2 704 int result;
AzureIoTClient 30:20a85b733111 705
AzureIoTClient 34:51d158b409d2 706 memset(instance, 0, sizeof(DEVICE_INSTANCE));
AzureIoTClient 30:20a85b733111 707
AzureIoTClient 34:51d158b409d2 708 // Codes_SRS_DEVICE_09_004: [All `config` parameters shall be saved into `instance`]
AzureIoTClient 34:51d158b409d2 709 if ((instance->config = clone_device_config(config)) == NULL)
AzureIoTClient 34:51d158b409d2 710 {
AzureIoTClient 34:51d158b409d2 711 // 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 712 LogError("Failed creating the device instance for device '%s' (failed copying the configuration)", config->device_id);
AzureIoTClient 34:51d158b409d2 713 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 714 }
AzureIoTClient 34:51d158b409d2 715 // 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 716 else if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS &&
AzureIoTClient 34:51d158b409d2 717 create_authentication_instance(instance) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 718 {
AzureIoTClient 34:51d158b409d2 719 // Codes_SRS_DEVICE_09_007: [If the AUTHENTICATION_HANDLE fails to be created, device_create shall fail and return NULL]
AzureIoTClient 34:51d158b409d2 720 LogError("Failed creating the device instance for device '%s' (failed creating the authentication instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 721 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 722 }
AzureIoTClient 36:f78f9a56869e 723 // Codes_SRS_DEVICE_09_008: [`instance->messenger_handle` shall be set using telemetry_messenger_create()]
AzureIoTClient 39:e98d5df6dc74 724 else if (create_telemetry_messenger_instance(instance, config->product_info) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 725 {
AzureIoTClient 36:f78f9a56869e 726 // Codes_SRS_DEVICE_09_009: [If the TELEMETRY_MESSENGER_HANDLE fails to be created, device_create shall fail and return NULL]
AzureIoTClient 34:51d158b409d2 727 LogError("Failed creating the device instance for device '%s' (failed creating the messenger instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 728 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 729 }
AzureIoTClient 41:71c01aa3df1a 730 // Codes_SRS_DEVICE_09_122: [`instance->twin_messenger_handle` shall be set using twin_messenger_create()]
AzureIoTClient 41:71c01aa3df1a 731 else if (create_twin_messenger(instance) != RESULT_OK)
AzureIoTClient 41:71c01aa3df1a 732 {
AzureIoTClient 41:71c01aa3df1a 733 // Codes_SRS_DEVICE_09_123: [If the TWIN_MESSENGER_HANDLE fails to be created, device_create shall fail and return NULL]
AzureIoTClient 41:71c01aa3df1a 734 LogError("Failed creating the twin messenger for device '%s'", instance->config->device_id);
AzureIoTClient 41:71c01aa3df1a 735 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 736 }
AzureIoTClient 34:51d158b409d2 737 else
AzureIoTClient 34:51d158b409d2 738 {
AzureIoTClient 34:51d158b409d2 739 instance->auth_state = AUTHENTICATION_STATE_STOPPED;
AzureIoTClient 41:71c01aa3df1a 740 instance->msgr_state = TELEMETRY_MESSENGER_STATE_STOPPED;
AzureIoTClient 41:71c01aa3df1a 741 instance->twin_msgr_state = TWIN_MESSENGER_STATE_STOPPED;
AzureIoTClient 34:51d158b409d2 742 instance->state = DEVICE_STATE_STOPPED;
AzureIoTClient 34:51d158b409d2 743 instance->auth_state_last_changed_time = INDEFINITE_TIME;
AzureIoTClient 34:51d158b409d2 744 instance->auth_state_change_timeout_secs = DEFAULT_AUTH_STATE_CHANGED_TIMEOUT_SECS;
AzureIoTClient 34:51d158b409d2 745 instance->msgr_state_last_changed_time = INDEFINITE_TIME;
AzureIoTClient 34:51d158b409d2 746 instance->msgr_state_change_timeout_secs = DEFAULT_MSGR_STATE_CHANGED_TIMEOUT_SECS;
AzureIoTClient 41:71c01aa3df1a 747 instance->twin_msgr_state_last_changed_time = INDEFINITE_TIME;
AzureIoTClient 41:71c01aa3df1a 748 instance->twin_msgr_state_change_timeout_secs = DEFAULT_MSGR_STATE_CHANGED_TIMEOUT_SECS;
AzureIoTClient 30:20a85b733111 749
AzureIoTClient 34:51d158b409d2 750 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 751 }
AzureIoTClient 30:20a85b733111 752
AzureIoTClient 34:51d158b409d2 753 if (result != RESULT_OK)
AzureIoTClient 34:51d158b409d2 754 {
AzureIoTClient 34:51d158b409d2 755 // Codes_SRS_DEVICE_09_010: [If device_create fails it shall release all memory it has allocated]
AzureIoTClient 34:51d158b409d2 756 internal_destroy_device(instance);
AzureIoTClient 34:51d158b409d2 757 instance = NULL;
AzureIoTClient 34:51d158b409d2 758 }
AzureIoTClient 34:51d158b409d2 759 }
AzureIoTClient 30:20a85b733111 760
AzureIoTClient 34:51d158b409d2 761 // Codes_SRS_DEVICE_09_011: [If device_create succeeds it shall return a handle to its `instance` structure]
AzureIoTClient 34:51d158b409d2 762 return (DEVICE_HANDLE)instance;
AzureIoTClient 30:20a85b733111 763 }
AzureIoTClient 30:20a85b733111 764
AzureIoTClient 30:20a85b733111 765 int device_start_async(DEVICE_HANDLE handle, SESSION_HANDLE session_handle, CBS_HANDLE cbs_handle)
AzureIoTClient 30:20a85b733111 766 {
AzureIoTClient 34:51d158b409d2 767 int result;
AzureIoTClient 30:20a85b733111 768
AzureIoTClient 34:51d158b409d2 769 // Codes_SRS_DEVICE_09_017: [If `handle` is NULL, device_start_async shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 770 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 771 {
AzureIoTClient 34:51d158b409d2 772 LogError("Failed starting device (handle is NULL)");
AzureIoTClient 34:51d158b409d2 773 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 774 }
AzureIoTClient 34:51d158b409d2 775 else
AzureIoTClient 34:51d158b409d2 776 {
AzureIoTClient 34:51d158b409d2 777 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 778
AzureIoTClient 34:51d158b409d2 779 // 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 780 if (instance->state != DEVICE_STATE_STOPPED)
AzureIoTClient 34:51d158b409d2 781 {
AzureIoTClient 34:51d158b409d2 782 LogError("Failed starting device (device is not stopped)");
AzureIoTClient 34:51d158b409d2 783 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 784 }
AzureIoTClient 34:51d158b409d2 785 // Codes_SRS_DEVICE_09_019: [If `session_handle` is NULL, device_start_async shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 786 else if (session_handle == NULL)
AzureIoTClient 34:51d158b409d2 787 {
AzureIoTClient 34:51d158b409d2 788 LogError("Failed starting device (session_handle is NULL)");
AzureIoTClient 34:51d158b409d2 789 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 790 }
AzureIoTClient 34:51d158b409d2 791 // 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 792 else if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS && cbs_handle == NULL)
AzureIoTClient 34:51d158b409d2 793 {
AzureIoTClient 34:51d158b409d2 794 LogError("Failed starting device (device using CBS authentication, but cbs_handle is NULL)");
AzureIoTClient 34:51d158b409d2 795 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 796 }
AzureIoTClient 34:51d158b409d2 797 else
AzureIoTClient 34:51d158b409d2 798 {
AzureIoTClient 34:51d158b409d2 799 // Codes_SRS_DEVICE_09_021: [`session_handle` and `cbs_handle` shall be saved into the `instance`]
AzureIoTClient 34:51d158b409d2 800 instance->session_handle = session_handle;
AzureIoTClient 34:51d158b409d2 801 instance->cbs_handle = cbs_handle;
AzureIoTClient 30:20a85b733111 802
AzureIoTClient 34:51d158b409d2 803 // Codes_SRS_DEVICE_09_022: [The device state shall be updated to DEVICE_STATE_STARTING, and state changed callback invoked]
AzureIoTClient 34:51d158b409d2 804 update_state(instance, DEVICE_STATE_STARTING);
AzureIoTClient 30:20a85b733111 805
AzureIoTClient 34:51d158b409d2 806 // Codes_SRS_DEVICE_09_023: [If no failures occur, device_start_async shall return 0]
AzureIoTClient 34:51d158b409d2 807 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 808 }
AzureIoTClient 34:51d158b409d2 809 }
AzureIoTClient 30:20a85b733111 810
AzureIoTClient 34:51d158b409d2 811 return result;
AzureIoTClient 30:20a85b733111 812 }
AzureIoTClient 30:20a85b733111 813
AzureIoTClient 30:20a85b733111 814 // @brief
AzureIoTClient 30:20a85b733111 815 // stops a device instance (stops messenger and authentication) synchronously.
AzureIoTClient 30:20a85b733111 816 // @returns
AzureIoTClient 30:20a85b733111 817 // 0 if the function succeeds, non-zero otherwise.
AzureIoTClient 30:20a85b733111 818 int device_stop(DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 819 {
AzureIoTClient 34:51d158b409d2 820 int result;
AzureIoTClient 30:20a85b733111 821
AzureIoTClient 34:51d158b409d2 822 // Codes_SRS_DEVICE_09_024: [If `handle` is NULL, device_stop shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 823 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 824 {
AzureIoTClient 34:51d158b409d2 825 LogError("Failed stopping device (handle is NULL)");
AzureIoTClient 34:51d158b409d2 826 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 827 }
AzureIoTClient 34:51d158b409d2 828 else
AzureIoTClient 34:51d158b409d2 829 {
AzureIoTClient 34:51d158b409d2 830 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 831
AzureIoTClient 34:51d158b409d2 832 // 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 833 if (instance->state == DEVICE_STATE_STOPPED || instance->state == DEVICE_STATE_STOPPING)
AzureIoTClient 34:51d158b409d2 834 {
AzureIoTClient 34:51d158b409d2 835 LogError("Failed stopping device '%s' (device is already stopped or stopping)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 836 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 837 }
AzureIoTClient 34:51d158b409d2 838 else
AzureIoTClient 34:51d158b409d2 839 {
AzureIoTClient 34:51d158b409d2 840 // Codes_SRS_DEVICE_09_026: [The device state shall be updated to DEVICE_STATE_STOPPING, and state changed callback invoked]
AzureIoTClient 34:51d158b409d2 841 update_state(instance, DEVICE_STATE_STOPPING);
AzureIoTClient 30:20a85b733111 842
AzureIoTClient 36:f78f9a56869e 843 // Codes_SRS_DEVICE_09_027: [If `instance->messenger_handle` state is not TELEMETRY_MESSENGER_STATE_STOPPED, messenger_stop shall be invoked]
AzureIoTClient 36:f78f9a56869e 844 if (instance->msgr_state != TELEMETRY_MESSENGER_STATE_STOPPED &&
AzureIoTClient 36:f78f9a56869e 845 instance->msgr_state != TELEMETRY_MESSENGER_STATE_STOPPING &&
AzureIoTClient 36:f78f9a56869e 846 telemetry_messenger_stop(instance->messenger_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 847 {
AzureIoTClient 34:51d158b409d2 848 // 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 849 LogError("Failed stopping device '%s' (telemetry_messenger_stop failed)", instance->config->device_id);
AzureIoTClient 39:e98d5df6dc74 850 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 851 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 39:e98d5df6dc74 852 }
AzureIoTClient 41:71c01aa3df1a 853 // 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 854 else if (instance->twin_msgr_state != TWIN_MESSENGER_STATE_STOPPED &&
AzureIoTClient 39:e98d5df6dc74 855 instance->twin_msgr_state != TWIN_MESSENGER_STATE_STOPPING &&
AzureIoTClient 39:e98d5df6dc74 856 twin_messenger_stop(instance->twin_messenger_handle) != RESULT_OK)
AzureIoTClient 39:e98d5df6dc74 857 {
AzureIoTClient 41:71c01aa3df1a 858 // 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 859 LogError("Failed stopping device '%s' (twin_messenger_stop failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 860 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 861 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 862 }
AzureIoTClient 34:51d158b409d2 863 // 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 864 else if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS &&
AzureIoTClient 34:51d158b409d2 865 instance->auth_state != AUTHENTICATION_STATE_STOPPED &&
AzureIoTClient 34:51d158b409d2 866 authentication_stop(instance->authentication_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 867 {
AzureIoTClient 34:51d158b409d2 868 // 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 869 LogError("Failed stopping device '%s' (authentication_stop failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 870 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 871 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 872 }
AzureIoTClient 34:51d158b409d2 873 else
AzureIoTClient 34:51d158b409d2 874 {
AzureIoTClient 34:51d158b409d2 875 // Codes_SRS_DEVICE_09_031: [The device state shall be updated to DEVICE_STATE_STOPPED, and state changed callback invoked]
AzureIoTClient 34:51d158b409d2 876 update_state(instance, DEVICE_STATE_STOPPED);
AzureIoTClient 30:20a85b733111 877
AzureIoTClient 34:51d158b409d2 878 // Codes_SRS_DEVICE_09_032: [If no failures occur, device_stop shall return 0]
AzureIoTClient 34:51d158b409d2 879 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 880 }
AzureIoTClient 34:51d158b409d2 881 }
AzureIoTClient 34:51d158b409d2 882 }
AzureIoTClient 30:20a85b733111 883
AzureIoTClient 34:51d158b409d2 884 return result;
AzureIoTClient 30:20a85b733111 885 }
AzureIoTClient 30:20a85b733111 886
AzureIoTClient 30:20a85b733111 887 void device_do_work(DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 888 {
AzureIoTClient 34:51d158b409d2 889 // Codes_SRS_DEVICE_09_033: [If `handle` is NULL, device_do_work shall return]
AzureIoTClient 34:51d158b409d2 890 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 891 {
AzureIoTClient 34:51d158b409d2 892 LogError("Failed to perform device_do_work (handle is NULL)");
AzureIoTClient 34:51d158b409d2 893 }
AzureIoTClient 34:51d158b409d2 894 else
AzureIoTClient 34:51d158b409d2 895 {
AzureIoTClient 34:51d158b409d2 896 // Cranking the state monster:
AzureIoTClient 34:51d158b409d2 897 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 898
AzureIoTClient 34:51d158b409d2 899 if (instance->state == DEVICE_STATE_STARTING)
AzureIoTClient 34:51d158b409d2 900 {
AzureIoTClient 34:51d158b409d2 901 // 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 902 if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS)
AzureIoTClient 34:51d158b409d2 903 {
AzureIoTClient 34:51d158b409d2 904 if (instance->auth_state == AUTHENTICATION_STATE_STOPPED)
AzureIoTClient 34:51d158b409d2 905 {
AzureIoTClient 34:51d158b409d2 906 if (authentication_start(instance->authentication_handle, instance->cbs_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 907 {
AzureIoTClient 34:51d158b409d2 908 // Codes_SRS_DEVICE_09_035: [If authentication_start fails, the device state shall be updated to DEVICE_STATE_ERROR_AUTH]
AzureIoTClient 34:51d158b409d2 909 LogError("Device '%s' failed to be authenticated (authentication_start failed)", instance->config->device_id);
AzureIoTClient 30:20a85b733111 910
AzureIoTClient 34:51d158b409d2 911 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 912 }
AzureIoTClient 34:51d158b409d2 913 }
AzureIoTClient 34:51d158b409d2 914 // 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 915 else if (instance->auth_state == AUTHENTICATION_STATE_STARTING)
AzureIoTClient 34:51d158b409d2 916 {
AzureIoTClient 34:51d158b409d2 917 int is_timed_out;
AzureIoTClient 34:51d158b409d2 918 if (is_timeout_reached(instance->auth_state_last_changed_time, instance->auth_state_change_timeout_secs, &is_timed_out) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 919 {
AzureIoTClient 34:51d158b409d2 920 LogError("Device '%s' failed verifying the timeout for authentication start (is_timeout_reached failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 921 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 922 }
AzureIoTClient 34:51d158b409d2 923 // 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 924 else if (is_timed_out == 1)
AzureIoTClient 34:51d158b409d2 925 {
AzureIoTClient 34:51d158b409d2 926 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 927
AzureIoTClient 34:51d158b409d2 928 update_state(instance, DEVICE_STATE_ERROR_AUTH_TIMEOUT);
AzureIoTClient 34:51d158b409d2 929 }
AzureIoTClient 34:51d158b409d2 930 }
AzureIoTClient 34:51d158b409d2 931 else if (instance->auth_state == AUTHENTICATION_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 932 {
AzureIoTClient 34:51d158b409d2 933 // 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 934 if (instance->auth_error_code == AUTHENTICATION_ERROR_AUTH_FAILED)
AzureIoTClient 34:51d158b409d2 935 {
AzureIoTClient 34:51d158b409d2 936 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 937 }
AzureIoTClient 34:51d158b409d2 938 // 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 939 else // DEVICE_STATE_ERROR_TIMEOUT
AzureIoTClient 34:51d158b409d2 940 {
AzureIoTClient 34:51d158b409d2 941 update_state(instance, DEVICE_STATE_ERROR_AUTH_TIMEOUT);
AzureIoTClient 34:51d158b409d2 942 }
AzureIoTClient 34:51d158b409d2 943 }
AzureIoTClient 34:51d158b409d2 944 // There is no AUTHENTICATION_STATE_STOPPING
AzureIoTClient 34:51d158b409d2 945 }
AzureIoTClient 30:20a85b733111 946
AzureIoTClient 34:51d158b409d2 947 // Codes_SRS_DEVICE_09_040: [Messenger shall not be started if using CBS authentication and authentication start has not completed yet]
AzureIoTClient 41:71c01aa3df1a 948 // 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 949 if (instance->config->authentication_mode == DEVICE_AUTH_MODE_X509 || instance->auth_state == AUTHENTICATION_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 950 {
AzureIoTClient 41:71c01aa3df1a 951 size_t number_of_messengers_started = 0;
AzureIoTClient 39:e98d5df6dc74 952
AzureIoTClient 36:f78f9a56869e 953 // Codes_SRS_DEVICE_09_041: [If messenger state is TELEMETRY_MESSENGER_STATE_STOPPED, messenger_start shall be invoked]
AzureIoTClient 36:f78f9a56869e 954 if (instance->msgr_state == TELEMETRY_MESSENGER_STATE_STOPPED)
AzureIoTClient 34:51d158b409d2 955 {
AzureIoTClient 34:51d158b409d2 956 // Codes_SRS_DEVICE_09_042: [If messenger_start fails, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 36:f78f9a56869e 957 if (telemetry_messenger_start(instance->messenger_handle, instance->session_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 958 {
AzureIoTClient 34:51d158b409d2 959 LogError("Device '%s' messenger failed to be started (messenger_start failed)", instance->config->device_id);
AzureIoTClient 30:20a85b733111 960
AzureIoTClient 34:51d158b409d2 961 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 962 }
AzureIoTClient 34:51d158b409d2 963 }
AzureIoTClient 36:f78f9a56869e 964 // 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 965 else if (instance->msgr_state == TELEMETRY_MESSENGER_STATE_STARTING)
AzureIoTClient 34:51d158b409d2 966 {
AzureIoTClient 34:51d158b409d2 967 int is_timed_out;
AzureIoTClient 34:51d158b409d2 968 if (is_timeout_reached(instance->msgr_state_last_changed_time, instance->msgr_state_change_timeout_secs, &is_timed_out) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 969 {
AzureIoTClient 34:51d158b409d2 970 LogError("Device '%s' failed verifying the timeout for messenger start (is_timeout_reached failed)", instance->config->device_id);
AzureIoTClient 30:20a85b733111 971
AzureIoTClient 34:51d158b409d2 972 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 973 }
AzureIoTClient 34:51d158b409d2 974 // Codes_SRS_DEVICE_09_044: [If messenger_start times out, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 34:51d158b409d2 975 else if (is_timed_out == 1)
AzureIoTClient 34:51d158b409d2 976 {
AzureIoTClient 34:51d158b409d2 977 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 978
AzureIoTClient 34:51d158b409d2 979 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 980 }
AzureIoTClient 34:51d158b409d2 981 }
AzureIoTClient 36:f78f9a56869e 982 // 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 983 else if (instance->msgr_state == TELEMETRY_MESSENGER_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 984 {
AzureIoTClient 34:51d158b409d2 985 LogError("Device '%s' messenger failed to be started (messenger got into error state)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 986
AzureIoTClient 34:51d158b409d2 987 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 988 }
AzureIoTClient 36:f78f9a56869e 989 // 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 990 else if (instance->msgr_state == TELEMETRY_MESSENGER_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 991 {
AzureIoTClient 41:71c01aa3df1a 992 number_of_messengers_started++;
AzureIoTClient 34:51d158b409d2 993 }
AzureIoTClient 39:e98d5df6dc74 994
AzureIoTClient 41:71c01aa3df1a 995 // Codes_SRS_DEVICE_09_125: [If TWIN messenger state is TWIN_MESSENGER_STATE_STOPPED, twin_messenger_start shall be invoked]
AzureIoTClient 41:71c01aa3df1a 996 if (instance->twin_msgr_state == TWIN_MESSENGER_STATE_STOPPED)
AzureIoTClient 41:71c01aa3df1a 997 {
AzureIoTClient 41:71c01aa3df1a 998 if (twin_messenger_start(instance->twin_messenger_handle, instance->session_handle) != RESULT_OK)
AzureIoTClient 41:71c01aa3df1a 999 {
AzureIoTClient 41:71c01aa3df1a 1000 // Codes_SRS_DEVICE_09_126: [If twin_messenger_start fails, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 41:71c01aa3df1a 1001 LogError("Device '%s' twin messenger failed to be started (messenger_start failed)", instance->config->device_id);
AzureIoTClient 39:e98d5df6dc74 1002
AzureIoTClient 41:71c01aa3df1a 1003 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 41:71c01aa3df1a 1004 }
AzureIoTClient 41:71c01aa3df1a 1005 }
AzureIoTClient 41:71c01aa3df1a 1006 else if (instance->twin_msgr_state == TWIN_MESSENGER_STATE_STARTING)
AzureIoTClient 41:71c01aa3df1a 1007 {
AzureIoTClient 41:71c01aa3df1a 1008 int is_timed_out;
AzureIoTClient 41:71c01aa3df1a 1009 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 1010 {
AzureIoTClient 41:71c01aa3df1a 1011 LogError("Device '%s' failed verifying the timeout for twin messenger start (is_timeout_reached failed)", instance->config->device_id);
AzureIoTClient 39:e98d5df6dc74 1012
AzureIoTClient 41:71c01aa3df1a 1013 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 41:71c01aa3df1a 1014 }
AzureIoTClient 41:71c01aa3df1a 1015 // 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 1016 else if (is_timed_out == 1)
AzureIoTClient 41:71c01aa3df1a 1017 {
AzureIoTClient 41:71c01aa3df1a 1018 // 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 1019 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 1020
AzureIoTClient 41:71c01aa3df1a 1021 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 41:71c01aa3df1a 1022 }
AzureIoTClient 41:71c01aa3df1a 1023 }
AzureIoTClient 41:71c01aa3df1a 1024 // 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 1025 else if (instance->twin_msgr_state == TWIN_MESSENGER_STATE_ERROR)
AzureIoTClient 41:71c01aa3df1a 1026 {
AzureIoTClient 41:71c01aa3df1a 1027 LogError("Device '%s' twin messenger failed to be started (messenger got into error state)", instance->config->device_id);
AzureIoTClient 39:e98d5df6dc74 1028
AzureIoTClient 41:71c01aa3df1a 1029 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 41:71c01aa3df1a 1030 }
AzureIoTClient 41:71c01aa3df1a 1031 // 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 1032 else if (instance->twin_msgr_state == TWIN_MESSENGER_STATE_STARTED)
AzureIoTClient 41:71c01aa3df1a 1033 {
AzureIoTClient 41:71c01aa3df1a 1034 number_of_messengers_started++;
AzureIoTClient 41:71c01aa3df1a 1035 }
AzureIoTClient 39:e98d5df6dc74 1036
AzureIoTClient 41:71c01aa3df1a 1037 if (number_of_messengers_started == 2)
AzureIoTClient 41:71c01aa3df1a 1038 {
AzureIoTClient 41:71c01aa3df1a 1039 update_state(instance, DEVICE_STATE_STARTED);
AzureIoTClient 41:71c01aa3df1a 1040 }
AzureIoTClient 34:51d158b409d2 1041 }
AzureIoTClient 34:51d158b409d2 1042 }
AzureIoTClient 34:51d158b409d2 1043 else if (instance->state == DEVICE_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 1044 {
AzureIoTClient 34:51d158b409d2 1045 // 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 1046 if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS &&
AzureIoTClient 34:51d158b409d2 1047 instance->auth_state != AUTHENTICATION_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 1048 {
AzureIoTClient 34:51d158b409d2 1049 LogError("Device '%s' is started but authentication reported unexpected state %d", instance->config->device_id, instance->auth_state);
AzureIoTClient 30:20a85b733111 1050
AzureIoTClient 34:51d158b409d2 1051 if (instance->auth_state != AUTHENTICATION_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 1052 {
AzureIoTClient 34:51d158b409d2 1053 if (instance->auth_error_code == AUTHENTICATION_ERROR_AUTH_FAILED)
AzureIoTClient 34:51d158b409d2 1054 {
AzureIoTClient 34:51d158b409d2 1055 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 1056 }
AzureIoTClient 34:51d158b409d2 1057 else // AUTHENTICATION_ERROR_AUTH_TIMEOUT
AzureIoTClient 34:51d158b409d2 1058 {
AzureIoTClient 34:51d158b409d2 1059 update_state(instance, DEVICE_STATE_ERROR_AUTH_TIMEOUT);
AzureIoTClient 34:51d158b409d2 1060 }
AzureIoTClient 34:51d158b409d2 1061 }
AzureIoTClient 34:51d158b409d2 1062 else
AzureIoTClient 34:51d158b409d2 1063 {
AzureIoTClient 34:51d158b409d2 1064 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 1065 }
AzureIoTClient 34:51d158b409d2 1066 }
AzureIoTClient 34:51d158b409d2 1067 else
AzureIoTClient 34:51d158b409d2 1068 {
AzureIoTClient 36:f78f9a56869e 1069 // 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 1070 if (instance->msgr_state != TELEMETRY_MESSENGER_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 1071 {
AzureIoTClient 34:51d158b409d2 1072 LogError("Device '%s' is started but messenger reported unexpected state %d", instance->config->device_id, instance->msgr_state);
AzureIoTClient 34:51d158b409d2 1073 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 1074 }
AzureIoTClient 39:e98d5df6dc74 1075
AzureIoTClient 41:71c01aa3df1a 1076 // 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 1077 if (instance->twin_msgr_state != TWIN_MESSENGER_STATE_STARTED)
AzureIoTClient 41:71c01aa3df1a 1078 {
AzureIoTClient 41:71c01aa3df1a 1079 LogError("Device '%s' is started but TWIN messenger reported unexpected state %d", instance->config->device_id, instance->msgr_state);
AzureIoTClient 41:71c01aa3df1a 1080 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 41:71c01aa3df1a 1081 }
AzureIoTClient 34:51d158b409d2 1082 }
AzureIoTClient 34:51d158b409d2 1083 }
AzureIoTClient 30:20a85b733111 1084
AzureIoTClient 34:51d158b409d2 1085 // Invoking the do_works():
AzureIoTClient 34:51d158b409d2 1086 if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS)
AzureIoTClient 34:51d158b409d2 1087 {
AzureIoTClient 34:51d158b409d2 1088 if (instance->auth_state != AUTHENTICATION_STATE_STOPPED && instance->auth_state != AUTHENTICATION_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 1089 {
AzureIoTClient 34:51d158b409d2 1090 // 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 1091 authentication_do_work(instance->authentication_handle);
AzureIoTClient 34:51d158b409d2 1092 }
AzureIoTClient 34:51d158b409d2 1093 }
AzureIoTClient 30:20a85b733111 1094
AzureIoTClient 36:f78f9a56869e 1095 if (instance->msgr_state != TELEMETRY_MESSENGER_STATE_STOPPED && instance->msgr_state != TELEMETRY_MESSENGER_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 1096 {
AzureIoTClient 39:e98d5df6dc74 1097 // 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 1098 telemetry_messenger_do_work(instance->messenger_handle);
AzureIoTClient 34:51d158b409d2 1099 }
AzureIoTClient 39:e98d5df6dc74 1100
AzureIoTClient 41:71c01aa3df1a 1101 if (instance->twin_msgr_state != TWIN_MESSENGER_STATE_STOPPED && instance->twin_msgr_state != TWIN_MESSENGER_STATE_ERROR)
AzureIoTClient 41:71c01aa3df1a 1102 {
AzureIoTClient 41:71c01aa3df1a 1103 // 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 1104 twin_messenger_do_work(instance->twin_messenger_handle);
AzureIoTClient 41:71c01aa3df1a 1105 }
AzureIoTClient 34:51d158b409d2 1106 }
AzureIoTClient 30:20a85b733111 1107 }
AzureIoTClient 30:20a85b733111 1108
AzureIoTClient 30:20a85b733111 1109 void device_destroy(DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 1110 {
AzureIoTClient 34:51d158b409d2 1111 // Codes_SRS_DEVICE_09_012: [If `handle` is NULL, device_destroy shall return]
AzureIoTClient 34:51d158b409d2 1112 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 1113 {
AzureIoTClient 34:51d158b409d2 1114 LogError("Failed destroying device handle (handle is NULL)");
AzureIoTClient 34:51d158b409d2 1115 }
AzureIoTClient 34:51d158b409d2 1116 else
AzureIoTClient 34:51d158b409d2 1117 {
AzureIoTClient 34:51d158b409d2 1118 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 34:51d158b409d2 1119 // 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 1120 if (instance->state == DEVICE_STATE_STARTED || instance->state == DEVICE_STATE_STARTING)
AzureIoTClient 34:51d158b409d2 1121 {
AzureIoTClient 34:51d158b409d2 1122 (void)device_stop((DEVICE_HANDLE)instance);
AzureIoTClient 34:51d158b409d2 1123 }
AzureIoTClient 30:20a85b733111 1124
AzureIoTClient 36:f78f9a56869e 1125 // Codes_SRS_DEVICE_09_014: [`instance->messenger_handle shall be destroyed using telemetry_messenger_destroy()`]
AzureIoTClient 34:51d158b409d2 1126 // Codes_SRS_DEVICE_09_015: [If created, `instance->authentication_handle` shall be destroyed using authentication_destroy()`]
AzureIoTClient 34:51d158b409d2 1127 // Codes_SRS_DEVICE_09_016: [The contents of `instance->config` shall be detroyed and then it shall be freed]
AzureIoTClient 34:51d158b409d2 1128 internal_destroy_device((DEVICE_INSTANCE*)handle);
AzureIoTClient 34:51d158b409d2 1129 }
AzureIoTClient 30:20a85b733111 1130 }
AzureIoTClient 30:20a85b733111 1131
AzureIoTClient 30:20a85b733111 1132 int device_send_event_async(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 1133 {
AzureIoTClient 34:51d158b409d2 1134 int result;
AzureIoTClient 30:20a85b733111 1135
AzureIoTClient 34:51d158b409d2 1136 // Codes_SRS_DEVICE_09_051: [If `handle` are `message` are NULL, device_send_event_async shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1137 if (handle == NULL || message == NULL)
AzureIoTClient 34:51d158b409d2 1138 {
AzureIoTClient 34:51d158b409d2 1139 LogError("Failed sending event (either handle (%p) or message (%p) are NULL)", handle, message);
AzureIoTClient 34:51d158b409d2 1140 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1141 }
AzureIoTClient 34:51d158b409d2 1142 else
AzureIoTClient 34:51d158b409d2 1143 {
AzureIoTClient 34:51d158b409d2 1144 DEVICE_SEND_EVENT_TASK* send_task;
AzureIoTClient 30:20a85b733111 1145
AzureIoTClient 34:51d158b409d2 1146 // Codes_SRS_DEVICE_09_052: [A structure (`send_task`) shall be created to track the send state of the message]
AzureIoTClient 34:51d158b409d2 1147 if ((send_task = (DEVICE_SEND_EVENT_TASK*)malloc(sizeof(DEVICE_SEND_EVENT_TASK))) == NULL)
AzureIoTClient 34:51d158b409d2 1148 {
AzureIoTClient 34:51d158b409d2 1149 // 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 1150 LogError("Failed sending event (failed creating task to send event)");
AzureIoTClient 34:51d158b409d2 1151 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1152 }
AzureIoTClient 34:51d158b409d2 1153 else
AzureIoTClient 34:51d158b409d2 1154 {
AzureIoTClient 34:51d158b409d2 1155 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1156
AzureIoTClient 34:51d158b409d2 1157 // Codes_SRS_DEVICE_09_054: [`send_task` shall contain the user callback and the context provided]
AzureIoTClient 34:51d158b409d2 1158 memset(send_task, 0, sizeof(DEVICE_SEND_EVENT_TASK));
AzureIoTClient 34:51d158b409d2 1159 send_task->on_event_send_complete_callback = on_device_d2c_event_send_complete_callback;
AzureIoTClient 34:51d158b409d2 1160 send_task->on_event_send_complete_context = context;
AzureIoTClient 34:51d158b409d2 1161
AzureIoTClient 36:f78f9a56869e 1162 // 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 1163 if (telemetry_messenger_send_async(instance->messenger_handle, message, on_event_send_complete_messenger_callback, (void*)send_task) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1164 {
AzureIoTClient 36:f78f9a56869e 1165 // Codes_SRS_DEVICE_09_056: [If telemetry_messenger_send_async fails, device_send_event_async shall return a non-zero value]
AzureIoTClient 36:f78f9a56869e 1166 LogError("Failed sending event (telemetry_messenger_send_async failed)");
AzureIoTClient 34:51d158b409d2 1167 // Codes_SRS_DEVICE_09_057: [If any failures occur, device_send_event_async shall release all memory it has allocated]
AzureIoTClient 34:51d158b409d2 1168 free(send_task);
AzureIoTClient 34:51d158b409d2 1169 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1170 }
AzureIoTClient 34:51d158b409d2 1171 else
AzureIoTClient 34:51d158b409d2 1172 {
AzureIoTClient 34:51d158b409d2 1173 // Codes_SRS_DEVICE_09_058: [If no failures occur, device_send_event_async shall return 0]
AzureIoTClient 34:51d158b409d2 1174 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1175 }
AzureIoTClient 34:51d158b409d2 1176 }
AzureIoTClient 34:51d158b409d2 1177 }
AzureIoTClient 30:20a85b733111 1178
AzureIoTClient 34:51d158b409d2 1179 return result;
AzureIoTClient 30:20a85b733111 1180 }
AzureIoTClient 30:20a85b733111 1181
AzureIoTClient 30:20a85b733111 1182 int device_get_send_status(DEVICE_HANDLE handle, DEVICE_SEND_STATUS *send_status)
AzureIoTClient 30:20a85b733111 1183 {
AzureIoTClient 34:51d158b409d2 1184 int result;
AzureIoTClient 30:20a85b733111 1185
AzureIoTClient 30:20a85b733111 1186
AzureIoTClient 34:51d158b409d2 1187 // 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 1188 if (handle == NULL || send_status == NULL)
AzureIoTClient 34:51d158b409d2 1189 {
AzureIoTClient 34:51d158b409d2 1190 LogError("Failed getting the device messenger send status (NULL parameter received; handle=%p, send_status=%p)", handle, send_status);
AzureIoTClient 34:51d158b409d2 1191 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1192 }
AzureIoTClient 34:51d158b409d2 1193 else
AzureIoTClient 34:51d158b409d2 1194 {
AzureIoTClient 34:51d158b409d2 1195 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 36:f78f9a56869e 1196 TELEMETRY_MESSENGER_SEND_STATUS messenger_send_status;
AzureIoTClient 34:51d158b409d2 1197
AzureIoTClient 36:f78f9a56869e 1198 // Codes_SRS_DEVICE_09_106: [The status of `instance->messenger_handle` shall be obtained using telemetry_messenger_get_send_status]
AzureIoTClient 36:f78f9a56869e 1199 if (telemetry_messenger_get_send_status(instance->messenger_handle, &messenger_send_status) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1200 {
AzureIoTClient 36:f78f9a56869e 1201 // 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 1202 LogError("Failed getting the device messenger send status (telemetry_messenger_get_send_status failed)");
AzureIoTClient 34:51d158b409d2 1203 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1204 }
AzureIoTClient 34:51d158b409d2 1205 else
AzureIoTClient 34:51d158b409d2 1206 {
AzureIoTClient 36:f78f9a56869e 1207 // 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 1208 if (messenger_send_status == TELEMETRY_MESSENGER_SEND_STATUS_IDLE)
AzureIoTClient 34:51d158b409d2 1209 {
AzureIoTClient 34:51d158b409d2 1210 *send_status = DEVICE_SEND_STATUS_IDLE;
AzureIoTClient 34:51d158b409d2 1211 }
AzureIoTClient 36:f78f9a56869e 1212 // 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 1213 else // i.e., messenger_send_status == TELEMETRY_MESSENGER_SEND_STATUS_BUSY
AzureIoTClient 34:51d158b409d2 1214 {
AzureIoTClient 34:51d158b409d2 1215 *send_status = DEVICE_SEND_STATUS_BUSY;
AzureIoTClient 34:51d158b409d2 1216 }
AzureIoTClient 30:20a85b733111 1217
AzureIoTClient 34:51d158b409d2 1218 // Codes_SRS_DEVICE_09_110: [If device_get_send_status succeeds, it shall return zero as result]
AzureIoTClient 34:51d158b409d2 1219 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1220 }
AzureIoTClient 34:51d158b409d2 1221 }
AzureIoTClient 30:20a85b733111 1222
AzureIoTClient 34:51d158b409d2 1223 return result;
AzureIoTClient 30:20a85b733111 1224 }
AzureIoTClient 30:20a85b733111 1225
AzureIoTClient 30:20a85b733111 1226 int device_subscribe_message(DEVICE_HANDLE handle, ON_DEVICE_C2D_MESSAGE_RECEIVED on_message_received_callback, void* context)
AzureIoTClient 30:20a85b733111 1227 {
AzureIoTClient 34:51d158b409d2 1228 int result;
AzureIoTClient 30:20a85b733111 1229
AzureIoTClient 34:51d158b409d2 1230 // 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 1231 if (handle == NULL || on_message_received_callback == NULL || context == NULL)
AzureIoTClient 34:51d158b409d2 1232 {
AzureIoTClient 34:51d158b409d2 1233 LogError("Failed subscribing to C2D messages (either handle (%p), on_message_received_callback (%p) or context (%p) is NULL)",
AzureIoTClient 34:51d158b409d2 1234 handle, on_message_received_callback, context);
AzureIoTClient 34:51d158b409d2 1235 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1236 }
AzureIoTClient 34:51d158b409d2 1237 else
AzureIoTClient 34:51d158b409d2 1238 {
AzureIoTClient 34:51d158b409d2 1239 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1240
AzureIoTClient 36:f78f9a56869e 1241 // 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 1242 if (telemetry_messenger_subscribe_for_messages(instance->messenger_handle, on_messenger_message_received_callback, handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1243 {
AzureIoTClient 36:f78f9a56869e 1244 // Codes_SRS_DEVICE_09_068: [If telemetry_messenger_subscribe_for_messages fails, device_subscribe_message shall return a non-zero result]
AzureIoTClient 36:f78f9a56869e 1245 LogError("Failed subscribing to C2D messages (telemetry_messenger_subscribe_for_messages failed)");
AzureIoTClient 34:51d158b409d2 1246 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1247 }
AzureIoTClient 34:51d158b409d2 1248 else
AzureIoTClient 34:51d158b409d2 1249 {
AzureIoTClient 34:51d158b409d2 1250 instance->on_message_received_callback = on_message_received_callback;
AzureIoTClient 34:51d158b409d2 1251 instance->on_message_received_context = context;
AzureIoTClient 30:20a85b733111 1252
AzureIoTClient 34:51d158b409d2 1253 // Codes_SRS_DEVICE_09_069: [If no failures occur, device_subscribe_message shall return 0]
AzureIoTClient 34:51d158b409d2 1254 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1255 }
AzureIoTClient 34:51d158b409d2 1256 }
AzureIoTClient 30:20a85b733111 1257
AzureIoTClient 34:51d158b409d2 1258 return result;
AzureIoTClient 30:20a85b733111 1259 }
AzureIoTClient 30:20a85b733111 1260
AzureIoTClient 30:20a85b733111 1261 int device_unsubscribe_message(DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 1262 {
AzureIoTClient 34:51d158b409d2 1263 int result;
AzureIoTClient 30:20a85b733111 1264
AzureIoTClient 34:51d158b409d2 1265 // Codes_SRS_DEVICE_09_076: [If `handle` is NULL, device_unsubscribe_message shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1266 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 1267 {
AzureIoTClient 34:51d158b409d2 1268 LogError("Failed unsubscribing to C2D messages (handle is NULL)");
AzureIoTClient 34:51d158b409d2 1269 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1270 }
AzureIoTClient 34:51d158b409d2 1271 else
AzureIoTClient 34:51d158b409d2 1272 {
AzureIoTClient 34:51d158b409d2 1273 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1274
AzureIoTClient 36:f78f9a56869e 1275 // Codes_SRS_DEVICE_09_077: [telemetry_messenger_unsubscribe_for_messages shall be invoked passing `instance->messenger_handle`]
AzureIoTClient 36:f78f9a56869e 1276 if (telemetry_messenger_unsubscribe_for_messages(instance->messenger_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1277 {
AzureIoTClient 36:f78f9a56869e 1278 // Codes_SRS_DEVICE_09_078: [If telemetry_messenger_unsubscribe_for_messages fails, device_unsubscribe_message shall return a non-zero result]
AzureIoTClient 36:f78f9a56869e 1279 LogError("Failed unsubscribing to C2D messages (telemetry_messenger_unsubscribe_for_messages failed)");
AzureIoTClient 34:51d158b409d2 1280 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1281 }
AzureIoTClient 34:51d158b409d2 1282 else
AzureIoTClient 34:51d158b409d2 1283 {
AzureIoTClient 34:51d158b409d2 1284 // Codes_SRS_DEVICE_09_079: [If no failures occur, device_unsubscribe_message shall return 0]
AzureIoTClient 34:51d158b409d2 1285 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1286 }
AzureIoTClient 34:51d158b409d2 1287 }
AzureIoTClient 34:51d158b409d2 1288 return result;
AzureIoTClient 30:20a85b733111 1289 }
AzureIoTClient 30:20a85b733111 1290
AzureIoTClient 30:20a85b733111 1291 int device_send_message_disposition(DEVICE_HANDLE device_handle, DEVICE_MESSAGE_DISPOSITION_INFO* disposition_info, DEVICE_MESSAGE_DISPOSITION_RESULT disposition_result)
AzureIoTClient 30:20a85b733111 1292 {
AzureIoTClient 34:51d158b409d2 1293 int result;
AzureIoTClient 30:20a85b733111 1294
AzureIoTClient 34:51d158b409d2 1295 // 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 1296 if (device_handle == NULL || disposition_info == NULL)
AzureIoTClient 34:51d158b409d2 1297 {
AzureIoTClient 34:51d158b409d2 1298 LogError("Failed sending message disposition (either device_handle (%p) or disposition_info (%p) are NULL)", device_handle, disposition_info);
AzureIoTClient 34:51d158b409d2 1299 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1300 }
AzureIoTClient 34:51d158b409d2 1301 // Codes_SRS_DEVICE_09_112: [If `disposition_info->source` is NULL, device_send_message_disposition() shall fail and return __FAILURE__]
AzureIoTClient 34:51d158b409d2 1302 else if (disposition_info->source == NULL)
AzureIoTClient 34:51d158b409d2 1303 {
AzureIoTClient 34:51d158b409d2 1304 LogError("Failed sending message disposition (disposition_info->source is NULL)");
AzureIoTClient 34:51d158b409d2 1305 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1306 }
AzureIoTClient 34:51d158b409d2 1307 else
AzureIoTClient 34:51d158b409d2 1308 {
AzureIoTClient 34:51d158b409d2 1309 DEVICE_INSTANCE* device = (DEVICE_INSTANCE*)device_handle;
AzureIoTClient 36:f78f9a56869e 1310 TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO* messenger_disposition_info;
AzureIoTClient 30:20a85b733111 1311
AzureIoTClient 36:f78f9a56869e 1312 // 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 1313 if ((messenger_disposition_info = create_messenger_disposition_info(disposition_info)) == NULL)
AzureIoTClient 34:51d158b409d2 1314 {
AzureIoTClient 36:f78f9a56869e 1315 // 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 1316 LogError("Failed sending message disposition (failed to create TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO)");
AzureIoTClient 34:51d158b409d2 1317 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1318 }
AzureIoTClient 34:51d158b409d2 1319 else
AzureIoTClient 34:51d158b409d2 1320 {
AzureIoTClient 36:f78f9a56869e 1321 TELEMETRY_MESSENGER_DISPOSITION_RESULT messenger_disposition_result = get_messenger_message_disposition_result_from(disposition_result);
AzureIoTClient 30:20a85b733111 1322
AzureIoTClient 36:f78f9a56869e 1323 // 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 1324 if (telemetry_messenger_send_message_disposition(device->messenger_handle, messenger_disposition_info, messenger_disposition_result) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1325 {
AzureIoTClient 36:f78f9a56869e 1326 // Codes_SRS_DEVICE_09_116: [If `telemetry_messenger_send_message_disposition()` fails, device_send_message_disposition() shall fail and return __FAILURE__]
AzureIoTClient 36:f78f9a56869e 1327 LogError("Failed sending message disposition (telemetry_messenger_send_message_disposition failed)");
AzureIoTClient 34:51d158b409d2 1328 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1329 }
AzureIoTClient 34:51d158b409d2 1330 else
AzureIoTClient 34:51d158b409d2 1331 {
AzureIoTClient 34:51d158b409d2 1332 // Codes_SRS_DEVICE_09_118: [If no failures occurr, device_send_message_disposition() shall return 0]
AzureIoTClient 34:51d158b409d2 1333 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1334 }
AzureIoTClient 30:20a85b733111 1335
AzureIoTClient 36:f78f9a56869e 1336 // Codes_SRS_DEVICE_09_117: [device_send_message_disposition() shall destroy the TELEMETRY_MESSENGER_MESSAGE_DISPOSITION_INFO instance]
AzureIoTClient 34:51d158b409d2 1337 destroy_messenger_disposition_info(messenger_disposition_info);
AzureIoTClient 34:51d158b409d2 1338 }
AzureIoTClient 34:51d158b409d2 1339 }
AzureIoTClient 30:20a85b733111 1340
AzureIoTClient 34:51d158b409d2 1341 return result;
AzureIoTClient 30:20a85b733111 1342 }
AzureIoTClient 30:20a85b733111 1343
AzureIoTClient 30:20a85b733111 1344 int device_set_retry_policy(DEVICE_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY policy, size_t retry_timeout_limit_in_seconds)
AzureIoTClient 30:20a85b733111 1345 {
AzureIoTClient 34:51d158b409d2 1346 (void)retry_timeout_limit_in_seconds;
AzureIoTClient 34:51d158b409d2 1347 (void)policy;
AzureIoTClient 34:51d158b409d2 1348 int result;
AzureIoTClient 30:20a85b733111 1349
AzureIoTClient 34:51d158b409d2 1350 // Codes_SRS_DEVICE_09_080: [If `handle` is NULL, device_set_retry_policy shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1351 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 1352 {
AzureIoTClient 34:51d158b409d2 1353 LogError("Failed setting retry policy (handle is NULL)");
AzureIoTClient 34:51d158b409d2 1354 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1355 }
AzureIoTClient 34:51d158b409d2 1356 else
AzureIoTClient 34:51d158b409d2 1357 {
AzureIoTClient 34:51d158b409d2 1358 // Codes_SRS_DEVICE_09_081: [device_set_retry_policy shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1359 LogError("Failed setting retry policy (functionality not supported)");
AzureIoTClient 34:51d158b409d2 1360 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1361 }
AzureIoTClient 30:20a85b733111 1362
AzureIoTClient 34:51d158b409d2 1363 return result;
AzureIoTClient 30:20a85b733111 1364 }
AzureIoTClient 30:20a85b733111 1365
AzureIoTClient 30:20a85b733111 1366 int device_set_option(DEVICE_HANDLE handle, const char* name, void* value)
AzureIoTClient 30:20a85b733111 1367 {
AzureIoTClient 34:51d158b409d2 1368 int result;
AzureIoTClient 30:20a85b733111 1369
AzureIoTClient 34:51d158b409d2 1370 // 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 1371 if (handle == NULL || name == NULL || value == NULL)
AzureIoTClient 34:51d158b409d2 1372 {
AzureIoTClient 34:51d158b409d2 1373 LogError("failed setting device option (one of the followin are NULL: _handle=%p, name=%p, value=%p)",
AzureIoTClient 34:51d158b409d2 1374 handle, name, value);
AzureIoTClient 34:51d158b409d2 1375 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1376 }
AzureIoTClient 34:51d158b409d2 1377 else
AzureIoTClient 34:51d158b409d2 1378 {
AzureIoTClient 34:51d158b409d2 1379 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1380
AzureIoTClient 34:51d158b409d2 1381 if (strcmp(DEVICE_OPTION_CBS_REQUEST_TIMEOUT_SECS, name) == 0 ||
AzureIoTClient 34:51d158b409d2 1382 strcmp(DEVICE_OPTION_SAS_TOKEN_REFRESH_TIME_SECS, name) == 0 ||
AzureIoTClient 34:51d158b409d2 1383 strcmp(DEVICE_OPTION_SAS_TOKEN_LIFETIME_SECS, name) == 0)
AzureIoTClient 34:51d158b409d2 1384 {
AzureIoTClient 34:51d158b409d2 1385 // 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 1386 if (instance->authentication_handle == NULL)
AzureIoTClient 34:51d158b409d2 1387 {
AzureIoTClient 34:51d158b409d2 1388 LogError("failed setting option for device '%s' (cannot set authentication option '%s'; not using CBS authentication)", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1389 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1390 }
AzureIoTClient 34:51d158b409d2 1391 // Codes_SRS_DEVICE_09_084: [If `name` refers to authentication, it shall be passed along with `value` to authentication_set_option]
AzureIoTClient 34:51d158b409d2 1392 else if(authentication_set_option(instance->authentication_handle, name, value) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1393 {
AzureIoTClient 34:51d158b409d2 1394 // Codes_SRS_DEVICE_09_085: [If authentication_set_option fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1395 LogError("failed setting option for device '%s' (failed setting authentication option '%s')", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1396 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1397 }
AzureIoTClient 34:51d158b409d2 1398 else
AzureIoTClient 34:51d158b409d2 1399 {
AzureIoTClient 34:51d158b409d2 1400 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1401 }
AzureIoTClient 34:51d158b409d2 1402 }
AzureIoTClient 34:51d158b409d2 1403 else if (strcmp(DEVICE_OPTION_EVENT_SEND_TIMEOUT_SECS, name) == 0)
AzureIoTClient 34:51d158b409d2 1404 {
AzureIoTClient 36:f78f9a56869e 1405 // Codes_SRS_DEVICE_09_086: [If `name` refers to messenger module, it shall be passed along with `value` to telemetry_messenger_set_option]
AzureIoTClient 36:f78f9a56869e 1406 if (telemetry_messenger_set_option(instance->messenger_handle, MESSENGER_OPTION_EVENT_SEND_TIMEOUT_SECS, value) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1407 {
AzureIoTClient 36:f78f9a56869e 1408 // Codes_SRS_DEVICE_09_087: [If telemetry_messenger_set_option fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1409 LogError("failed setting option for device '%s' (failed setting messenger option '%s')", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1410 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1411 }
AzureIoTClient 34:51d158b409d2 1412 else
AzureIoTClient 34:51d158b409d2 1413 {
AzureIoTClient 34:51d158b409d2 1414 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1415 }
AzureIoTClient 34:51d158b409d2 1416 }
AzureIoTClient 34:51d158b409d2 1417 else if (strcmp(DEVICE_OPTION_SAVED_AUTH_OPTIONS, name) == 0)
AzureIoTClient 34:51d158b409d2 1418 {
AzureIoTClient 34:51d158b409d2 1419 // 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 1420 if (instance->authentication_handle == NULL)
AzureIoTClient 34:51d158b409d2 1421 {
AzureIoTClient 34:51d158b409d2 1422 LogError("failed setting option for device '%s' (cannot set authentication option '%s'; not using CBS authentication)", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1423 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1424 }
AzureIoTClient 34:51d158b409d2 1425 else if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, instance->authentication_handle) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1426 {
AzureIoTClient 34:51d158b409d2 1427 // Codes_SRS_DEVICE_09_091: [If any call to OptionHandler_FeedOptions fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1428 LogError("failed setting option for device '%s' (OptionHandler_FeedOptions failed for authentication instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1429 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1430 }
AzureIoTClient 34:51d158b409d2 1431 else
AzureIoTClient 34:51d158b409d2 1432 {
AzureIoTClient 34:51d158b409d2 1433 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1434 }
AzureIoTClient 34:51d158b409d2 1435 }
AzureIoTClient 34:51d158b409d2 1436 else if (strcmp(DEVICE_OPTION_SAVED_MESSENGER_OPTIONS, name) == 0)
AzureIoTClient 34:51d158b409d2 1437 {
AzureIoTClient 34:51d158b409d2 1438 // 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 1439 if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, instance->messenger_handle) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1440 {
AzureIoTClient 34:51d158b409d2 1441 // Codes_SRS_DEVICE_09_091: [If any call to OptionHandler_FeedOptions fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1442 LogError("failed setting option for device '%s' (OptionHandler_FeedOptions failed for messenger instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1443 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1444 }
AzureIoTClient 34:51d158b409d2 1445 else
AzureIoTClient 34:51d158b409d2 1446 {
AzureIoTClient 34:51d158b409d2 1447 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1448 }
AzureIoTClient 34:51d158b409d2 1449 }
AzureIoTClient 34:51d158b409d2 1450 else if (strcmp(DEVICE_OPTION_SAVED_OPTIONS, name) == 0)
AzureIoTClient 34:51d158b409d2 1451 {
AzureIoTClient 34:51d158b409d2 1452 // Codes_SRS_DEVICE_09_090: [If `name` is DEVICE_OPTION_SAVED_OPTIONS, `value` shall be fed to `instance` using OptionHandler_FeedOptions]
AzureIoTClient 34:51d158b409d2 1453 if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, handle) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1454 {
AzureIoTClient 34:51d158b409d2 1455 // Codes_SRS_DEVICE_09_091: [If any call to OptionHandler_FeedOptions fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1456 LogError("failed setting option for device '%s' (OptionHandler_FeedOptions failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1457 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1458 }
AzureIoTClient 34:51d158b409d2 1459 else
AzureIoTClient 34:51d158b409d2 1460 {
AzureIoTClient 34:51d158b409d2 1461 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1462 }
AzureIoTClient 34:51d158b409d2 1463 }
AzureIoTClient 34:51d158b409d2 1464 else
AzureIoTClient 34:51d158b409d2 1465 {
AzureIoTClient 34:51d158b409d2 1466 // Codes_SRS_DEVICE_09_092: [If no failures occur, device_set_option shall return 0]
AzureIoTClient 34:51d158b409d2 1467 LogError("failed setting option for device '%s' (option with name '%s' is not suppported)", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1468 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1469 }
AzureIoTClient 34:51d158b409d2 1470 }
AzureIoTClient 30:20a85b733111 1471
AzureIoTClient 34:51d158b409d2 1472 return result;
AzureIoTClient 30:20a85b733111 1473 }
AzureIoTClient 30:20a85b733111 1474
AzureIoTClient 30:20a85b733111 1475 OPTIONHANDLER_HANDLE device_retrieve_options(DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 1476 {
AzureIoTClient 34:51d158b409d2 1477 OPTIONHANDLER_HANDLE result;
AzureIoTClient 30:20a85b733111 1478
AzureIoTClient 34:51d158b409d2 1479 // Codes_SRS_DEVICE_09_093: [If `handle` is NULL, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1480 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 1481 {
AzureIoTClient 34:51d158b409d2 1482 LogError("Failed to retrieve options from device instance (handle is NULL)");
AzureIoTClient 34:51d158b409d2 1483 result = NULL;
AzureIoTClient 34:51d158b409d2 1484 }
AzureIoTClient 34:51d158b409d2 1485 else
AzureIoTClient 34:51d158b409d2 1486 {
AzureIoTClient 34:51d158b409d2 1487 // Codes_SRS_DEVICE_09_094: [A OPTIONHANDLER_HANDLE instance, aka `options` shall be created using OptionHandler_Create]
AzureIoTClient 34:51d158b409d2 1488 OPTIONHANDLER_HANDLE options = OptionHandler_Create(device_clone_option, device_destroy_option, (pfSetOption)device_set_option);
AzureIoTClient 30:20a85b733111 1489
AzureIoTClient 34:51d158b409d2 1490 if (options == NULL)
AzureIoTClient 34:51d158b409d2 1491 {
AzureIoTClient 34:51d158b409d2 1492 // Codes_SRS_DEVICE_09_095: [If OptionHandler_Create fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1493 LogError("Failed to retrieve options from device instance (OptionHandler_Create failed)");
AzureIoTClient 34:51d158b409d2 1494 result = NULL;
AzureIoTClient 34:51d158b409d2 1495 }
AzureIoTClient 34:51d158b409d2 1496 else
AzureIoTClient 34:51d158b409d2 1497 {
AzureIoTClient 34:51d158b409d2 1498 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1499
AzureIoTClient 34:51d158b409d2 1500 OPTIONHANDLER_HANDLE dependency_options = NULL;
AzureIoTClient 30:20a85b733111 1501
AzureIoTClient 34:51d158b409d2 1502 // Codes_SRS_DEVICE_09_096: [If CBS authentication is used, `instance->authentication_handle` options shall be retrieved using authentication_retrieve_options]
AzureIoTClient 34:51d158b409d2 1503 if (instance->authentication_handle != NULL &&
AzureIoTClient 34:51d158b409d2 1504 (dependency_options = authentication_retrieve_options(instance->authentication_handle)) == NULL)
AzureIoTClient 34:51d158b409d2 1505 {
AzureIoTClient 34:51d158b409d2 1506 // Codes_SRS_DEVICE_09_097: [If authentication_retrieve_options fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1507 LogError("Failed to retrieve options from device '%s' (failed to retrieve options from authentication instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1508 result = NULL;
AzureIoTClient 34:51d158b409d2 1509 }
AzureIoTClient 34:51d158b409d2 1510 // 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 1511 else if (instance->authentication_handle != NULL &&
AzureIoTClient 34:51d158b409d2 1512 OptionHandler_AddOption(options, DEVICE_OPTION_SAVED_AUTH_OPTIONS, (const void*)dependency_options) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1513 {
AzureIoTClient 34:51d158b409d2 1514 // Codes_SRS_DEVICE_09_102: [If any call to OptionHandler_AddOption fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1515 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 1516 result = NULL;
AzureIoTClient 34:51d158b409d2 1517 }
AzureIoTClient 36:f78f9a56869e 1518 // Codes_SRS_DEVICE_09_099: [`instance->messenger_handle` options shall be retrieved using telemetry_messenger_retrieve_options]
AzureIoTClient 36:f78f9a56869e 1519 else if ((dependency_options = telemetry_messenger_retrieve_options(instance->messenger_handle)) == NULL)
AzureIoTClient 34:51d158b409d2 1520 {
AzureIoTClient 36:f78f9a56869e 1521 // Codes_SRS_DEVICE_09_100: [If telemetry_messenger_retrieve_options fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1522 LogError("Failed to retrieve options from device '%s' (failed to retrieve options from messenger instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1523 result = NULL;
AzureIoTClient 34:51d158b409d2 1524 }
AzureIoTClient 34:51d158b409d2 1525 // 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 1526 else if (OptionHandler_AddOption(options, DEVICE_OPTION_SAVED_MESSENGER_OPTIONS, (const void*)dependency_options) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1527 {
AzureIoTClient 34:51d158b409d2 1528 // Codes_SRS_DEVICE_09_102: [If any call to OptionHandler_AddOption fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1529 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 1530 result = NULL;
AzureIoTClient 34:51d158b409d2 1531 }
AzureIoTClient 34:51d158b409d2 1532 else
AzureIoTClient 34:51d158b409d2 1533 {
AzureIoTClient 34:51d158b409d2 1534 // Codes_SRS_DEVICE_09_104: [If no failures occur, a handle to `options` shall be return]
AzureIoTClient 34:51d158b409d2 1535 result = options;
AzureIoTClient 34:51d158b409d2 1536 }
AzureIoTClient 30:20a85b733111 1537
AzureIoTClient 34:51d158b409d2 1538 if (result == NULL)
AzureIoTClient 34:51d158b409d2 1539 {
AzureIoTClient 34:51d158b409d2 1540 // Codes_SRS_DEVICE_09_103: [If any failure occurs, any memory allocated by device_retrieve_options shall be destroyed]
AzureIoTClient 34:51d158b409d2 1541 OptionHandler_Destroy(options);
AzureIoTClient 34:51d158b409d2 1542 }
AzureIoTClient 34:51d158b409d2 1543 }
AzureIoTClient 34:51d158b409d2 1544 }
AzureIoTClient 30:20a85b733111 1545
AzureIoTClient 34:51d158b409d2 1546 return result;
AzureIoTClient 30:20a85b733111 1547 }
AzureIoTClient 39:e98d5df6dc74 1548
AzureIoTClient 39:e98d5df6dc74 1549 int device_send_twin_update_async(DEVICE_HANDLE handle, CONSTBUFFER_HANDLE data, DEVICE_SEND_TWIN_UPDATE_COMPLETE_CALLBACK on_send_twin_update_complete_callback, void* context)
AzureIoTClient 39:e98d5df6dc74 1550 {
AzureIoTClient 41:71c01aa3df1a 1551 int result;
AzureIoTClient 39:e98d5df6dc74 1552
AzureIoTClient 41:71c01aa3df1a 1553 // 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 1554 if (handle == NULL || data == NULL)
AzureIoTClient 41:71c01aa3df1a 1555 {
AzureIoTClient 41:71c01aa3df1a 1556 LogError("Invalid argument (handle=%p, data=%p)", handle, data);
AzureIoTClient 41:71c01aa3df1a 1557 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1558 }
AzureIoTClient 41:71c01aa3df1a 1559 else
AzureIoTClient 41:71c01aa3df1a 1560 {
AzureIoTClient 41:71c01aa3df1a 1561 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 41:71c01aa3df1a 1562 DEVICE_SEND_TWIN_UPDATE_CONTEXT* twin_ctx;
AzureIoTClient 39:e98d5df6dc74 1563
AzureIoTClient 41:71c01aa3df1a 1564 // Codes_SRS_DEVICE_09_136: [A structure (`twin_ctx`) shall be created to track the send state of the twin report]
AzureIoTClient 41:71c01aa3df1a 1565 if ((twin_ctx = (DEVICE_SEND_TWIN_UPDATE_CONTEXT*)malloc(sizeof(DEVICE_SEND_TWIN_UPDATE_CONTEXT))) == NULL)
AzureIoTClient 41:71c01aa3df1a 1566 {
AzureIoTClient 41:71c01aa3df1a 1567 // 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 1568 LogError("Cannot send twin update (failed creating TWIN context)");
AzureIoTClient 41:71c01aa3df1a 1569 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1570 }
AzureIoTClient 41:71c01aa3df1a 1571 else
AzureIoTClient 41:71c01aa3df1a 1572 {
AzureIoTClient 41:71c01aa3df1a 1573 twin_ctx->on_send_twin_update_complete_callback = on_send_twin_update_complete_callback;
AzureIoTClient 41:71c01aa3df1a 1574 twin_ctx->context = context;
AzureIoTClient 39:e98d5df6dc74 1575
AzureIoTClient 41:71c01aa3df1a 1576 // 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 1577 if (twin_messenger_report_state_async(instance->twin_messenger_handle, data, on_report_state_complete_callback, (const void*)twin_ctx) != 0)
AzureIoTClient 41:71c01aa3df1a 1578 {
AzureIoTClient 41:71c01aa3df1a 1579 // 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 1580 LogError("Cannot send twin update (failed creating TWIN messenger)");
AzureIoTClient 41:71c01aa3df1a 1581 free(twin_ctx);
AzureIoTClient 41:71c01aa3df1a 1582 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1583 }
AzureIoTClient 41:71c01aa3df1a 1584 else
AzureIoTClient 41:71c01aa3df1a 1585 {
AzureIoTClient 41:71c01aa3df1a 1586 // Codes_SRS_DEVICE_09_140: [If no failures occur, device_send_twin_update_async shall return 0]
AzureIoTClient 41:71c01aa3df1a 1587 result = RESULT_OK;
AzureIoTClient 41:71c01aa3df1a 1588 }
AzureIoTClient 41:71c01aa3df1a 1589 }
AzureIoTClient 41:71c01aa3df1a 1590 }
AzureIoTClient 39:e98d5df6dc74 1591
AzureIoTClient 41:71c01aa3df1a 1592 return result;
AzureIoTClient 39:e98d5df6dc74 1593 }
AzureIoTClient 39:e98d5df6dc74 1594
AzureIoTClient 39:e98d5df6dc74 1595 int device_subscribe_for_twin_updates(DEVICE_HANDLE handle, DEVICE_TWIN_UPDATE_RECEIVED_CALLBACK on_device_twin_update_received_callback, void* context)
AzureIoTClient 39:e98d5df6dc74 1596 {
AzureIoTClient 41:71c01aa3df1a 1597 int result;
AzureIoTClient 39:e98d5df6dc74 1598
AzureIoTClient 41:71c01aa3df1a 1599 // 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 1600 if (handle == NULL || on_device_twin_update_received_callback == NULL)
AzureIoTClient 41:71c01aa3df1a 1601 {
AzureIoTClient 41:71c01aa3df1a 1602 LogError("Invalid argument (handle=%p, on_device_twin_update_received_callback=%p)", handle, on_device_twin_update_received_callback);
AzureIoTClient 41:71c01aa3df1a 1603 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1604 }
AzureIoTClient 41:71c01aa3df1a 1605 else
AzureIoTClient 41:71c01aa3df1a 1606 {
AzureIoTClient 41:71c01aa3df1a 1607 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 39:e98d5df6dc74 1608
AzureIoTClient 41:71c01aa3df1a 1609 DEVICE_TWIN_UPDATE_RECEIVED_CALLBACK previous_callback = instance->on_device_twin_update_received_callback;
AzureIoTClient 41:71c01aa3df1a 1610 void* previous_context = instance->on_device_twin_update_received_context;
AzureIoTClient 39:e98d5df6dc74 1611
AzureIoTClient 41:71c01aa3df1a 1612 instance->on_device_twin_update_received_callback = on_device_twin_update_received_callback;
AzureIoTClient 41:71c01aa3df1a 1613 instance->on_device_twin_update_received_context = context;
AzureIoTClient 39:e98d5df6dc74 1614
AzureIoTClient 41:71c01aa3df1a 1615 // Codes_SRS_DEVICE_09_144: [twin_messenger_subscribe shall be invoked passing `on_twin_state_update_callback`]
AzureIoTClient 41:71c01aa3df1a 1616 if (twin_messenger_subscribe(instance->twin_messenger_handle, on_twin_state_update_callback, (void*)instance) != 0)
AzureIoTClient 41:71c01aa3df1a 1617 {
AzureIoTClient 41:71c01aa3df1a 1618 // Codes_SRS_DEVICE_09_145: [If twin_messenger_subscribe fails, device_subscribe_for_twin_updates shall return a non-zero value]
AzureIoTClient 41:71c01aa3df1a 1619 LogError("Failed subscribing for device twin updates");
AzureIoTClient 41:71c01aa3df1a 1620 instance->on_device_twin_update_received_callback = previous_callback;
AzureIoTClient 41:71c01aa3df1a 1621 instance->on_device_twin_update_received_context = previous_context;
AzureIoTClient 41:71c01aa3df1a 1622 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1623 }
AzureIoTClient 41:71c01aa3df1a 1624 else
AzureIoTClient 41:71c01aa3df1a 1625 {
AzureIoTClient 41:71c01aa3df1a 1626 // Codes_SRS_DEVICE_09_146: [If no failures occur, device_subscribe_for_twin_updates shall return 0]
AzureIoTClient 41:71c01aa3df1a 1627 result = RESULT_OK;
AzureIoTClient 41:71c01aa3df1a 1628 }
AzureIoTClient 41:71c01aa3df1a 1629 }
AzureIoTClient 39:e98d5df6dc74 1630
AzureIoTClient 41:71c01aa3df1a 1631 return result;
AzureIoTClient 39:e98d5df6dc74 1632 }
AzureIoTClient 39:e98d5df6dc74 1633
AzureIoTClient 39:e98d5df6dc74 1634 int device_unsubscribe_for_twin_updates(DEVICE_HANDLE handle)
AzureIoTClient 39:e98d5df6dc74 1635 {
AzureIoTClient 41:71c01aa3df1a 1636 int result;
AzureIoTClient 39:e98d5df6dc74 1637
AzureIoTClient 39:e98d5df6dc74 1638
AzureIoTClient 41:71c01aa3df1a 1639 // Codes_SRS_DEVICE_09_147: [If `handle` is NULL, device_unsubscribe_for_twin_updates shall return a non-zero result]
AzureIoTClient 41:71c01aa3df1a 1640 if (handle == NULL)
AzureIoTClient 41:71c01aa3df1a 1641 {
AzureIoTClient 41:71c01aa3df1a 1642 LogError("Invalid argument (handle is NULL)");
AzureIoTClient 41:71c01aa3df1a 1643 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1644 }
AzureIoTClient 41:71c01aa3df1a 1645 else
AzureIoTClient 41:71c01aa3df1a 1646 {
AzureIoTClient 41:71c01aa3df1a 1647 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 39:e98d5df6dc74 1648
AzureIoTClient 41:71c01aa3df1a 1649 // Codes_SRS_DEVICE_09_148: [twin_messenger_unsubscribe shall be invoked passing `on_twin_state_update_callback`]
AzureIoTClient 41:71c01aa3df1a 1650 if (twin_messenger_unsubscribe(instance->twin_messenger_handle) != 0)
AzureIoTClient 41:71c01aa3df1a 1651 {
AzureIoTClient 41:71c01aa3df1a 1652 // Codes_SRS_DEVICE_09_149: [If twin_messenger_unsubscribe fails, device_unsubscribe_for_twin_updates shall return a non-zero value]
AzureIoTClient 41:71c01aa3df1a 1653 LogError("Failed unsubscribing for device twin updates");
AzureIoTClient 41:71c01aa3df1a 1654 result = __FAILURE__;
AzureIoTClient 41:71c01aa3df1a 1655 }
AzureIoTClient 41:71c01aa3df1a 1656 else
AzureIoTClient 41:71c01aa3df1a 1657 {
AzureIoTClient 41:71c01aa3df1a 1658 instance->on_device_twin_update_received_callback = NULL;
AzureIoTClient 41:71c01aa3df1a 1659 instance->on_device_twin_update_received_context = NULL;
AzureIoTClient 41:71c01aa3df1a 1660 // Codes_SRS_DEVICE_09_150: [If no failures occur, device_unsubscribe_for_twin_updates shall return 0]
AzureIoTClient 41:71c01aa3df1a 1661 result = RESULT_OK;
AzureIoTClient 41:71c01aa3df1a 1662 }
AzureIoTClient 41:71c01aa3df1a 1663 }
AzureIoTClient 39:e98d5df6dc74 1664
AzureIoTClient 41:71c01aa3df1a 1665 return result;
AzureIoTClient 39:e98d5df6dc74 1666 }