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 May 08 10:49:54 2017 -0700
Revision:
34:51d158b409d2
Parent:
30:20a85b733111
Child:
36:f78f9a56869e
1.1.14

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 "iothubtransport_amqp_messenger.h"
AzureIoTClient 30:20a85b733111 6 #include "azure_c_shared_utility/optimize_size.h"
AzureIoTClient 30:20a85b733111 7 #include "azure_c_shared_utility/gballoc.h"
AzureIoTClient 30:20a85b733111 8 #include "azure_c_shared_utility/agenttime.h"
AzureIoTClient 30:20a85b733111 9 #include "azure_c_shared_utility/xlogging.h"
AzureIoTClient 30:20a85b733111 10 #include "azure_c_shared_utility/strings.h"
AzureIoTClient 30:20a85b733111 11 #include "iothubtransport_amqp_cbs_auth.h"
AzureIoTClient 30:20a85b733111 12 #include "iothubtransport_amqp_device.h"
AzureIoTClient 30:20a85b733111 13
AzureIoTClient 30:20a85b733111 14 #define RESULT_OK 0
AzureIoTClient 30:20a85b733111 15 #define INDEFINITE_TIME ((time_t)-1)
AzureIoTClient 30:20a85b733111 16 #define DEFAULT_AUTH_STATE_CHANGED_TIMEOUT_SECS 60
AzureIoTClient 30:20a85b733111 17 #define DEFAULT_MSGR_STATE_CHANGED_TIMEOUT_SECS 60
AzureIoTClient 30:20a85b733111 18
AzureIoTClient 30:20a85b733111 19 static const char* DEVICE_OPTION_SAVED_AUTH_OPTIONS = "saved_device_auth_options";
AzureIoTClient 30:20a85b733111 20 static const char* DEVICE_OPTION_SAVED_MESSENGER_OPTIONS = "saved_device_messenger_options";
AzureIoTClient 30:20a85b733111 21
AzureIoTClient 30:20a85b733111 22 typedef struct DEVICE_INSTANCE_TAG
AzureIoTClient 30:20a85b733111 23 {
AzureIoTClient 34:51d158b409d2 24 DEVICE_CONFIG* config;
AzureIoTClient 34:51d158b409d2 25 DEVICE_STATE state;
AzureIoTClient 30:20a85b733111 26
AzureIoTClient 34:51d158b409d2 27 SESSION_HANDLE session_handle;
AzureIoTClient 34:51d158b409d2 28 CBS_HANDLE cbs_handle;
AzureIoTClient 30:20a85b733111 29
AzureIoTClient 34:51d158b409d2 30 AUTHENTICATION_HANDLE authentication_handle;
AzureIoTClient 34:51d158b409d2 31 AUTHENTICATION_STATE auth_state;
AzureIoTClient 34:51d158b409d2 32 AUTHENTICATION_ERROR_CODE auth_error_code;
AzureIoTClient 34:51d158b409d2 33 time_t auth_state_last_changed_time;
AzureIoTClient 34:51d158b409d2 34 size_t auth_state_change_timeout_secs;
AzureIoTClient 30:20a85b733111 35
AzureIoTClient 34:51d158b409d2 36 MESSENGER_HANDLE messenger_handle;
AzureIoTClient 34:51d158b409d2 37 MESSENGER_STATE msgr_state;
AzureIoTClient 34:51d158b409d2 38 time_t msgr_state_last_changed_time;
AzureIoTClient 34:51d158b409d2 39 size_t msgr_state_change_timeout_secs;
AzureIoTClient 30:20a85b733111 40
AzureIoTClient 34:51d158b409d2 41 ON_DEVICE_C2D_MESSAGE_RECEIVED on_message_received_callback;
AzureIoTClient 34:51d158b409d2 42 void* on_message_received_context;
AzureIoTClient 30:20a85b733111 43 } DEVICE_INSTANCE;
AzureIoTClient 30:20a85b733111 44
AzureIoTClient 30:20a85b733111 45 typedef struct DEVICE_SEND_EVENT_TASK_TAG
AzureIoTClient 30:20a85b733111 46 {
AzureIoTClient 34:51d158b409d2 47 ON_DEVICE_D2C_EVENT_SEND_COMPLETE on_event_send_complete_callback;
AzureIoTClient 34:51d158b409d2 48 void* on_event_send_complete_context;
AzureIoTClient 30:20a85b733111 49 } DEVICE_SEND_EVENT_TASK;
AzureIoTClient 30:20a85b733111 50
AzureIoTClient 30:20a85b733111 51 // Internal state control
AzureIoTClient 30:20a85b733111 52 static void update_state(DEVICE_INSTANCE* instance, DEVICE_STATE new_state)
AzureIoTClient 30:20a85b733111 53 {
AzureIoTClient 34:51d158b409d2 54 if (new_state != instance->state)
AzureIoTClient 34:51d158b409d2 55 {
AzureIoTClient 34:51d158b409d2 56 DEVICE_STATE previous_state = instance->state;
AzureIoTClient 34:51d158b409d2 57 instance->state = new_state;
AzureIoTClient 30:20a85b733111 58
AzureIoTClient 34:51d158b409d2 59 if (instance->config->on_state_changed_callback != NULL)
AzureIoTClient 34:51d158b409d2 60 {
AzureIoTClient 34:51d158b409d2 61 instance->config->on_state_changed_callback(instance->config->on_state_changed_context, previous_state, new_state);
AzureIoTClient 34:51d158b409d2 62 }
AzureIoTClient 34:51d158b409d2 63 }
AzureIoTClient 30:20a85b733111 64 }
AzureIoTClient 30:20a85b733111 65
AzureIoTClient 30:20a85b733111 66 static int is_timeout_reached(time_t start_time, size_t timeout_in_secs, int *is_timed_out)
AzureIoTClient 30:20a85b733111 67 {
AzureIoTClient 34:51d158b409d2 68 int result;
AzureIoTClient 30:20a85b733111 69
AzureIoTClient 34:51d158b409d2 70 if (start_time == INDEFINITE_TIME)
AzureIoTClient 34:51d158b409d2 71 {
AzureIoTClient 34:51d158b409d2 72 LogError("Failed to verify timeout (start_time is INDEFINITE)");
AzureIoTClient 34:51d158b409d2 73 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 74 }
AzureIoTClient 34:51d158b409d2 75 else
AzureIoTClient 34:51d158b409d2 76 {
AzureIoTClient 34:51d158b409d2 77 time_t current_time;
AzureIoTClient 30:20a85b733111 78
AzureIoTClient 34:51d158b409d2 79 if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
AzureIoTClient 34:51d158b409d2 80 {
AzureIoTClient 34:51d158b409d2 81 LogError("Failed to verify timeout (get_time failed)");
AzureIoTClient 34:51d158b409d2 82 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 83 }
AzureIoTClient 34:51d158b409d2 84 else
AzureIoTClient 34:51d158b409d2 85 {
AzureIoTClient 34:51d158b409d2 86 if (get_difftime(current_time, start_time) >= timeout_in_secs)
AzureIoTClient 34:51d158b409d2 87 {
AzureIoTClient 34:51d158b409d2 88 *is_timed_out = 1;
AzureIoTClient 34:51d158b409d2 89 }
AzureIoTClient 34:51d158b409d2 90 else
AzureIoTClient 34:51d158b409d2 91 {
AzureIoTClient 34:51d158b409d2 92 *is_timed_out = 0;
AzureIoTClient 34:51d158b409d2 93 }
AzureIoTClient 30:20a85b733111 94
AzureIoTClient 34:51d158b409d2 95 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 96 }
AzureIoTClient 34:51d158b409d2 97 }
AzureIoTClient 30:20a85b733111 98
AzureIoTClient 34:51d158b409d2 99 return result;
AzureIoTClient 30:20a85b733111 100 }
AzureIoTClient 30:20a85b733111 101
AzureIoTClient 30:20a85b733111 102 // Callback Handlers
AzureIoTClient 30:20a85b733111 103 static D2C_EVENT_SEND_RESULT get_d2c_event_send_result_from(MESSENGER_EVENT_SEND_COMPLETE_RESULT result)
AzureIoTClient 30:20a85b733111 104 {
AzureIoTClient 34:51d158b409d2 105 D2C_EVENT_SEND_RESULT d2c_esr;
AzureIoTClient 30:20a85b733111 106
AzureIoTClient 34:51d158b409d2 107 switch (result)
AzureIoTClient 34:51d158b409d2 108 {
AzureIoTClient 34:51d158b409d2 109 case MESSENGER_EVENT_SEND_COMPLETE_RESULT_OK:
AzureIoTClient 34:51d158b409d2 110 d2c_esr = D2C_EVENT_SEND_COMPLETE_RESULT_OK;
AzureIoTClient 34:51d158b409d2 111 break;
AzureIoTClient 34:51d158b409d2 112 case MESSENGER_EVENT_SEND_COMPLETE_RESULT_ERROR_CANNOT_PARSE:
AzureIoTClient 34:51d158b409d2 113 d2c_esr = D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_CANNOT_PARSE;
AzureIoTClient 34:51d158b409d2 114 break;
AzureIoTClient 34:51d158b409d2 115 case MESSENGER_EVENT_SEND_COMPLETE_RESULT_ERROR_FAIL_SENDING:
AzureIoTClient 34:51d158b409d2 116 d2c_esr = D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_FAIL_SENDING;
AzureIoTClient 34:51d158b409d2 117 break;
AzureIoTClient 34:51d158b409d2 118 case MESSENGER_EVENT_SEND_COMPLETE_RESULT_ERROR_TIMEOUT:
AzureIoTClient 34:51d158b409d2 119 d2c_esr = D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_TIMEOUT;
AzureIoTClient 34:51d158b409d2 120 break;
AzureIoTClient 34:51d158b409d2 121 case MESSENGER_EVENT_SEND_COMPLETE_RESULT_MESSENGER_DESTROYED:
AzureIoTClient 34:51d158b409d2 122 d2c_esr = D2C_EVENT_SEND_COMPLETE_RESULT_DEVICE_DESTROYED;
AzureIoTClient 34:51d158b409d2 123 break;
AzureIoTClient 34:51d158b409d2 124 default:
AzureIoTClient 34:51d158b409d2 125 // This is not expected. All states should be mapped.
AzureIoTClient 34:51d158b409d2 126 d2c_esr = D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_UNKNOWN;
AzureIoTClient 34:51d158b409d2 127 break;
AzureIoTClient 34:51d158b409d2 128 };
AzureIoTClient 30:20a85b733111 129
AzureIoTClient 34:51d158b409d2 130 return d2c_esr;
AzureIoTClient 30:20a85b733111 131 }
AzureIoTClient 30:20a85b733111 132
AzureIoTClient 30:20a85b733111 133 static void on_event_send_complete_messenger_callback(IOTHUB_MESSAGE_LIST* iothub_message, MESSENGER_EVENT_SEND_COMPLETE_RESULT ev_send_comp_result, void* context)
AzureIoTClient 30:20a85b733111 134 {
AzureIoTClient 34:51d158b409d2 135 if (iothub_message == NULL || context == NULL)
AzureIoTClient 34:51d158b409d2 136 {
AzureIoTClient 34:51d158b409d2 137 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 138 }
AzureIoTClient 34:51d158b409d2 139 else
AzureIoTClient 34:51d158b409d2 140 {
AzureIoTClient 34:51d158b409d2 141 DEVICE_SEND_EVENT_TASK* send_task = (DEVICE_SEND_EVENT_TASK*)context;
AzureIoTClient 30:20a85b733111 142
AzureIoTClient 34:51d158b409d2 143 // Codes_SRS_DEVICE_09_059: [If `ev_send_comp_result` is MESSENGER_EVENT_SEND_COMPLETE_RESULT_OK, D2C_EVENT_SEND_COMPLETE_RESULT_OK shall be reported as `event_send_complete`]
AzureIoTClient 34:51d158b409d2 144 // Codes_SRS_DEVICE_09_060: [If `ev_send_comp_result` is MESSENGER_EVENT_SEND_COMPLETE_RESULT_ERROR_CANNOT_PARSE, D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_CANNOT_PARSE shall be reported as `event_send_complete`]
AzureIoTClient 34:51d158b409d2 145 // Codes_SRS_DEVICE_09_061: [If `ev_send_comp_result` is MESSENGER_EVENT_SEND_COMPLETE_RESULT_ERROR_FAIL_SENDING, D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_FAIL_SENDING shall be reported as `event_send_complete`]
AzureIoTClient 34:51d158b409d2 146 // Codes_SRS_DEVICE_09_062: [If `ev_send_comp_result` is MESSENGER_EVENT_SEND_COMPLETE_RESULT_ERROR_TIMEOUT, D2C_EVENT_SEND_COMPLETE_RESULT_ERROR_TIMEOUT shall be reported as `event_send_complete`]
AzureIoTClient 34:51d158b409d2 147 // Codes_SRS_DEVICE_09_063: [If `ev_send_comp_result` is MESSENGER_EVENT_SEND_COMPLETE_RESULT_MESSENGER_DESTROYED, D2C_EVENT_SEND_COMPLETE_RESULT_DEVICE_DESTROYED shall be reported as `event_send_complete`]
AzureIoTClient 34:51d158b409d2 148 D2C_EVENT_SEND_RESULT device_send_result = get_d2c_event_send_result_from(ev_send_comp_result);
AzureIoTClient 30:20a85b733111 149
AzureIoTClient 34:51d158b409d2 150 // 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 151 if (send_task->on_event_send_complete_callback != NULL)
AzureIoTClient 34:51d158b409d2 152 {
AzureIoTClient 34:51d158b409d2 153 send_task->on_event_send_complete_callback(iothub_message, device_send_result, send_task->on_event_send_complete_context);
AzureIoTClient 34:51d158b409d2 154 }
AzureIoTClient 30:20a85b733111 155
AzureIoTClient 34:51d158b409d2 156 // Codes_SRS_DEVICE_09_065: [The memory allocated for `send_task` shall be released]
AzureIoTClient 34:51d158b409d2 157 free(send_task);
AzureIoTClient 34:51d158b409d2 158 }
AzureIoTClient 30:20a85b733111 159 }
AzureIoTClient 30:20a85b733111 160
AzureIoTClient 30:20a85b733111 161 static void on_authentication_error_callback(void* context, AUTHENTICATION_ERROR_CODE error_code)
AzureIoTClient 30:20a85b733111 162 {
AzureIoTClient 34:51d158b409d2 163 if (context == NULL)
AzureIoTClient 34:51d158b409d2 164 {
AzureIoTClient 34:51d158b409d2 165 LogError("on_authentication_error_callback was invoked with error %d, but context is NULL", error_code);
AzureIoTClient 34:51d158b409d2 166 }
AzureIoTClient 34:51d158b409d2 167 else
AzureIoTClient 34:51d158b409d2 168 {
AzureIoTClient 34:51d158b409d2 169 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)context;
AzureIoTClient 34:51d158b409d2 170 instance->auth_error_code = error_code;
AzureIoTClient 34:51d158b409d2 171 }
AzureIoTClient 30:20a85b733111 172 }
AzureIoTClient 30:20a85b733111 173
AzureIoTClient 30:20a85b733111 174 static void on_authentication_state_changed_callback(void* context, AUTHENTICATION_STATE previous_state, AUTHENTICATION_STATE new_state)
AzureIoTClient 30:20a85b733111 175 {
AzureIoTClient 34:51d158b409d2 176 if (context == NULL)
AzureIoTClient 34:51d158b409d2 177 {
AzureIoTClient 34:51d158b409d2 178 LogError("on_authentication_state_changed_callback was invoked with new_state %d, but context is NULL", new_state);
AzureIoTClient 34:51d158b409d2 179 }
AzureIoTClient 34:51d158b409d2 180 else if (new_state != previous_state)
AzureIoTClient 34:51d158b409d2 181 {
AzureIoTClient 34:51d158b409d2 182 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)context;
AzureIoTClient 34:51d158b409d2 183 instance->auth_state = new_state;
AzureIoTClient 30:20a85b733111 184
AzureIoTClient 34:51d158b409d2 185 if ((instance->auth_state_last_changed_time = get_time(NULL)) == INDEFINITE_TIME)
AzureIoTClient 34:51d158b409d2 186 {
AzureIoTClient 34:51d158b409d2 187 LogError("Device '%s' failed to set time of last authentication state change (get_time failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 188 }
AzureIoTClient 34:51d158b409d2 189 }
AzureIoTClient 30:20a85b733111 190 }
AzureIoTClient 30:20a85b733111 191
AzureIoTClient 30:20a85b733111 192 static void on_messenger_state_changed_callback(void* context, MESSENGER_STATE previous_state, MESSENGER_STATE new_state)
AzureIoTClient 30:20a85b733111 193 {
AzureIoTClient 34:51d158b409d2 194 if (context == NULL)
AzureIoTClient 34:51d158b409d2 195 {
AzureIoTClient 34:51d158b409d2 196 LogError("on_messenger_state_changed_callback was invoked with new_state %d, but context is NULL", new_state);
AzureIoTClient 34:51d158b409d2 197 }
AzureIoTClient 34:51d158b409d2 198 else if (new_state != previous_state)
AzureIoTClient 34:51d158b409d2 199 {
AzureIoTClient 34:51d158b409d2 200 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)context;
AzureIoTClient 34:51d158b409d2 201 instance->msgr_state = new_state;
AzureIoTClient 30:20a85b733111 202
AzureIoTClient 34:51d158b409d2 203 if ((instance->msgr_state_last_changed_time = get_time(NULL)) == INDEFINITE_TIME)
AzureIoTClient 34:51d158b409d2 204 {
AzureIoTClient 34:51d158b409d2 205 LogError("Device '%s' failed to set time of last messenger state change (get_time failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 206 }
AzureIoTClient 34:51d158b409d2 207 }
AzureIoTClient 30:20a85b733111 208 }
AzureIoTClient 30:20a85b733111 209
AzureIoTClient 30:20a85b733111 210 static DEVICE_MESSAGE_DISPOSITION_INFO* create_device_message_disposition_info_from(MESSENGER_MESSAGE_DISPOSITION_INFO* messenger_disposition_info)
AzureIoTClient 30:20a85b733111 211 {
AzureIoTClient 34:51d158b409d2 212 DEVICE_MESSAGE_DISPOSITION_INFO* device_disposition_info;
AzureIoTClient 30:20a85b733111 213
AzureIoTClient 34:51d158b409d2 214 if ((device_disposition_info = (DEVICE_MESSAGE_DISPOSITION_INFO*)malloc(sizeof(DEVICE_MESSAGE_DISPOSITION_INFO))) == NULL)
AzureIoTClient 34:51d158b409d2 215 {
AzureIoTClient 34:51d158b409d2 216 LogError("Failed creating DEVICE_MESSAGE_DISPOSITION_INFO (malloc failed)");
AzureIoTClient 34:51d158b409d2 217 }
AzureIoTClient 34:51d158b409d2 218 else if (mallocAndStrcpy_s(&device_disposition_info->source, messenger_disposition_info->source) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 219 {
AzureIoTClient 34:51d158b409d2 220 LogError("Failed creating DEVICE_MESSAGE_DISPOSITION_INFO (mallocAndStrcpy_s failed)");
AzureIoTClient 34:51d158b409d2 221 free(device_disposition_info);
AzureIoTClient 34:51d158b409d2 222 device_disposition_info = NULL;
AzureIoTClient 34:51d158b409d2 223 }
AzureIoTClient 34:51d158b409d2 224 else
AzureIoTClient 34:51d158b409d2 225 {
AzureIoTClient 34:51d158b409d2 226 device_disposition_info->message_id = messenger_disposition_info->message_id;
AzureIoTClient 34:51d158b409d2 227 }
AzureIoTClient 30:20a85b733111 228
AzureIoTClient 34:51d158b409d2 229 return device_disposition_info;
AzureIoTClient 30:20a85b733111 230 }
AzureIoTClient 30:20a85b733111 231
AzureIoTClient 30:20a85b733111 232 static void destroy_device_disposition_info(DEVICE_MESSAGE_DISPOSITION_INFO* disposition_info)
AzureIoTClient 30:20a85b733111 233 {
AzureIoTClient 34:51d158b409d2 234 free(disposition_info->source);
AzureIoTClient 34:51d158b409d2 235 free(disposition_info);
AzureIoTClient 30:20a85b733111 236 }
AzureIoTClient 30:20a85b733111 237
AzureIoTClient 30:20a85b733111 238 static MESSENGER_MESSAGE_DISPOSITION_INFO* create_messenger_disposition_info(DEVICE_MESSAGE_DISPOSITION_INFO* device_disposition_info)
AzureIoTClient 30:20a85b733111 239 {
AzureIoTClient 34:51d158b409d2 240 MESSENGER_MESSAGE_DISPOSITION_INFO* messenger_disposition_info;
AzureIoTClient 30:20a85b733111 241
AzureIoTClient 34:51d158b409d2 242 if ((messenger_disposition_info = (MESSENGER_MESSAGE_DISPOSITION_INFO*)malloc(sizeof(MESSENGER_MESSAGE_DISPOSITION_INFO))) == NULL)
AzureIoTClient 34:51d158b409d2 243 {
AzureIoTClient 34:51d158b409d2 244 LogError("Failed creating MESSENGER_MESSAGE_DISPOSITION_INFO (malloc failed)");
AzureIoTClient 34:51d158b409d2 245 }
AzureIoTClient 34:51d158b409d2 246 else if (mallocAndStrcpy_s(&messenger_disposition_info->source, device_disposition_info->source) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 247 {
AzureIoTClient 34:51d158b409d2 248 LogError("Failed creating MESSENGER_MESSAGE_DISPOSITION_INFO (mallocAndStrcpy_s failed)");
AzureIoTClient 34:51d158b409d2 249 free(messenger_disposition_info);
AzureIoTClient 34:51d158b409d2 250 messenger_disposition_info = NULL;
AzureIoTClient 34:51d158b409d2 251 }
AzureIoTClient 34:51d158b409d2 252 else
AzureIoTClient 34:51d158b409d2 253 {
AzureIoTClient 34:51d158b409d2 254 messenger_disposition_info->message_id = device_disposition_info->message_id;
AzureIoTClient 34:51d158b409d2 255 }
AzureIoTClient 30:20a85b733111 256
AzureIoTClient 34:51d158b409d2 257 return messenger_disposition_info;
AzureIoTClient 30:20a85b733111 258 }
AzureIoTClient 30:20a85b733111 259
AzureIoTClient 30:20a85b733111 260 static void destroy_messenger_disposition_info(MESSENGER_MESSAGE_DISPOSITION_INFO* messenger_disposition_info)
AzureIoTClient 30:20a85b733111 261 {
AzureIoTClient 34:51d158b409d2 262 free(messenger_disposition_info->source);
AzureIoTClient 34:51d158b409d2 263 free(messenger_disposition_info);
AzureIoTClient 30:20a85b733111 264 }
AzureIoTClient 30:20a85b733111 265
AzureIoTClient 30:20a85b733111 266 static MESSENGER_DISPOSITION_RESULT get_messenger_message_disposition_result_from(DEVICE_MESSAGE_DISPOSITION_RESULT device_disposition_result)
AzureIoTClient 30:20a85b733111 267 {
AzureIoTClient 34:51d158b409d2 268 MESSENGER_DISPOSITION_RESULT messenger_disposition_result;
AzureIoTClient 30:20a85b733111 269
AzureIoTClient 34:51d158b409d2 270 switch (device_disposition_result)
AzureIoTClient 34:51d158b409d2 271 {
AzureIoTClient 34:51d158b409d2 272 case DEVICE_MESSAGE_DISPOSITION_RESULT_NONE:
AzureIoTClient 34:51d158b409d2 273 messenger_disposition_result = MESSENGER_DISPOSITION_RESULT_NONE;
AzureIoTClient 34:51d158b409d2 274 break;
AzureIoTClient 34:51d158b409d2 275 case DEVICE_MESSAGE_DISPOSITION_RESULT_ACCEPTED:
AzureIoTClient 34:51d158b409d2 276 messenger_disposition_result = MESSENGER_DISPOSITION_RESULT_ACCEPTED;
AzureIoTClient 34:51d158b409d2 277 break;
AzureIoTClient 34:51d158b409d2 278 case DEVICE_MESSAGE_DISPOSITION_RESULT_REJECTED:
AzureIoTClient 34:51d158b409d2 279 messenger_disposition_result = MESSENGER_DISPOSITION_RESULT_REJECTED;
AzureIoTClient 34:51d158b409d2 280 break;
AzureIoTClient 34:51d158b409d2 281 case DEVICE_MESSAGE_DISPOSITION_RESULT_RELEASED:
AzureIoTClient 34:51d158b409d2 282 messenger_disposition_result = MESSENGER_DISPOSITION_RESULT_RELEASED;
AzureIoTClient 34:51d158b409d2 283 break;
AzureIoTClient 34:51d158b409d2 284 default:
AzureIoTClient 34:51d158b409d2 285 LogError("Failed to get the corresponding MESSENGER_DISPOSITION_RESULT (%d is not supported)", device_disposition_result);
AzureIoTClient 34:51d158b409d2 286 messenger_disposition_result = MESSENGER_DISPOSITION_RESULT_RELEASED;
AzureIoTClient 34:51d158b409d2 287 break;
AzureIoTClient 34:51d158b409d2 288 }
AzureIoTClient 30:20a85b733111 289
AzureIoTClient 34:51d158b409d2 290 return messenger_disposition_result;
AzureIoTClient 30:20a85b733111 291 }
AzureIoTClient 30:20a85b733111 292
AzureIoTClient 30:20a85b733111 293 static MESSENGER_DISPOSITION_RESULT on_messenger_message_received_callback(IOTHUB_MESSAGE_HANDLE iothub_message_handle, MESSENGER_MESSAGE_DISPOSITION_INFO* disposition_info, void* context)
AzureIoTClient 30:20a85b733111 294 {
AzureIoTClient 34:51d158b409d2 295 MESSENGER_DISPOSITION_RESULT msgr_disposition_result;
AzureIoTClient 30:20a85b733111 296
AzureIoTClient 34:51d158b409d2 297 // Codes_SRS_DEVICE_09_070: [If `iothub_message_handle` or `context` is NULL, on_messenger_message_received_callback shall return MESSENGER_DISPOSITION_RESULT_RELEASED]
AzureIoTClient 34:51d158b409d2 298 if (iothub_message_handle == NULL || context == NULL)
AzureIoTClient 34:51d158b409d2 299 {
AzureIoTClient 34:51d158b409d2 300 LogError("Failed receiving incoming C2D message (message handle (%p) or context (%p) is NULL)", iothub_message_handle, context);
AzureIoTClient 34:51d158b409d2 301 msgr_disposition_result = MESSENGER_DISPOSITION_RESULT_RELEASED;
AzureIoTClient 34:51d158b409d2 302 }
AzureIoTClient 34:51d158b409d2 303 else
AzureIoTClient 34:51d158b409d2 304 {
AzureIoTClient 34:51d158b409d2 305 DEVICE_INSTANCE* device_instance = (DEVICE_INSTANCE*)context;
AzureIoTClient 30:20a85b733111 306
AzureIoTClient 34:51d158b409d2 307 if (device_instance->on_message_received_callback == NULL)
AzureIoTClient 34:51d158b409d2 308 {
AzureIoTClient 34:51d158b409d2 309 LogError("Device '%s' failed receiving incoming C2D message (callback is NULL)", device_instance->config->device_id);
AzureIoTClient 34:51d158b409d2 310 msgr_disposition_result = MESSENGER_DISPOSITION_RESULT_RELEASED;
AzureIoTClient 34:51d158b409d2 311 }
AzureIoTClient 34:51d158b409d2 312 else
AzureIoTClient 34:51d158b409d2 313 {
AzureIoTClient 34:51d158b409d2 314 DEVICE_MESSAGE_DISPOSITION_INFO* device_message_disposition_info;
AzureIoTClient 30:20a85b733111 315
AzureIoTClient 34:51d158b409d2 316 // 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 317 if ((device_message_disposition_info = create_device_message_disposition_info_from(disposition_info)) == NULL)
AzureIoTClient 34:51d158b409d2 318 {
AzureIoTClient 34:51d158b409d2 319 // Codes_SRS_DEVICE_09_120: [If the DEVICE_MESSAGE_DISPOSITION_INFO instance fails to be created, on_messenger_message_received_callback shall return MESSENGER_DISPOSITION_RESULT_RELEASED]
AzureIoTClient 34:51d158b409d2 320 LogError("Device '%s' failed receiving incoming C2D message (failed creating DEVICE_MESSAGE_DISPOSITION_INFO)", device_instance->config->device_id);
AzureIoTClient 34:51d158b409d2 321 msgr_disposition_result = MESSENGER_DISPOSITION_RESULT_RELEASED;
AzureIoTClient 34:51d158b409d2 322 }
AzureIoTClient 34:51d158b409d2 323 else
AzureIoTClient 34:51d158b409d2 324 {
AzureIoTClient 34:51d158b409d2 325 // Codes_SRS_DEVICE_09_071: [The user callback shall be invoked, passing the context it provided]
AzureIoTClient 34:51d158b409d2 326 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 327
AzureIoTClient 34:51d158b409d2 328 // Codes_SRS_DEVICE_09_072: [If the user callback returns DEVICE_MESSAGE_DISPOSITION_RESULT_ACCEPTED, on_messenger_message_received_callback shall return MESSENGER_DISPOSITION_RESULT_ACCEPTED]
AzureIoTClient 34:51d158b409d2 329 // Codes_SRS_DEVICE_09_073: [If the user callback returns DEVICE_MESSAGE_DISPOSITION_RESULT_REJECTED, on_messenger_message_received_callback shall return MESSENGER_DISPOSITION_RESULT_REJECTED]
AzureIoTClient 34:51d158b409d2 330 // Codes_SRS_DEVICE_09_074: [If the user callback returns DEVICE_MESSAGE_DISPOSITION_RESULT_RELEASED, on_messenger_message_received_callback shall return MESSENGER_DISPOSITION_RESULT_RELEASED]
AzureIoTClient 34:51d158b409d2 331 msgr_disposition_result = get_messenger_message_disposition_result_from(device_disposition_result);
AzureIoTClient 30:20a85b733111 332
AzureIoTClient 34:51d158b409d2 333 // Codes_SRS_DEVICE_09_121: [on_messenger_message_received_callback shall release the memory allocated for DEVICE_MESSAGE_DISPOSITION_INFO]
AzureIoTClient 34:51d158b409d2 334 destroy_device_disposition_info(device_message_disposition_info);
AzureIoTClient 34:51d158b409d2 335 }
AzureIoTClient 34:51d158b409d2 336 }
AzureIoTClient 34:51d158b409d2 337 }
AzureIoTClient 30:20a85b733111 338
AzureIoTClient 34:51d158b409d2 339 return msgr_disposition_result;
AzureIoTClient 30:20a85b733111 340 }
AzureIoTClient 30:20a85b733111 341
AzureIoTClient 30:20a85b733111 342 // Configuration Helpers
AzureIoTClient 30:20a85b733111 343 static void destroy_device_config(DEVICE_CONFIG* config)
AzureIoTClient 30:20a85b733111 344 {
AzureIoTClient 34:51d158b409d2 345 if (config != NULL)
AzureIoTClient 34:51d158b409d2 346 {
AzureIoTClient 34:51d158b409d2 347 free(config->product_info);
AzureIoTClient 34:51d158b409d2 348 free(config->iothub_host_fqdn);
AzureIoTClient 34:51d158b409d2 349 free(config);
AzureIoTClient 34:51d158b409d2 350 }
AzureIoTClient 30:20a85b733111 351 }
AzureIoTClient 30:20a85b733111 352
AzureIoTClient 30:20a85b733111 353 static DEVICE_CONFIG* clone_device_config(DEVICE_CONFIG *config)
AzureIoTClient 30:20a85b733111 354 {
AzureIoTClient 34:51d158b409d2 355 DEVICE_CONFIG* new_config;
AzureIoTClient 30:20a85b733111 356
AzureIoTClient 34:51d158b409d2 357 if ((new_config = (DEVICE_CONFIG*)malloc(sizeof(DEVICE_CONFIG))) == NULL)
AzureIoTClient 34:51d158b409d2 358 {
AzureIoTClient 34:51d158b409d2 359 LogError("Failed copying the DEVICE_CONFIG (malloc failed)");
AzureIoTClient 34:51d158b409d2 360 }
AzureIoTClient 34:51d158b409d2 361 else
AzureIoTClient 34:51d158b409d2 362 {
AzureIoTClient 34:51d158b409d2 363 int result;
AzureIoTClient 34:51d158b409d2 364 memset(new_config, 0, sizeof(DEVICE_CONFIG));
AzureIoTClient 30:20a85b733111 365
AzureIoTClient 34:51d158b409d2 366 if (config->product_info != NULL &&
AzureIoTClient 34:51d158b409d2 367 mallocAndStrcpy_s(&new_config->product_info, config->product_info) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 368 {
AzureIoTClient 34:51d158b409d2 369 LogError("Failed copying the DEVICE_CONFIG (failed copying product_info)");
AzureIoTClient 34:51d158b409d2 370 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 371 }
AzureIoTClient 34:51d158b409d2 372 else if (mallocAndStrcpy_s(&new_config->iothub_host_fqdn, config->iothub_host_fqdn) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 373 {
AzureIoTClient 34:51d158b409d2 374 LogError("Failed copying the DEVICE_CONFIG (failed copying iothub_host_fqdn)");
AzureIoTClient 34:51d158b409d2 375 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 376 }
AzureIoTClient 34:51d158b409d2 377 else
AzureIoTClient 34:51d158b409d2 378 {
AzureIoTClient 34:51d158b409d2 379 new_config->authorization_module = config->authorization_module;
AzureIoTClient 34:51d158b409d2 380 new_config->authentication_mode = config->authentication_mode;
AzureIoTClient 34:51d158b409d2 381 new_config->on_state_changed_callback = config->on_state_changed_callback;
AzureIoTClient 34:51d158b409d2 382 new_config->on_state_changed_context = config->on_state_changed_context;
AzureIoTClient 34:51d158b409d2 383 new_config->device_id = IoTHubClient_Auth_Get_DeviceId(config->authorization_module);
AzureIoTClient 34:51d158b409d2 384 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 385 }
AzureIoTClient 30:20a85b733111 386
AzureIoTClient 34:51d158b409d2 387 if (result != RESULT_OK)
AzureIoTClient 34:51d158b409d2 388 {
AzureIoTClient 34:51d158b409d2 389 destroy_device_config(new_config);
AzureIoTClient 34:51d158b409d2 390 new_config = NULL;
AzureIoTClient 34:51d158b409d2 391 }
AzureIoTClient 34:51d158b409d2 392 }
AzureIoTClient 30:20a85b733111 393
AzureIoTClient 34:51d158b409d2 394 return new_config;
AzureIoTClient 30:20a85b733111 395 }
AzureIoTClient 30:20a85b733111 396
AzureIoTClient 30:20a85b733111 397 static void set_authentication_config(DEVICE_INSTANCE* device_instance, AUTHENTICATION_CONFIG* auth_config)
AzureIoTClient 30:20a85b733111 398 {
AzureIoTClient 34:51d158b409d2 399 DEVICE_CONFIG *device_config = device_instance->config;
AzureIoTClient 30:20a85b733111 400
AzureIoTClient 34:51d158b409d2 401 auth_config->device_id = device_config->device_id;
AzureIoTClient 34:51d158b409d2 402 auth_config->iothub_host_fqdn = device_config->iothub_host_fqdn;
AzureIoTClient 34:51d158b409d2 403 auth_config->on_error_callback = on_authentication_error_callback;
AzureIoTClient 34:51d158b409d2 404 auth_config->on_error_callback_context = device_instance;
AzureIoTClient 34:51d158b409d2 405 auth_config->on_state_changed_callback = on_authentication_state_changed_callback;
AzureIoTClient 34:51d158b409d2 406 auth_config->on_state_changed_callback_context = device_instance;
AzureIoTClient 34:51d158b409d2 407 auth_config->authorization_module = device_config->authorization_module;
AzureIoTClient 30:20a85b733111 408 }
AzureIoTClient 30:20a85b733111 409
AzureIoTClient 30:20a85b733111 410 // Create and Destroy Helpers
AzureIoTClient 30:20a85b733111 411 static void internal_destroy_device(DEVICE_INSTANCE* instance)
AzureIoTClient 30:20a85b733111 412 {
AzureIoTClient 34:51d158b409d2 413 if (instance != NULL)
AzureIoTClient 34:51d158b409d2 414 {
AzureIoTClient 34:51d158b409d2 415 if (instance->messenger_handle != NULL)
AzureIoTClient 34:51d158b409d2 416 {
AzureIoTClient 34:51d158b409d2 417 messenger_destroy(instance->messenger_handle);
AzureIoTClient 34:51d158b409d2 418 }
AzureIoTClient 30:20a85b733111 419
AzureIoTClient 34:51d158b409d2 420 if (instance->authentication_handle != NULL)
AzureIoTClient 34:51d158b409d2 421 {
AzureIoTClient 34:51d158b409d2 422 authentication_destroy(instance->authentication_handle);
AzureIoTClient 34:51d158b409d2 423 }
AzureIoTClient 30:20a85b733111 424
AzureIoTClient 34:51d158b409d2 425 destroy_device_config(instance->config);
AzureIoTClient 34:51d158b409d2 426 free(instance);
AzureIoTClient 34:51d158b409d2 427 }
AzureIoTClient 30:20a85b733111 428 }
AzureIoTClient 30:20a85b733111 429
AzureIoTClient 30:20a85b733111 430 static int create_authentication_instance(DEVICE_INSTANCE *instance)
AzureIoTClient 30:20a85b733111 431 {
AzureIoTClient 34:51d158b409d2 432 int result;
AzureIoTClient 34:51d158b409d2 433 AUTHENTICATION_CONFIG auth_config;
AzureIoTClient 30:20a85b733111 434
AzureIoTClient 34:51d158b409d2 435 set_authentication_config(instance, &auth_config);
AzureIoTClient 30:20a85b733111 436
AzureIoTClient 34:51d158b409d2 437 if ((instance->authentication_handle = authentication_create(&auth_config)) == NULL)
AzureIoTClient 34:51d158b409d2 438 {
AzureIoTClient 34:51d158b409d2 439 LogError("Failed creating the AUTHENTICATION_HANDLE (authentication_create failed)");
AzureIoTClient 34:51d158b409d2 440 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 441 }
AzureIoTClient 34:51d158b409d2 442 else
AzureIoTClient 34:51d158b409d2 443 {
AzureIoTClient 34:51d158b409d2 444 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 445 }
AzureIoTClient 30:20a85b733111 446
AzureIoTClient 34:51d158b409d2 447 return result;
AzureIoTClient 30:20a85b733111 448 }
AzureIoTClient 30:20a85b733111 449
AzureIoTClient 34:51d158b409d2 450 static int create_messenger_instance(DEVICE_INSTANCE* instance, const char* pi)
AzureIoTClient 30:20a85b733111 451 {
AzureIoTClient 34:51d158b409d2 452 int result;
AzureIoTClient 30:20a85b733111 453
AzureIoTClient 34:51d158b409d2 454 MESSENGER_CONFIG messenger_config;
AzureIoTClient 34:51d158b409d2 455 messenger_config.device_id = instance->config->device_id;
AzureIoTClient 34:51d158b409d2 456 messenger_config.iothub_host_fqdn = instance->config->iothub_host_fqdn;
AzureIoTClient 34:51d158b409d2 457 messenger_config.on_state_changed_callback = on_messenger_state_changed_callback;
AzureIoTClient 34:51d158b409d2 458 messenger_config.on_state_changed_context = instance;
AzureIoTClient 30:20a85b733111 459
AzureIoTClient 34:51d158b409d2 460 if ((instance->messenger_handle = messenger_create(&messenger_config, pi)) == NULL)
AzureIoTClient 34:51d158b409d2 461 {
AzureIoTClient 34:51d158b409d2 462 LogError("Failed creating the MESSENGER_HANDLE (messenger_create failed)");
AzureIoTClient 34:51d158b409d2 463 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 464 }
AzureIoTClient 34:51d158b409d2 465 else
AzureIoTClient 34:51d158b409d2 466 {
AzureIoTClient 34:51d158b409d2 467 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 468 }
AzureIoTClient 30:20a85b733111 469
AzureIoTClient 34:51d158b409d2 470 return result;
AzureIoTClient 30:20a85b733111 471 }
AzureIoTClient 30:20a85b733111 472
AzureIoTClient 30:20a85b733111 473 // ---------- Set/Retrieve Options Helpers ----------//
AzureIoTClient 30:20a85b733111 474 static void* device_clone_option(const char* name, const void* value)
AzureIoTClient 30:20a85b733111 475 {
AzureIoTClient 34:51d158b409d2 476 void* result;
AzureIoTClient 30:20a85b733111 477
AzureIoTClient 34:51d158b409d2 478 if (name == NULL || value == NULL)
AzureIoTClient 34:51d158b409d2 479 {
AzureIoTClient 34:51d158b409d2 480 LogError("Failed to clone device option (either name (%p) or value (%p) is NULL)", name, value);
AzureIoTClient 34:51d158b409d2 481 result = NULL;
AzureIoTClient 34:51d158b409d2 482 }
AzureIoTClient 34:51d158b409d2 483 else
AzureIoTClient 34:51d158b409d2 484 {
AzureIoTClient 34:51d158b409d2 485 if (strcmp(DEVICE_OPTION_SAVED_AUTH_OPTIONS, name) == 0 ||
AzureIoTClient 34:51d158b409d2 486 strcmp(DEVICE_OPTION_SAVED_MESSENGER_OPTIONS, name) == 0)
AzureIoTClient 34:51d158b409d2 487 {
AzureIoTClient 34:51d158b409d2 488 if ((result = (void*)OptionHandler_Clone((OPTIONHANDLER_HANDLE)value)) == NULL)
AzureIoTClient 34:51d158b409d2 489 {
AzureIoTClient 34:51d158b409d2 490 LogError("Failed to clone device option (OptionHandler_Clone failed for option %s)", name);
AzureIoTClient 34:51d158b409d2 491 }
AzureIoTClient 34:51d158b409d2 492 }
AzureIoTClient 34:51d158b409d2 493 else
AzureIoTClient 34:51d158b409d2 494 {
AzureIoTClient 34:51d158b409d2 495 LogError("Failed to clone device option (option with name '%s' is not suppported)", name);
AzureIoTClient 34:51d158b409d2 496 result = NULL;
AzureIoTClient 34:51d158b409d2 497 }
AzureIoTClient 34:51d158b409d2 498 }
AzureIoTClient 30:20a85b733111 499
AzureIoTClient 34:51d158b409d2 500 return result;
AzureIoTClient 30:20a85b733111 501 }
AzureIoTClient 30:20a85b733111 502
AzureIoTClient 30:20a85b733111 503 static void device_destroy_option(const char* name, const void* value)
AzureIoTClient 30:20a85b733111 504 {
AzureIoTClient 34:51d158b409d2 505 if (name == NULL || value == NULL)
AzureIoTClient 34:51d158b409d2 506 {
AzureIoTClient 34:51d158b409d2 507 LogError("Failed to destroy device option (either name (%p) or value (%p) is NULL)", name, value);
AzureIoTClient 34:51d158b409d2 508 }
AzureIoTClient 34:51d158b409d2 509 else
AzureIoTClient 34:51d158b409d2 510 {
AzureIoTClient 34:51d158b409d2 511 if (strcmp(name, DEVICE_OPTION_SAVED_AUTH_OPTIONS) == 0 ||
AzureIoTClient 34:51d158b409d2 512 strcmp(name, DEVICE_OPTION_SAVED_MESSENGER_OPTIONS) == 0)
AzureIoTClient 34:51d158b409d2 513 {
AzureIoTClient 34:51d158b409d2 514 OptionHandler_Destroy((OPTIONHANDLER_HANDLE)value);
AzureIoTClient 34:51d158b409d2 515 }
AzureIoTClient 34:51d158b409d2 516 else
AzureIoTClient 34:51d158b409d2 517 {
AzureIoTClient 34:51d158b409d2 518 LogError("Failed to clone device option (option with name '%s' is not suppported)", name);
AzureIoTClient 34:51d158b409d2 519 }
AzureIoTClient 34:51d158b409d2 520 }
AzureIoTClient 30:20a85b733111 521 }
AzureIoTClient 30:20a85b733111 522
AzureIoTClient 30:20a85b733111 523 // Public APIs:
AzureIoTClient 30:20a85b733111 524 DEVICE_HANDLE device_create(DEVICE_CONFIG *config)
AzureIoTClient 30:20a85b733111 525 {
AzureIoTClient 34:51d158b409d2 526 DEVICE_INSTANCE *instance;
AzureIoTClient 30:20a85b733111 527
AzureIoTClient 34:51d158b409d2 528 // 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 529 if (config == NULL)
AzureIoTClient 34:51d158b409d2 530 {
AzureIoTClient 34:51d158b409d2 531 LogError("Failed creating the device instance (config is NULL)");
AzureIoTClient 34:51d158b409d2 532 instance = NULL;
AzureIoTClient 34:51d158b409d2 533 }
AzureIoTClient 34:51d158b409d2 534 else if (config->iothub_host_fqdn == NULL)
AzureIoTClient 34:51d158b409d2 535 {
AzureIoTClient 34:51d158b409d2 536 LogError("Failed creating the device instance (config->iothub_host_fqdn is NULL)");
AzureIoTClient 34:51d158b409d2 537 instance = NULL;
AzureIoTClient 34:51d158b409d2 538 }
AzureIoTClient 34:51d158b409d2 539 else if (config->on_state_changed_callback == NULL)
AzureIoTClient 34:51d158b409d2 540 {
AzureIoTClient 34:51d158b409d2 541 LogError("Failed creating the device instance (config->on_state_changed_callback is NULL)");
AzureIoTClient 34:51d158b409d2 542 instance = NULL;
AzureIoTClient 34:51d158b409d2 543 }
AzureIoTClient 34:51d158b409d2 544 else if (config->authorization_module == NULL)
AzureIoTClient 34:51d158b409d2 545 {
AzureIoTClient 34:51d158b409d2 546 LogError("Failed creating the device instance (config->authorization_module is NULL)");
AzureIoTClient 34:51d158b409d2 547 instance = NULL;
AzureIoTClient 34:51d158b409d2 548 }
AzureIoTClient 34:51d158b409d2 549 // Codes_SRS_DEVICE_09_002: [device_create shall allocate memory for the device instance structure]
AzureIoTClient 34:51d158b409d2 550 else if ((instance = (DEVICE_INSTANCE*)malloc(sizeof(DEVICE_INSTANCE))) == NULL)
AzureIoTClient 34:51d158b409d2 551 {
AzureIoTClient 34:51d158b409d2 552 // Codes_SRS_DEVICE_09_003: [If malloc fails, device_create shall fail and return NULL]
AzureIoTClient 34:51d158b409d2 553 LogError("Failed creating the device instance (malloc failed)");
AzureIoTClient 34:51d158b409d2 554 }
AzureIoTClient 34:51d158b409d2 555 else
AzureIoTClient 34:51d158b409d2 556 {
AzureIoTClient 34:51d158b409d2 557 int result;
AzureIoTClient 30:20a85b733111 558
AzureIoTClient 34:51d158b409d2 559 memset(instance, 0, sizeof(DEVICE_INSTANCE));
AzureIoTClient 30:20a85b733111 560
AzureIoTClient 34:51d158b409d2 561 // Codes_SRS_DEVICE_09_004: [All `config` parameters shall be saved into `instance`]
AzureIoTClient 34:51d158b409d2 562 if ((instance->config = clone_device_config(config)) == NULL)
AzureIoTClient 34:51d158b409d2 563 {
AzureIoTClient 34:51d158b409d2 564 // 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 565 LogError("Failed creating the device instance for device '%s' (failed copying the configuration)", config->device_id);
AzureIoTClient 34:51d158b409d2 566 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 567 }
AzureIoTClient 34:51d158b409d2 568 // 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 569 else if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS &&
AzureIoTClient 34:51d158b409d2 570 create_authentication_instance(instance) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 571 {
AzureIoTClient 34:51d158b409d2 572 // Codes_SRS_DEVICE_09_007: [If the AUTHENTICATION_HANDLE fails to be created, device_create shall fail and return NULL]
AzureIoTClient 34:51d158b409d2 573 LogError("Failed creating the device instance for device '%s' (failed creating the authentication instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 574 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 575 }
AzureIoTClient 34:51d158b409d2 576 // Codes_SRS_DEVICE_09_008: [`instance->messenger_handle` shall be set using messenger_create()]
AzureIoTClient 34:51d158b409d2 577 else if (create_messenger_instance(instance, config->product_info) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 578 {
AzureIoTClient 34:51d158b409d2 579 // Codes_SRS_DEVICE_09_009: [If the MESSENGER_HANDLE fails to be created, device_create shall fail and return NULL]
AzureIoTClient 34:51d158b409d2 580 LogError("Failed creating the device instance for device '%s' (failed creating the messenger instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 581 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 582 }
AzureIoTClient 34:51d158b409d2 583 else
AzureIoTClient 34:51d158b409d2 584 {
AzureIoTClient 34:51d158b409d2 585 instance->auth_state = AUTHENTICATION_STATE_STOPPED;
AzureIoTClient 34:51d158b409d2 586 instance->msgr_state = MESSENGER_STATE_STOPPED;
AzureIoTClient 34:51d158b409d2 587 instance->state = DEVICE_STATE_STOPPED;
AzureIoTClient 34:51d158b409d2 588 instance->auth_state_last_changed_time = INDEFINITE_TIME;
AzureIoTClient 34:51d158b409d2 589 instance->auth_state_change_timeout_secs = DEFAULT_AUTH_STATE_CHANGED_TIMEOUT_SECS;
AzureIoTClient 34:51d158b409d2 590 instance->msgr_state_last_changed_time = INDEFINITE_TIME;
AzureIoTClient 34:51d158b409d2 591 instance->msgr_state_change_timeout_secs = DEFAULT_MSGR_STATE_CHANGED_TIMEOUT_SECS;
AzureIoTClient 30:20a85b733111 592
AzureIoTClient 34:51d158b409d2 593 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 594 }
AzureIoTClient 30:20a85b733111 595
AzureIoTClient 34:51d158b409d2 596 if (result != RESULT_OK)
AzureIoTClient 34:51d158b409d2 597 {
AzureIoTClient 34:51d158b409d2 598 // Codes_SRS_DEVICE_09_010: [If device_create fails it shall release all memory it has allocated]
AzureIoTClient 34:51d158b409d2 599 internal_destroy_device(instance);
AzureIoTClient 34:51d158b409d2 600 instance = NULL;
AzureIoTClient 34:51d158b409d2 601 }
AzureIoTClient 34:51d158b409d2 602 }
AzureIoTClient 30:20a85b733111 603
AzureIoTClient 34:51d158b409d2 604 // Codes_SRS_DEVICE_09_011: [If device_create succeeds it shall return a handle to its `instance` structure]
AzureIoTClient 34:51d158b409d2 605 return (DEVICE_HANDLE)instance;
AzureIoTClient 30:20a85b733111 606 }
AzureIoTClient 30:20a85b733111 607
AzureIoTClient 30:20a85b733111 608 int device_start_async(DEVICE_HANDLE handle, SESSION_HANDLE session_handle, CBS_HANDLE cbs_handle)
AzureIoTClient 30:20a85b733111 609 {
AzureIoTClient 34:51d158b409d2 610 int result;
AzureIoTClient 30:20a85b733111 611
AzureIoTClient 34:51d158b409d2 612 // Codes_SRS_DEVICE_09_017: [If `handle` is NULL, device_start_async shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 613 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 614 {
AzureIoTClient 34:51d158b409d2 615 LogError("Failed starting device (handle is NULL)");
AzureIoTClient 34:51d158b409d2 616 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 617 }
AzureIoTClient 34:51d158b409d2 618 else
AzureIoTClient 34:51d158b409d2 619 {
AzureIoTClient 34:51d158b409d2 620 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 621
AzureIoTClient 34:51d158b409d2 622 // 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 623 if (instance->state != DEVICE_STATE_STOPPED)
AzureIoTClient 34:51d158b409d2 624 {
AzureIoTClient 34:51d158b409d2 625 LogError("Failed starting device (device is not stopped)");
AzureIoTClient 34:51d158b409d2 626 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 627 }
AzureIoTClient 34:51d158b409d2 628 // Codes_SRS_DEVICE_09_019: [If `session_handle` is NULL, device_start_async shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 629 else if (session_handle == NULL)
AzureIoTClient 34:51d158b409d2 630 {
AzureIoTClient 34:51d158b409d2 631 LogError("Failed starting device (session_handle is NULL)");
AzureIoTClient 34:51d158b409d2 632 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 633 }
AzureIoTClient 34:51d158b409d2 634 // 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 635 else if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS && cbs_handle == NULL)
AzureIoTClient 34:51d158b409d2 636 {
AzureIoTClient 34:51d158b409d2 637 LogError("Failed starting device (device using CBS authentication, but cbs_handle is NULL)");
AzureIoTClient 34:51d158b409d2 638 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 639 }
AzureIoTClient 34:51d158b409d2 640 else
AzureIoTClient 34:51d158b409d2 641 {
AzureIoTClient 34:51d158b409d2 642 // Codes_SRS_DEVICE_09_021: [`session_handle` and `cbs_handle` shall be saved into the `instance`]
AzureIoTClient 34:51d158b409d2 643 instance->session_handle = session_handle;
AzureIoTClient 34:51d158b409d2 644 instance->cbs_handle = cbs_handle;
AzureIoTClient 30:20a85b733111 645
AzureIoTClient 34:51d158b409d2 646 // Codes_SRS_DEVICE_09_022: [The device state shall be updated to DEVICE_STATE_STARTING, and state changed callback invoked]
AzureIoTClient 34:51d158b409d2 647 update_state(instance, DEVICE_STATE_STARTING);
AzureIoTClient 30:20a85b733111 648
AzureIoTClient 34:51d158b409d2 649 // Codes_SRS_DEVICE_09_023: [If no failures occur, device_start_async shall return 0]
AzureIoTClient 34:51d158b409d2 650 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 651 }
AzureIoTClient 34:51d158b409d2 652 }
AzureIoTClient 30:20a85b733111 653
AzureIoTClient 34:51d158b409d2 654 return result;
AzureIoTClient 30:20a85b733111 655 }
AzureIoTClient 30:20a85b733111 656
AzureIoTClient 30:20a85b733111 657 // @brief
AzureIoTClient 30:20a85b733111 658 // stops a device instance (stops messenger and authentication) synchronously.
AzureIoTClient 30:20a85b733111 659 // @returns
AzureIoTClient 30:20a85b733111 660 // 0 if the function succeeds, non-zero otherwise.
AzureIoTClient 30:20a85b733111 661 int device_stop(DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 662 {
AzureIoTClient 34:51d158b409d2 663 int result;
AzureIoTClient 30:20a85b733111 664
AzureIoTClient 34:51d158b409d2 665 // Codes_SRS_DEVICE_09_024: [If `handle` is NULL, device_stop shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 666 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 667 {
AzureIoTClient 34:51d158b409d2 668 LogError("Failed stopping device (handle is NULL)");
AzureIoTClient 34:51d158b409d2 669 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 670 }
AzureIoTClient 34:51d158b409d2 671 else
AzureIoTClient 34:51d158b409d2 672 {
AzureIoTClient 34:51d158b409d2 673 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 674
AzureIoTClient 34:51d158b409d2 675 // 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 676 if (instance->state == DEVICE_STATE_STOPPED || instance->state == DEVICE_STATE_STOPPING)
AzureIoTClient 34:51d158b409d2 677 {
AzureIoTClient 34:51d158b409d2 678 LogError("Failed stopping device '%s' (device is already stopped or stopping)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 679 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 680 }
AzureIoTClient 34:51d158b409d2 681 else
AzureIoTClient 34:51d158b409d2 682 {
AzureIoTClient 34:51d158b409d2 683 // Codes_SRS_DEVICE_09_026: [The device state shall be updated to DEVICE_STATE_STOPPING, and state changed callback invoked]
AzureIoTClient 34:51d158b409d2 684 update_state(instance, DEVICE_STATE_STOPPING);
AzureIoTClient 30:20a85b733111 685
AzureIoTClient 34:51d158b409d2 686 // Codes_SRS_DEVICE_09_027: [If `instance->messenger_handle` state is not MESSENGER_STATE_STOPPED, messenger_stop shall be invoked]
AzureIoTClient 34:51d158b409d2 687 if (instance->msgr_state != MESSENGER_STATE_STOPPED &&
AzureIoTClient 34:51d158b409d2 688 instance->msgr_state != MESSENGER_STATE_STOPPING &&
AzureIoTClient 34:51d158b409d2 689 messenger_stop(instance->messenger_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 690 {
AzureIoTClient 34:51d158b409d2 691 // 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 34:51d158b409d2 692 LogError("Failed stopping device '%s' (messenger_stop failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 693 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 694 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 695 }
AzureIoTClient 34:51d158b409d2 696 // 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 697 else if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS &&
AzureIoTClient 34:51d158b409d2 698 instance->auth_state != AUTHENTICATION_STATE_STOPPED &&
AzureIoTClient 34:51d158b409d2 699 authentication_stop(instance->authentication_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 700 {
AzureIoTClient 34:51d158b409d2 701 // 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 702 LogError("Failed stopping device '%s' (authentication_stop failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 703 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 704 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 705 }
AzureIoTClient 34:51d158b409d2 706 else
AzureIoTClient 34:51d158b409d2 707 {
AzureIoTClient 34:51d158b409d2 708 // Codes_SRS_DEVICE_09_031: [The device state shall be updated to DEVICE_STATE_STOPPED, and state changed callback invoked]
AzureIoTClient 34:51d158b409d2 709 update_state(instance, DEVICE_STATE_STOPPED);
AzureIoTClient 30:20a85b733111 710
AzureIoTClient 34:51d158b409d2 711 // Codes_SRS_DEVICE_09_032: [If no failures occur, device_stop shall return 0]
AzureIoTClient 34:51d158b409d2 712 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 713 }
AzureIoTClient 34:51d158b409d2 714 }
AzureIoTClient 34:51d158b409d2 715 }
AzureIoTClient 30:20a85b733111 716
AzureIoTClient 34:51d158b409d2 717 return result;
AzureIoTClient 30:20a85b733111 718 }
AzureIoTClient 30:20a85b733111 719
AzureIoTClient 30:20a85b733111 720 void device_do_work(DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 721 {
AzureIoTClient 34:51d158b409d2 722 // Codes_SRS_DEVICE_09_033: [If `handle` is NULL, device_do_work shall return]
AzureIoTClient 34:51d158b409d2 723 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 724 {
AzureIoTClient 34:51d158b409d2 725 LogError("Failed to perform device_do_work (handle is NULL)");
AzureIoTClient 34:51d158b409d2 726 }
AzureIoTClient 34:51d158b409d2 727 else
AzureIoTClient 34:51d158b409d2 728 {
AzureIoTClient 34:51d158b409d2 729 // Cranking the state monster:
AzureIoTClient 34:51d158b409d2 730 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 731
AzureIoTClient 34:51d158b409d2 732 if (instance->state == DEVICE_STATE_STARTING)
AzureIoTClient 34:51d158b409d2 733 {
AzureIoTClient 34:51d158b409d2 734 // 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 735 if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS)
AzureIoTClient 34:51d158b409d2 736 {
AzureIoTClient 34:51d158b409d2 737 if (instance->auth_state == AUTHENTICATION_STATE_STOPPED)
AzureIoTClient 34:51d158b409d2 738 {
AzureIoTClient 34:51d158b409d2 739 if (authentication_start(instance->authentication_handle, instance->cbs_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 740 {
AzureIoTClient 34:51d158b409d2 741 // Codes_SRS_DEVICE_09_035: [If authentication_start fails, the device state shall be updated to DEVICE_STATE_ERROR_AUTH]
AzureIoTClient 34:51d158b409d2 742 LogError("Device '%s' failed to be authenticated (authentication_start failed)", instance->config->device_id);
AzureIoTClient 30:20a85b733111 743
AzureIoTClient 34:51d158b409d2 744 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 745 }
AzureIoTClient 34:51d158b409d2 746 }
AzureIoTClient 34:51d158b409d2 747 // 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 748 else if (instance->auth_state == AUTHENTICATION_STATE_STARTING)
AzureIoTClient 34:51d158b409d2 749 {
AzureIoTClient 34:51d158b409d2 750 int is_timed_out;
AzureIoTClient 34:51d158b409d2 751 if (is_timeout_reached(instance->auth_state_last_changed_time, instance->auth_state_change_timeout_secs, &is_timed_out) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 752 {
AzureIoTClient 34:51d158b409d2 753 LogError("Device '%s' failed verifying the timeout for authentication start (is_timeout_reached failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 754 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 755 }
AzureIoTClient 34:51d158b409d2 756 // 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 757 else if (is_timed_out == 1)
AzureIoTClient 34:51d158b409d2 758 {
AzureIoTClient 34:51d158b409d2 759 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 760
AzureIoTClient 34:51d158b409d2 761 update_state(instance, DEVICE_STATE_ERROR_AUTH_TIMEOUT);
AzureIoTClient 34:51d158b409d2 762 }
AzureIoTClient 34:51d158b409d2 763 }
AzureIoTClient 34:51d158b409d2 764 else if (instance->auth_state == AUTHENTICATION_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 765 {
AzureIoTClient 34:51d158b409d2 766 // 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 767 if (instance->auth_error_code == AUTHENTICATION_ERROR_AUTH_FAILED)
AzureIoTClient 34:51d158b409d2 768 {
AzureIoTClient 34:51d158b409d2 769 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 770 }
AzureIoTClient 34:51d158b409d2 771 // 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 772 else // DEVICE_STATE_ERROR_TIMEOUT
AzureIoTClient 34:51d158b409d2 773 {
AzureIoTClient 34:51d158b409d2 774 update_state(instance, DEVICE_STATE_ERROR_AUTH_TIMEOUT);
AzureIoTClient 34:51d158b409d2 775 }
AzureIoTClient 34:51d158b409d2 776 }
AzureIoTClient 34:51d158b409d2 777 // There is no AUTHENTICATION_STATE_STOPPING
AzureIoTClient 34:51d158b409d2 778 }
AzureIoTClient 30:20a85b733111 779
AzureIoTClient 34:51d158b409d2 780 // Codes_SRS_DEVICE_09_040: [Messenger shall not be started if using CBS authentication and authentication start has not completed yet]
AzureIoTClient 34:51d158b409d2 781 if (instance->config->authentication_mode == DEVICE_AUTH_MODE_X509 || instance->auth_state == AUTHENTICATION_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 782 {
AzureIoTClient 34:51d158b409d2 783 // Codes_SRS_DEVICE_09_041: [If messenger state is MESSENGER_STATE_STOPPED, messenger_start shall be invoked]
AzureIoTClient 34:51d158b409d2 784 if (instance->msgr_state == MESSENGER_STATE_STOPPED)
AzureIoTClient 34:51d158b409d2 785 {
AzureIoTClient 34:51d158b409d2 786 // Codes_SRS_DEVICE_09_042: [If messenger_start fails, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 34:51d158b409d2 787 if (messenger_start(instance->messenger_handle, instance->session_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 788 {
AzureIoTClient 34:51d158b409d2 789 LogError("Device '%s' messenger failed to be started (messenger_start failed)", instance->config->device_id);
AzureIoTClient 30:20a85b733111 790
AzureIoTClient 34:51d158b409d2 791 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 792 }
AzureIoTClient 34:51d158b409d2 793 }
AzureIoTClient 34:51d158b409d2 794 // Codes_SRS_DEVICE_09_043: [If messenger state is MESSENGER_STATE_STARTING, the device shall track the time since last event change and timeout if needed]
AzureIoTClient 34:51d158b409d2 795 else if (instance->msgr_state == MESSENGER_STATE_STARTING)
AzureIoTClient 34:51d158b409d2 796 {
AzureIoTClient 34:51d158b409d2 797 int is_timed_out;
AzureIoTClient 34:51d158b409d2 798 if (is_timeout_reached(instance->msgr_state_last_changed_time, instance->msgr_state_change_timeout_secs, &is_timed_out) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 799 {
AzureIoTClient 34:51d158b409d2 800 LogError("Device '%s' failed verifying the timeout for messenger start (is_timeout_reached failed)", instance->config->device_id);
AzureIoTClient 30:20a85b733111 801
AzureIoTClient 34:51d158b409d2 802 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 803 }
AzureIoTClient 34:51d158b409d2 804 // Codes_SRS_DEVICE_09_044: [If messenger_start times out, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 34:51d158b409d2 805 else if (is_timed_out == 1)
AzureIoTClient 34:51d158b409d2 806 {
AzureIoTClient 34:51d158b409d2 807 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 808
AzureIoTClient 34:51d158b409d2 809 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 810 }
AzureIoTClient 34:51d158b409d2 811 }
AzureIoTClient 34:51d158b409d2 812 // Codes_SRS_DEVICE_09_045: [If messenger state is MESSENGER_STATE_ERROR, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 34:51d158b409d2 813 else if (instance->msgr_state == MESSENGER_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 814 {
AzureIoTClient 34:51d158b409d2 815 LogError("Device '%s' messenger failed to be started (messenger got into error state)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 816
AzureIoTClient 34:51d158b409d2 817 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 818 }
AzureIoTClient 34:51d158b409d2 819 // Codes_SRS_DEVICE_09_046: [If messenger state is MESSENGER_STATE_STARTED, the device state shall be updated to DEVICE_STATE_STARTED]
AzureIoTClient 34:51d158b409d2 820 else if (instance->msgr_state == MESSENGER_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 821 {
AzureIoTClient 34:51d158b409d2 822 update_state(instance, DEVICE_STATE_STARTED);
AzureIoTClient 34:51d158b409d2 823 }
AzureIoTClient 34:51d158b409d2 824 }
AzureIoTClient 34:51d158b409d2 825 }
AzureIoTClient 34:51d158b409d2 826 else if (instance->state == DEVICE_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 827 {
AzureIoTClient 34:51d158b409d2 828 // 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 829 if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS &&
AzureIoTClient 34:51d158b409d2 830 instance->auth_state != AUTHENTICATION_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 831 {
AzureIoTClient 34:51d158b409d2 832 LogError("Device '%s' is started but authentication reported unexpected state %d", instance->config->device_id, instance->auth_state);
AzureIoTClient 30:20a85b733111 833
AzureIoTClient 34:51d158b409d2 834 if (instance->auth_state != AUTHENTICATION_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 835 {
AzureIoTClient 34:51d158b409d2 836 if (instance->auth_error_code == AUTHENTICATION_ERROR_AUTH_FAILED)
AzureIoTClient 34:51d158b409d2 837 {
AzureIoTClient 34:51d158b409d2 838 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 839 }
AzureIoTClient 34:51d158b409d2 840 else // AUTHENTICATION_ERROR_AUTH_TIMEOUT
AzureIoTClient 34:51d158b409d2 841 {
AzureIoTClient 34:51d158b409d2 842 update_state(instance, DEVICE_STATE_ERROR_AUTH_TIMEOUT);
AzureIoTClient 34:51d158b409d2 843 }
AzureIoTClient 34:51d158b409d2 844 }
AzureIoTClient 34:51d158b409d2 845 else
AzureIoTClient 34:51d158b409d2 846 {
AzureIoTClient 34:51d158b409d2 847 update_state(instance, DEVICE_STATE_ERROR_AUTH);
AzureIoTClient 34:51d158b409d2 848 }
AzureIoTClient 34:51d158b409d2 849 }
AzureIoTClient 34:51d158b409d2 850 else
AzureIoTClient 34:51d158b409d2 851 {
AzureIoTClient 34:51d158b409d2 852 // Codes_SRS_DEVICE_09_048: [If messenger state is not MESSENGER_STATE_STARTED, the device state shall be updated to DEVICE_STATE_ERROR_MSG]
AzureIoTClient 34:51d158b409d2 853 if (instance->msgr_state != MESSENGER_STATE_STARTED)
AzureIoTClient 34:51d158b409d2 854 {
AzureIoTClient 34:51d158b409d2 855 LogError("Device '%s' is started but messenger reported unexpected state %d", instance->config->device_id, instance->msgr_state);
AzureIoTClient 34:51d158b409d2 856 update_state(instance, DEVICE_STATE_ERROR_MSG);
AzureIoTClient 34:51d158b409d2 857 }
AzureIoTClient 34:51d158b409d2 858 }
AzureIoTClient 34:51d158b409d2 859 }
AzureIoTClient 30:20a85b733111 860
AzureIoTClient 34:51d158b409d2 861 // Invoking the do_works():
AzureIoTClient 34:51d158b409d2 862 if (instance->config->authentication_mode == DEVICE_AUTH_MODE_CBS)
AzureIoTClient 34:51d158b409d2 863 {
AzureIoTClient 34:51d158b409d2 864 if (instance->auth_state != AUTHENTICATION_STATE_STOPPED && instance->auth_state != AUTHENTICATION_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 865 {
AzureIoTClient 34:51d158b409d2 866 // 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 867 authentication_do_work(instance->authentication_handle);
AzureIoTClient 34:51d158b409d2 868 }
AzureIoTClient 34:51d158b409d2 869 }
AzureIoTClient 30:20a85b733111 870
AzureIoTClient 34:51d158b409d2 871 if (instance->msgr_state != MESSENGER_STATE_STOPPED && instance->msgr_state != MESSENGER_STATE_ERROR)
AzureIoTClient 34:51d158b409d2 872 {
AzureIoTClient 34:51d158b409d2 873 // Codes_SRS_DEVICE_09_050: [If `instance->messenger_handle` state is not STOPPED or ERROR, authentication_do_work shall be invoked]
AzureIoTClient 34:51d158b409d2 874 messenger_do_work(instance->messenger_handle);
AzureIoTClient 34:51d158b409d2 875 }
AzureIoTClient 34:51d158b409d2 876 }
AzureIoTClient 30:20a85b733111 877 }
AzureIoTClient 30:20a85b733111 878
AzureIoTClient 30:20a85b733111 879 void device_destroy(DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 880 {
AzureIoTClient 34:51d158b409d2 881 // Codes_SRS_DEVICE_09_012: [If `handle` is NULL, device_destroy shall return]
AzureIoTClient 34:51d158b409d2 882 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 883 {
AzureIoTClient 34:51d158b409d2 884 LogError("Failed destroying device handle (handle is NULL)");
AzureIoTClient 34:51d158b409d2 885 }
AzureIoTClient 34:51d158b409d2 886 else
AzureIoTClient 34:51d158b409d2 887 {
AzureIoTClient 34:51d158b409d2 888 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 34:51d158b409d2 889 // 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 890 if (instance->state == DEVICE_STATE_STARTED || instance->state == DEVICE_STATE_STARTING)
AzureIoTClient 34:51d158b409d2 891 {
AzureIoTClient 34:51d158b409d2 892 (void)device_stop((DEVICE_HANDLE)instance);
AzureIoTClient 34:51d158b409d2 893 }
AzureIoTClient 30:20a85b733111 894
AzureIoTClient 34:51d158b409d2 895 // Codes_SRS_DEVICE_09_014: [`instance->messenger_handle shall be destroyed using messenger_destroy()`]
AzureIoTClient 34:51d158b409d2 896 // Codes_SRS_DEVICE_09_015: [If created, `instance->authentication_handle` shall be destroyed using authentication_destroy()`]
AzureIoTClient 34:51d158b409d2 897 // Codes_SRS_DEVICE_09_016: [The contents of `instance->config` shall be detroyed and then it shall be freed]
AzureIoTClient 34:51d158b409d2 898 internal_destroy_device((DEVICE_INSTANCE*)handle);
AzureIoTClient 34:51d158b409d2 899 }
AzureIoTClient 30:20a85b733111 900 }
AzureIoTClient 30:20a85b733111 901
AzureIoTClient 30:20a85b733111 902 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 903 {
AzureIoTClient 34:51d158b409d2 904 int result;
AzureIoTClient 30:20a85b733111 905
AzureIoTClient 34:51d158b409d2 906 // Codes_SRS_DEVICE_09_051: [If `handle` are `message` are NULL, device_send_event_async shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 907 if (handle == NULL || message == NULL)
AzureIoTClient 34:51d158b409d2 908 {
AzureIoTClient 34:51d158b409d2 909 LogError("Failed sending event (either handle (%p) or message (%p) are NULL)", handle, message);
AzureIoTClient 34:51d158b409d2 910 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 911 }
AzureIoTClient 34:51d158b409d2 912 else
AzureIoTClient 34:51d158b409d2 913 {
AzureIoTClient 34:51d158b409d2 914 DEVICE_SEND_EVENT_TASK* send_task;
AzureIoTClient 30:20a85b733111 915
AzureIoTClient 34:51d158b409d2 916 // Codes_SRS_DEVICE_09_052: [A structure (`send_task`) shall be created to track the send state of the message]
AzureIoTClient 34:51d158b409d2 917 if ((send_task = (DEVICE_SEND_EVENT_TASK*)malloc(sizeof(DEVICE_SEND_EVENT_TASK))) == NULL)
AzureIoTClient 34:51d158b409d2 918 {
AzureIoTClient 34:51d158b409d2 919 // 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 920 LogError("Failed sending event (failed creating task to send event)");
AzureIoTClient 34:51d158b409d2 921 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 922 }
AzureIoTClient 34:51d158b409d2 923 else
AzureIoTClient 34:51d158b409d2 924 {
AzureIoTClient 34:51d158b409d2 925 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 926
AzureIoTClient 34:51d158b409d2 927 // Codes_SRS_DEVICE_09_054: [`send_task` shall contain the user callback and the context provided]
AzureIoTClient 34:51d158b409d2 928 memset(send_task, 0, sizeof(DEVICE_SEND_EVENT_TASK));
AzureIoTClient 34:51d158b409d2 929 send_task->on_event_send_complete_callback = on_device_d2c_event_send_complete_callback;
AzureIoTClient 34:51d158b409d2 930 send_task->on_event_send_complete_context = context;
AzureIoTClient 34:51d158b409d2 931
AzureIoTClient 34:51d158b409d2 932 // Codes_SRS_DEVICE_09_055: [The message shall be sent using messenger_send_async, passing `on_event_send_complete_messenger_callback` and `send_task`]
AzureIoTClient 34:51d158b409d2 933 if (messenger_send_async(instance->messenger_handle, message, on_event_send_complete_messenger_callback, (void*)send_task) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 934 {
AzureIoTClient 34:51d158b409d2 935 // Codes_SRS_DEVICE_09_056: [If messenger_send_async fails, device_send_event_async shall return a non-zero value]
AzureIoTClient 34:51d158b409d2 936 LogError("Failed sending event (messenger_send_async failed)");
AzureIoTClient 34:51d158b409d2 937 // Codes_SRS_DEVICE_09_057: [If any failures occur, device_send_event_async shall release all memory it has allocated]
AzureIoTClient 34:51d158b409d2 938 free(send_task);
AzureIoTClient 34:51d158b409d2 939 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 940 }
AzureIoTClient 34:51d158b409d2 941 else
AzureIoTClient 34:51d158b409d2 942 {
AzureIoTClient 34:51d158b409d2 943 // Codes_SRS_DEVICE_09_058: [If no failures occur, device_send_event_async shall return 0]
AzureIoTClient 34:51d158b409d2 944 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 945 }
AzureIoTClient 34:51d158b409d2 946 }
AzureIoTClient 34:51d158b409d2 947 }
AzureIoTClient 30:20a85b733111 948
AzureIoTClient 34:51d158b409d2 949 return result;
AzureIoTClient 30:20a85b733111 950 }
AzureIoTClient 30:20a85b733111 951
AzureIoTClient 30:20a85b733111 952 int device_get_send_status(DEVICE_HANDLE handle, DEVICE_SEND_STATUS *send_status)
AzureIoTClient 30:20a85b733111 953 {
AzureIoTClient 34:51d158b409d2 954 int result;
AzureIoTClient 30:20a85b733111 955
AzureIoTClient 30:20a85b733111 956
AzureIoTClient 34:51d158b409d2 957 // 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 958 if (handle == NULL || send_status == NULL)
AzureIoTClient 34:51d158b409d2 959 {
AzureIoTClient 34:51d158b409d2 960 LogError("Failed getting the device messenger send status (NULL parameter received; handle=%p, send_status=%p)", handle, send_status);
AzureIoTClient 34:51d158b409d2 961 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 962 }
AzureIoTClient 34:51d158b409d2 963 else
AzureIoTClient 34:51d158b409d2 964 {
AzureIoTClient 34:51d158b409d2 965 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 34:51d158b409d2 966 MESSENGER_SEND_STATUS messenger_send_status;
AzureIoTClient 34:51d158b409d2 967
AzureIoTClient 34:51d158b409d2 968 // Codes_SRS_DEVICE_09_106: [The status of `instance->messenger_handle` shall be obtained using messenger_get_send_status]
AzureIoTClient 34:51d158b409d2 969 if (messenger_get_send_status(instance->messenger_handle, &messenger_send_status) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 970 {
AzureIoTClient 34:51d158b409d2 971 // Codes_SRS_DEVICE_09_107: [If messenger_get_send_status fails, device_get_send_status shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 972 LogError("Failed getting the device messenger send status (messenger_get_send_status failed)");
AzureIoTClient 34:51d158b409d2 973 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 974 }
AzureIoTClient 34:51d158b409d2 975 else
AzureIoTClient 34:51d158b409d2 976 {
AzureIoTClient 34:51d158b409d2 977 // Codes_SRS_DEVICE_09_108: [If messenger_get_send_status returns MESSENGER_SEND_STATUS_IDLE, device_get_send_status return status DEVICE_SEND_STATUS_IDLE]
AzureIoTClient 34:51d158b409d2 978 if (messenger_send_status == MESSENGER_SEND_STATUS_IDLE)
AzureIoTClient 34:51d158b409d2 979 {
AzureIoTClient 34:51d158b409d2 980 *send_status = DEVICE_SEND_STATUS_IDLE;
AzureIoTClient 34:51d158b409d2 981 }
AzureIoTClient 34:51d158b409d2 982 // Codes_SRS_DEVICE_09_109: [If messenger_get_send_status returns MESSENGER_SEND_STATUS_BUSY, device_get_send_status return status DEVICE_SEND_STATUS_BUSY]
AzureIoTClient 34:51d158b409d2 983 else // i.e., messenger_send_status == MESSENGER_SEND_STATUS_BUSY
AzureIoTClient 34:51d158b409d2 984 {
AzureIoTClient 34:51d158b409d2 985 *send_status = DEVICE_SEND_STATUS_BUSY;
AzureIoTClient 34:51d158b409d2 986 }
AzureIoTClient 30:20a85b733111 987
AzureIoTClient 34:51d158b409d2 988 // Codes_SRS_DEVICE_09_110: [If device_get_send_status succeeds, it shall return zero as result]
AzureIoTClient 34:51d158b409d2 989 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 990 }
AzureIoTClient 34:51d158b409d2 991 }
AzureIoTClient 30:20a85b733111 992
AzureIoTClient 34:51d158b409d2 993 return result;
AzureIoTClient 30:20a85b733111 994 }
AzureIoTClient 30:20a85b733111 995
AzureIoTClient 30:20a85b733111 996 int device_subscribe_message(DEVICE_HANDLE handle, ON_DEVICE_C2D_MESSAGE_RECEIVED on_message_received_callback, void* context)
AzureIoTClient 30:20a85b733111 997 {
AzureIoTClient 34:51d158b409d2 998 int result;
AzureIoTClient 30:20a85b733111 999
AzureIoTClient 34:51d158b409d2 1000 // 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 1001 if (handle == NULL || on_message_received_callback == NULL || context == NULL)
AzureIoTClient 34:51d158b409d2 1002 {
AzureIoTClient 34:51d158b409d2 1003 LogError("Failed subscribing to C2D messages (either handle (%p), on_message_received_callback (%p) or context (%p) is NULL)",
AzureIoTClient 34:51d158b409d2 1004 handle, on_message_received_callback, context);
AzureIoTClient 34:51d158b409d2 1005 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1006 }
AzureIoTClient 34:51d158b409d2 1007 else
AzureIoTClient 34:51d158b409d2 1008 {
AzureIoTClient 34:51d158b409d2 1009 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1010
AzureIoTClient 34:51d158b409d2 1011 // Codes_SRS_DEVICE_09_067: [messenger_subscribe_for_messages shall be invoked passing `on_messenger_message_received_callback` and the user callback and context]
AzureIoTClient 34:51d158b409d2 1012 if (messenger_subscribe_for_messages(instance->messenger_handle, on_messenger_message_received_callback, handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1013 {
AzureIoTClient 34:51d158b409d2 1014 // Codes_SRS_DEVICE_09_068: [If messenger_subscribe_for_messages fails, device_subscribe_message shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1015 LogError("Failed subscribing to C2D messages (messenger_subscribe_for_messages failed)");
AzureIoTClient 34:51d158b409d2 1016 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1017 }
AzureIoTClient 34:51d158b409d2 1018 else
AzureIoTClient 34:51d158b409d2 1019 {
AzureIoTClient 34:51d158b409d2 1020 instance->on_message_received_callback = on_message_received_callback;
AzureIoTClient 34:51d158b409d2 1021 instance->on_message_received_context = context;
AzureIoTClient 30:20a85b733111 1022
AzureIoTClient 34:51d158b409d2 1023 // Codes_SRS_DEVICE_09_069: [If no failures occur, device_subscribe_message shall return 0]
AzureIoTClient 34:51d158b409d2 1024 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1025 }
AzureIoTClient 34:51d158b409d2 1026 }
AzureIoTClient 30:20a85b733111 1027
AzureIoTClient 34:51d158b409d2 1028 return result;
AzureIoTClient 30:20a85b733111 1029 }
AzureIoTClient 30:20a85b733111 1030
AzureIoTClient 30:20a85b733111 1031 int device_unsubscribe_message(DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 1032 {
AzureIoTClient 34:51d158b409d2 1033 int result;
AzureIoTClient 30:20a85b733111 1034
AzureIoTClient 34:51d158b409d2 1035 // Codes_SRS_DEVICE_09_076: [If `handle` is NULL, device_unsubscribe_message shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1036 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 1037 {
AzureIoTClient 34:51d158b409d2 1038 LogError("Failed unsubscribing to C2D messages (handle is NULL)");
AzureIoTClient 34:51d158b409d2 1039 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1040 }
AzureIoTClient 34:51d158b409d2 1041 else
AzureIoTClient 34:51d158b409d2 1042 {
AzureIoTClient 34:51d158b409d2 1043 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1044
AzureIoTClient 34:51d158b409d2 1045 // Codes_SRS_DEVICE_09_077: [messenger_unsubscribe_for_messages shall be invoked passing `instance->messenger_handle`]
AzureIoTClient 34:51d158b409d2 1046 if (messenger_unsubscribe_for_messages(instance->messenger_handle) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1047 {
AzureIoTClient 34:51d158b409d2 1048 // Codes_SRS_DEVICE_09_078: [If messenger_unsubscribe_for_messages fails, device_unsubscribe_message shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1049 LogError("Failed unsubscribing to C2D messages (messenger_unsubscribe_for_messages failed)");
AzureIoTClient 34:51d158b409d2 1050 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1051 }
AzureIoTClient 34:51d158b409d2 1052 else
AzureIoTClient 34:51d158b409d2 1053 {
AzureIoTClient 34:51d158b409d2 1054 // Codes_SRS_DEVICE_09_079: [If no failures occur, device_unsubscribe_message shall return 0]
AzureIoTClient 34:51d158b409d2 1055 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1056 }
AzureIoTClient 34:51d158b409d2 1057 }
AzureIoTClient 34:51d158b409d2 1058 return result;
AzureIoTClient 30:20a85b733111 1059 }
AzureIoTClient 30:20a85b733111 1060
AzureIoTClient 30:20a85b733111 1061 int device_send_message_disposition(DEVICE_HANDLE device_handle, DEVICE_MESSAGE_DISPOSITION_INFO* disposition_info, DEVICE_MESSAGE_DISPOSITION_RESULT disposition_result)
AzureIoTClient 30:20a85b733111 1062 {
AzureIoTClient 34:51d158b409d2 1063 int result;
AzureIoTClient 30:20a85b733111 1064
AzureIoTClient 34:51d158b409d2 1065 // 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 1066 if (device_handle == NULL || disposition_info == NULL)
AzureIoTClient 34:51d158b409d2 1067 {
AzureIoTClient 34:51d158b409d2 1068 LogError("Failed sending message disposition (either device_handle (%p) or disposition_info (%p) are NULL)", device_handle, disposition_info);
AzureIoTClient 34:51d158b409d2 1069 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1070 }
AzureIoTClient 34:51d158b409d2 1071 // Codes_SRS_DEVICE_09_112: [If `disposition_info->source` is NULL, device_send_message_disposition() shall fail and return __FAILURE__]
AzureIoTClient 34:51d158b409d2 1072 else if (disposition_info->source == NULL)
AzureIoTClient 34:51d158b409d2 1073 {
AzureIoTClient 34:51d158b409d2 1074 LogError("Failed sending message disposition (disposition_info->source is NULL)");
AzureIoTClient 34:51d158b409d2 1075 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1076 }
AzureIoTClient 34:51d158b409d2 1077 else
AzureIoTClient 34:51d158b409d2 1078 {
AzureIoTClient 34:51d158b409d2 1079 DEVICE_INSTANCE* device = (DEVICE_INSTANCE*)device_handle;
AzureIoTClient 34:51d158b409d2 1080 MESSENGER_MESSAGE_DISPOSITION_INFO* messenger_disposition_info;
AzureIoTClient 30:20a85b733111 1081
AzureIoTClient 34:51d158b409d2 1082 // Codes_SRS_DEVICE_09_113: [A MESSENGER_MESSAGE_DISPOSITION_INFO instance shall be created with a copy of the `source` and `message_id` contained in `disposition_info`]
AzureIoTClient 34:51d158b409d2 1083 if ((messenger_disposition_info = create_messenger_disposition_info(disposition_info)) == NULL)
AzureIoTClient 34:51d158b409d2 1084 {
AzureIoTClient 34:51d158b409d2 1085 // Codes_SRS_DEVICE_09_114: [If the MESSENGER_MESSAGE_DISPOSITION_INFO fails to be created, device_send_message_disposition() shall fail and return __FAILURE__]
AzureIoTClient 34:51d158b409d2 1086 LogError("Failed sending message disposition (failed to create MESSENGER_MESSAGE_DISPOSITION_INFO)");
AzureIoTClient 34:51d158b409d2 1087 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1088 }
AzureIoTClient 34:51d158b409d2 1089 else
AzureIoTClient 34:51d158b409d2 1090 {
AzureIoTClient 34:51d158b409d2 1091 MESSENGER_DISPOSITION_RESULT messenger_disposition_result = get_messenger_message_disposition_result_from(disposition_result);
AzureIoTClient 30:20a85b733111 1092
AzureIoTClient 34:51d158b409d2 1093 // Codes_SRS_DEVICE_09_115: [`messenger_send_message_disposition()` shall be invoked passing the MESSENGER_MESSAGE_DISPOSITION_INFO instance and the corresponding MESSENGER_DISPOSITION_RESULT]
AzureIoTClient 34:51d158b409d2 1094 if (messenger_send_message_disposition(device->messenger_handle, messenger_disposition_info, messenger_disposition_result) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1095 {
AzureIoTClient 34:51d158b409d2 1096 // Codes_SRS_DEVICE_09_116: [If `messenger_send_message_disposition()` fails, device_send_message_disposition() shall fail and return __FAILURE__]
AzureIoTClient 34:51d158b409d2 1097 LogError("Failed sending message disposition (messenger_send_message_disposition failed)");
AzureIoTClient 34:51d158b409d2 1098 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1099 }
AzureIoTClient 34:51d158b409d2 1100 else
AzureIoTClient 34:51d158b409d2 1101 {
AzureIoTClient 34:51d158b409d2 1102 // Codes_SRS_DEVICE_09_118: [If no failures occurr, device_send_message_disposition() shall return 0]
AzureIoTClient 34:51d158b409d2 1103 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1104 }
AzureIoTClient 30:20a85b733111 1105
AzureIoTClient 34:51d158b409d2 1106 // Codes_SRS_DEVICE_09_117: [device_send_message_disposition() shall destroy the MESSENGER_MESSAGE_DISPOSITION_INFO instance]
AzureIoTClient 34:51d158b409d2 1107 destroy_messenger_disposition_info(messenger_disposition_info);
AzureIoTClient 34:51d158b409d2 1108 }
AzureIoTClient 34:51d158b409d2 1109 }
AzureIoTClient 30:20a85b733111 1110
AzureIoTClient 34:51d158b409d2 1111 return result;
AzureIoTClient 30:20a85b733111 1112 }
AzureIoTClient 30:20a85b733111 1113
AzureIoTClient 30:20a85b733111 1114 int device_set_retry_policy(DEVICE_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY policy, size_t retry_timeout_limit_in_seconds)
AzureIoTClient 30:20a85b733111 1115 {
AzureIoTClient 34:51d158b409d2 1116 (void)retry_timeout_limit_in_seconds;
AzureIoTClient 34:51d158b409d2 1117 (void)policy;
AzureIoTClient 34:51d158b409d2 1118 int result;
AzureIoTClient 30:20a85b733111 1119
AzureIoTClient 34:51d158b409d2 1120 // Codes_SRS_DEVICE_09_080: [If `handle` is NULL, device_set_retry_policy shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1121 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 1122 {
AzureIoTClient 34:51d158b409d2 1123 LogError("Failed setting retry policy (handle is NULL)");
AzureIoTClient 34:51d158b409d2 1124 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1125 }
AzureIoTClient 34:51d158b409d2 1126 else
AzureIoTClient 34:51d158b409d2 1127 {
AzureIoTClient 34:51d158b409d2 1128 // Codes_SRS_DEVICE_09_081: [device_set_retry_policy shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1129 LogError("Failed setting retry policy (functionality not supported)");
AzureIoTClient 34:51d158b409d2 1130 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1131 }
AzureIoTClient 30:20a85b733111 1132
AzureIoTClient 34:51d158b409d2 1133 return result;
AzureIoTClient 30:20a85b733111 1134 }
AzureIoTClient 30:20a85b733111 1135
AzureIoTClient 30:20a85b733111 1136 int device_set_option(DEVICE_HANDLE handle, const char* name, void* value)
AzureIoTClient 30:20a85b733111 1137 {
AzureIoTClient 34:51d158b409d2 1138 int result;
AzureIoTClient 30:20a85b733111 1139
AzureIoTClient 34:51d158b409d2 1140 // 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 1141 if (handle == NULL || name == NULL || value == NULL)
AzureIoTClient 34:51d158b409d2 1142 {
AzureIoTClient 34:51d158b409d2 1143 LogError("failed setting device option (one of the followin are NULL: _handle=%p, name=%p, value=%p)",
AzureIoTClient 34:51d158b409d2 1144 handle, name, value);
AzureIoTClient 34:51d158b409d2 1145 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1146 }
AzureIoTClient 34:51d158b409d2 1147 else
AzureIoTClient 34:51d158b409d2 1148 {
AzureIoTClient 34:51d158b409d2 1149 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1150
AzureIoTClient 34:51d158b409d2 1151 if (strcmp(DEVICE_OPTION_CBS_REQUEST_TIMEOUT_SECS, name) == 0 ||
AzureIoTClient 34:51d158b409d2 1152 strcmp(DEVICE_OPTION_SAS_TOKEN_REFRESH_TIME_SECS, name) == 0 ||
AzureIoTClient 34:51d158b409d2 1153 strcmp(DEVICE_OPTION_SAS_TOKEN_LIFETIME_SECS, name) == 0)
AzureIoTClient 34:51d158b409d2 1154 {
AzureIoTClient 34:51d158b409d2 1155 // 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 1156 if (instance->authentication_handle == NULL)
AzureIoTClient 34:51d158b409d2 1157 {
AzureIoTClient 34:51d158b409d2 1158 LogError("failed setting option for device '%s' (cannot set authentication option '%s'; not using CBS authentication)", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1159 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1160 }
AzureIoTClient 34:51d158b409d2 1161 // Codes_SRS_DEVICE_09_084: [If `name` refers to authentication, it shall be passed along with `value` to authentication_set_option]
AzureIoTClient 34:51d158b409d2 1162 else if(authentication_set_option(instance->authentication_handle, name, value) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1163 {
AzureIoTClient 34:51d158b409d2 1164 // Codes_SRS_DEVICE_09_085: [If authentication_set_option fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1165 LogError("failed setting option for device '%s' (failed setting authentication option '%s')", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1166 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1167 }
AzureIoTClient 34:51d158b409d2 1168 else
AzureIoTClient 34:51d158b409d2 1169 {
AzureIoTClient 34:51d158b409d2 1170 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1171 }
AzureIoTClient 34:51d158b409d2 1172 }
AzureIoTClient 34:51d158b409d2 1173 else if (strcmp(DEVICE_OPTION_EVENT_SEND_TIMEOUT_SECS, name) == 0)
AzureIoTClient 34:51d158b409d2 1174 {
AzureIoTClient 34:51d158b409d2 1175 // Codes_SRS_DEVICE_09_086: [If `name` refers to messenger module, it shall be passed along with `value` to messenger_set_option]
AzureIoTClient 34:51d158b409d2 1176 if (messenger_set_option(instance->messenger_handle, name, value) != RESULT_OK)
AzureIoTClient 34:51d158b409d2 1177 {
AzureIoTClient 34:51d158b409d2 1178 // Codes_SRS_DEVICE_09_087: [If messenger_set_option fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1179 LogError("failed setting option for device '%s' (failed setting messenger option '%s')", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1180 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1181 }
AzureIoTClient 34:51d158b409d2 1182 else
AzureIoTClient 34:51d158b409d2 1183 {
AzureIoTClient 34:51d158b409d2 1184 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1185 }
AzureIoTClient 34:51d158b409d2 1186 }
AzureIoTClient 34:51d158b409d2 1187 else if (strcmp(DEVICE_OPTION_SAVED_AUTH_OPTIONS, name) == 0)
AzureIoTClient 34:51d158b409d2 1188 {
AzureIoTClient 34:51d158b409d2 1189 // 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 1190 if (instance->authentication_handle == NULL)
AzureIoTClient 34:51d158b409d2 1191 {
AzureIoTClient 34:51d158b409d2 1192 LogError("failed setting option for device '%s' (cannot set authentication option '%s'; not using CBS authentication)", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1193 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1194 }
AzureIoTClient 34:51d158b409d2 1195 else if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, instance->authentication_handle) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1196 {
AzureIoTClient 34:51d158b409d2 1197 // Codes_SRS_DEVICE_09_091: [If any call to OptionHandler_FeedOptions fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1198 LogError("failed setting option for device '%s' (OptionHandler_FeedOptions failed for authentication instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1199 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1200 }
AzureIoTClient 34:51d158b409d2 1201 else
AzureIoTClient 34:51d158b409d2 1202 {
AzureIoTClient 34:51d158b409d2 1203 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1204 }
AzureIoTClient 34:51d158b409d2 1205 }
AzureIoTClient 34:51d158b409d2 1206 else if (strcmp(DEVICE_OPTION_SAVED_MESSENGER_OPTIONS, name) == 0)
AzureIoTClient 34:51d158b409d2 1207 {
AzureIoTClient 34:51d158b409d2 1208 // 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 1209 if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, instance->messenger_handle) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1210 {
AzureIoTClient 34:51d158b409d2 1211 // Codes_SRS_DEVICE_09_091: [If any call to OptionHandler_FeedOptions fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1212 LogError("failed setting option for device '%s' (OptionHandler_FeedOptions failed for messenger instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1213 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1214 }
AzureIoTClient 34:51d158b409d2 1215 else
AzureIoTClient 34:51d158b409d2 1216 {
AzureIoTClient 34:51d158b409d2 1217 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1218 }
AzureIoTClient 34:51d158b409d2 1219 }
AzureIoTClient 34:51d158b409d2 1220 else if (strcmp(DEVICE_OPTION_SAVED_OPTIONS, name) == 0)
AzureIoTClient 34:51d158b409d2 1221 {
AzureIoTClient 34:51d158b409d2 1222 // Codes_SRS_DEVICE_09_090: [If `name` is DEVICE_OPTION_SAVED_OPTIONS, `value` shall be fed to `instance` using OptionHandler_FeedOptions]
AzureIoTClient 34:51d158b409d2 1223 if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, handle) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1224 {
AzureIoTClient 34:51d158b409d2 1225 // Codes_SRS_DEVICE_09_091: [If any call to OptionHandler_FeedOptions fails, device_set_option shall return a non-zero result]
AzureIoTClient 34:51d158b409d2 1226 LogError("failed setting option for device '%s' (OptionHandler_FeedOptions failed)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1227 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1228 }
AzureIoTClient 34:51d158b409d2 1229 else
AzureIoTClient 34:51d158b409d2 1230 {
AzureIoTClient 34:51d158b409d2 1231 result = RESULT_OK;
AzureIoTClient 34:51d158b409d2 1232 }
AzureIoTClient 34:51d158b409d2 1233 }
AzureIoTClient 34:51d158b409d2 1234 else
AzureIoTClient 34:51d158b409d2 1235 {
AzureIoTClient 34:51d158b409d2 1236 // Codes_SRS_DEVICE_09_092: [If no failures occur, device_set_option shall return 0]
AzureIoTClient 34:51d158b409d2 1237 LogError("failed setting option for device '%s' (option with name '%s' is not suppported)", instance->config->device_id, name);
AzureIoTClient 34:51d158b409d2 1238 result = __FAILURE__;
AzureIoTClient 34:51d158b409d2 1239 }
AzureIoTClient 34:51d158b409d2 1240 }
AzureIoTClient 30:20a85b733111 1241
AzureIoTClient 34:51d158b409d2 1242 return result;
AzureIoTClient 30:20a85b733111 1243 }
AzureIoTClient 30:20a85b733111 1244
AzureIoTClient 30:20a85b733111 1245 OPTIONHANDLER_HANDLE device_retrieve_options(DEVICE_HANDLE handle)
AzureIoTClient 30:20a85b733111 1246 {
AzureIoTClient 34:51d158b409d2 1247 OPTIONHANDLER_HANDLE result;
AzureIoTClient 30:20a85b733111 1248
AzureIoTClient 34:51d158b409d2 1249 // Codes_SRS_DEVICE_09_093: [If `handle` is NULL, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1250 if (handle == NULL)
AzureIoTClient 34:51d158b409d2 1251 {
AzureIoTClient 34:51d158b409d2 1252 LogError("Failed to retrieve options from device instance (handle is NULL)");
AzureIoTClient 34:51d158b409d2 1253 result = NULL;
AzureIoTClient 34:51d158b409d2 1254 }
AzureIoTClient 34:51d158b409d2 1255 else
AzureIoTClient 34:51d158b409d2 1256 {
AzureIoTClient 34:51d158b409d2 1257 // Codes_SRS_DEVICE_09_094: [A OPTIONHANDLER_HANDLE instance, aka `options` shall be created using OptionHandler_Create]
AzureIoTClient 34:51d158b409d2 1258 OPTIONHANDLER_HANDLE options = OptionHandler_Create(device_clone_option, device_destroy_option, (pfSetOption)device_set_option);
AzureIoTClient 30:20a85b733111 1259
AzureIoTClient 34:51d158b409d2 1260 if (options == NULL)
AzureIoTClient 34:51d158b409d2 1261 {
AzureIoTClient 34:51d158b409d2 1262 // Codes_SRS_DEVICE_09_095: [If OptionHandler_Create fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1263 LogError("Failed to retrieve options from device instance (OptionHandler_Create failed)");
AzureIoTClient 34:51d158b409d2 1264 result = NULL;
AzureIoTClient 34:51d158b409d2 1265 }
AzureIoTClient 34:51d158b409d2 1266 else
AzureIoTClient 34:51d158b409d2 1267 {
AzureIoTClient 34:51d158b409d2 1268 DEVICE_INSTANCE* instance = (DEVICE_INSTANCE*)handle;
AzureIoTClient 30:20a85b733111 1269
AzureIoTClient 34:51d158b409d2 1270 OPTIONHANDLER_HANDLE dependency_options = NULL;
AzureIoTClient 30:20a85b733111 1271
AzureIoTClient 34:51d158b409d2 1272 // Codes_SRS_DEVICE_09_096: [If CBS authentication is used, `instance->authentication_handle` options shall be retrieved using authentication_retrieve_options]
AzureIoTClient 34:51d158b409d2 1273 if (instance->authentication_handle != NULL &&
AzureIoTClient 34:51d158b409d2 1274 (dependency_options = authentication_retrieve_options(instance->authentication_handle)) == NULL)
AzureIoTClient 34:51d158b409d2 1275 {
AzureIoTClient 34:51d158b409d2 1276 // Codes_SRS_DEVICE_09_097: [If authentication_retrieve_options fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1277 LogError("Failed to retrieve options from device '%s' (failed to retrieve options from authentication instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1278 result = NULL;
AzureIoTClient 34:51d158b409d2 1279 }
AzureIoTClient 34:51d158b409d2 1280 // 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 1281 else if (instance->authentication_handle != NULL &&
AzureIoTClient 34:51d158b409d2 1282 OptionHandler_AddOption(options, DEVICE_OPTION_SAVED_AUTH_OPTIONS, (const void*)dependency_options) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1283 {
AzureIoTClient 34:51d158b409d2 1284 // Codes_SRS_DEVICE_09_102: [If any call to OptionHandler_AddOption fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1285 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 1286 result = NULL;
AzureIoTClient 34:51d158b409d2 1287 }
AzureIoTClient 34:51d158b409d2 1288 // Codes_SRS_DEVICE_09_099: [`instance->messenger_handle` options shall be retrieved using messenger_retrieve_options]
AzureIoTClient 34:51d158b409d2 1289 else if ((dependency_options = messenger_retrieve_options(instance->messenger_handle)) == NULL)
AzureIoTClient 34:51d158b409d2 1290 {
AzureIoTClient 34:51d158b409d2 1291 // Codes_SRS_DEVICE_09_100: [If messenger_retrieve_options fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1292 LogError("Failed to retrieve options from device '%s' (failed to retrieve options from messenger instance)", instance->config->device_id);
AzureIoTClient 34:51d158b409d2 1293 result = NULL;
AzureIoTClient 34:51d158b409d2 1294 }
AzureIoTClient 34:51d158b409d2 1295 // 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 1296 else if (OptionHandler_AddOption(options, DEVICE_OPTION_SAVED_MESSENGER_OPTIONS, (const void*)dependency_options) != OPTIONHANDLER_OK)
AzureIoTClient 34:51d158b409d2 1297 {
AzureIoTClient 34:51d158b409d2 1298 // Codes_SRS_DEVICE_09_102: [If any call to OptionHandler_AddOption fails, device_retrieve_options shall return NULL]
AzureIoTClient 34:51d158b409d2 1299 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 1300 result = NULL;
AzureIoTClient 34:51d158b409d2 1301 }
AzureIoTClient 34:51d158b409d2 1302 else
AzureIoTClient 34:51d158b409d2 1303 {
AzureIoTClient 34:51d158b409d2 1304 // Codes_SRS_DEVICE_09_104: [If no failures occur, a handle to `options` shall be return]
AzureIoTClient 34:51d158b409d2 1305 result = options;
AzureIoTClient 34:51d158b409d2 1306 }
AzureIoTClient 30:20a85b733111 1307
AzureIoTClient 34:51d158b409d2 1308 if (result == NULL)
AzureIoTClient 34:51d158b409d2 1309 {
AzureIoTClient 34:51d158b409d2 1310 // Codes_SRS_DEVICE_09_103: [If any failure occurs, any memory allocated by device_retrieve_options shall be destroyed]
AzureIoTClient 34:51d158b409d2 1311 OptionHandler_Destroy(options);
AzureIoTClient 34:51d158b409d2 1312 }
AzureIoTClient 34:51d158b409d2 1313 }
AzureIoTClient 34:51d158b409d2 1314 }
AzureIoTClient 30:20a85b733111 1315
AzureIoTClient 34:51d158b409d2 1316 return result;
AzureIoTClient 30:20a85b733111 1317 }