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:
Fri Mar 10 11:46:55 2017 -0800
Revision:
30:20a85b733111
Child:
34:51d158b409d2
1.1.9

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