1 | // Copyright (c) Microsoft. All rights reserved.
|
---|
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
---|
3 |
|
---|
4 | #include <stdlib.h>
|
---|
5 | #include <stdint.h>
|
---|
6 | #include <string.h>
|
---|
7 | #include <errno.h>
|
---|
8 |
|
---|
9 | #include "azure_c_shared_utility/optimize_size.h"
|
---|
10 | #include "azure_c_shared_utility/gballoc.h"
|
---|
11 | #include "azure_c_shared_utility/string_tokenizer.h"
|
---|
12 | #include "azure_c_shared_utility/doublylinkedlist.h"
|
---|
13 | #include "azure_c_shared_utility/xlogging.h"
|
---|
14 | #include "azure_c_shared_utility/tickcounter.h"
|
---|
15 | #include "azure_c_shared_utility/constbuffer.h"
|
---|
16 | #include "azure_c_shared_utility/platform.h"
|
---|
17 | #include "azure_c_shared_utility/singlylinkedlist.h"
|
---|
18 | #include "azure_c_shared_utility/shared_util_options.h"
|
---|
19 | #include "azure_c_shared_utility/agenttime.h"
|
---|
20 |
|
---|
21 | #include "iothub_client_core_ll.h"
|
---|
22 | #include "iothub_client_options.h"
|
---|
23 | #include "iothub_client_version.h"
|
---|
24 | #include "iothub_transport_ll.h"
|
---|
25 | #include "internal/iothub_client_authorization.h"
|
---|
26 | #include "internal/iothub_client_private.h"
|
---|
27 | #include "internal/iothub_client_diagnostic.h"
|
---|
28 | #include "internal/iothubtransport.h"
|
---|
29 |
|
---|
30 | #ifndef DONT_USE_UPLOADTOBLOB
|
---|
31 | #include "internal/iothub_client_ll_uploadtoblob.h"
|
---|
32 | #endif
|
---|
33 |
|
---|
34 | #ifdef USE_EDGE_MODULES
|
---|
35 | #include "azure_c_shared_utility/envvariable.h"
|
---|
36 | #include "azure_prov_client/iothub_security_factory.h"
|
---|
37 | #include "internal/iothub_client_edge.h"
|
---|
38 | #endif
|
---|
39 |
|
---|
40 | #define LOG_ERROR_RESULT LogError("result = %s", MU_ENUM_TO_STRING(IOTHUB_CLIENT_RESULT, result));
|
---|
41 | #define INDEFINITE_TIME ((time_t)(-1))
|
---|
42 |
|
---|
43 | MU_DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_FILE_UPLOAD_RESULT, IOTHUB_CLIENT_FILE_UPLOAD_RESULT_VALUES);
|
---|
44 | MU_DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUES);
|
---|
45 | MU_DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_RETRY_POLICY, IOTHUB_CLIENT_RETRY_POLICY_VALUES);
|
---|
46 | MU_DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_STATUS, IOTHUB_CLIENT_STATUS_VALUES);
|
---|
47 | MU_DEFINE_ENUM_STRINGS(IOTHUB_IDENTITY_TYPE, IOTHUB_IDENTITY_TYPE_VALUE);
|
---|
48 | MU_DEFINE_ENUM_STRINGS(IOTHUB_PROCESS_ITEM_RESULT, IOTHUB_PROCESS_ITEM_RESULT_VALUE);
|
---|
49 | MU_DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_IOTHUB_METHOD_STATUS, IOTHUB_CLIENT_IOTHUB_METHOD_STATUS_VALUES);
|
---|
50 | MU_DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_CONFIRMATION_RESULT, IOTHUB_CLIENT_CONFIRMATION_RESULT_VALUES);
|
---|
51 | MU_DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_CONNECTION_STATUS, IOTHUB_CLIENT_CONNECTION_STATUS_VALUES);
|
---|
52 | MU_DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_CONNECTION_STATUS_REASON, IOTHUB_CLIENT_CONNECTION_STATUS_REASON_VALUES);
|
---|
53 | MU_DEFINE_ENUM_STRINGS(TRANSPORT_TYPE, TRANSPORT_TYPE_VALUES);
|
---|
54 | MU_DEFINE_ENUM_STRINGS(DEVICE_TWIN_UPDATE_STATE, DEVICE_TWIN_UPDATE_STATE_VALUES);
|
---|
55 | #ifndef DONT_USE_UPLOADTOBLOB
|
---|
56 | MU_DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT_VALUES);
|
---|
57 | #endif // DONT_USE_UPLOADTOBLOB
|
---|
58 |
|
---|
59 | #define CALLBACK_TYPE_VALUES \
|
---|
60 | CALLBACK_TYPE_NONE, \
|
---|
61 | CALLBACK_TYPE_SYNC, \
|
---|
62 | CALLBACK_TYPE_ASYNC
|
---|
63 |
|
---|
64 | MU_DEFINE_ENUM(CALLBACK_TYPE, CALLBACK_TYPE_VALUES)
|
---|
65 | MU_DEFINE_ENUM_STRINGS(CALLBACK_TYPE, CALLBACK_TYPE_VALUES)
|
---|
66 |
|
---|
67 | typedef struct IOTHUB_METHOD_CALLBACK_DATA_TAG
|
---|
68 | {
|
---|
69 | CALLBACK_TYPE type;
|
---|
70 | IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC callbackSync;
|
---|
71 | IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK callbackAsync;
|
---|
72 | void* userContextCallback;
|
---|
73 | }IOTHUB_METHOD_CALLBACK_DATA;
|
---|
74 |
|
---|
75 | typedef struct IOTHUB_EVENT_CALLBACK_TAG
|
---|
76 | {
|
---|
77 | STRING_HANDLE inputName;
|
---|
78 | IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC callbackAsync;
|
---|
79 | IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX callbackAsyncEx;
|
---|
80 | void* userContextCallback;
|
---|
81 | void* userContextCallbackEx;
|
---|
82 | }IOTHUB_EVENT_CALLBACK;
|
---|
83 |
|
---|
84 | typedef struct IOTHUB_MESSAGE_CALLBACK_DATA_TAG
|
---|
85 | {
|
---|
86 | CALLBACK_TYPE type;
|
---|
87 | IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC callbackSync;
|
---|
88 | IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX callbackAsync;
|
---|
89 | void* userContextCallback;
|
---|
90 | }IOTHUB_MESSAGE_CALLBACK_DATA;
|
---|
91 |
|
---|
92 | typedef struct GET_TWIN_CONTEXT_TAG
|
---|
93 | {
|
---|
94 | IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK callback;
|
---|
95 | void* context;
|
---|
96 | } GET_TWIN_CONTEXT;
|
---|
97 |
|
---|
98 | typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG
|
---|
99 | {
|
---|
100 | DLIST_ENTRY waitingToSend;
|
---|
101 | DLIST_ENTRY iot_msg_queue;
|
---|
102 | DLIST_ENTRY iot_ack_queue;
|
---|
103 | TRANSPORT_LL_HANDLE transportHandle;
|
---|
104 | bool isSharedTransport;
|
---|
105 | IOTHUB_DEVICE_HANDLE deviceHandle;
|
---|
106 | TRANSPORT_PROVIDER_FIELDS;
|
---|
107 | IOTHUB_MESSAGE_CALLBACK_DATA messageCallback;
|
---|
108 | IOTHUB_METHOD_CALLBACK_DATA methodCallback;
|
---|
109 | IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK conStatusCallback;
|
---|
110 | void* conStatusUserContextCallback;
|
---|
111 | time_t lastMessageReceiveTime;
|
---|
112 | TICK_COUNTER_HANDLE tickCounter; /*shared tickcounter used to track message timeouts in waitingToSend list*/
|
---|
113 | tickcounter_ms_t currentMessageTimeout;
|
---|
114 | uint64_t current_device_twin_timeout;
|
---|
115 | IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback;
|
---|
116 | void* deviceTwinContextCallback;
|
---|
117 | IOTHUB_CLIENT_RETRY_POLICY retryPolicy;
|
---|
118 | size_t retryTimeoutLimitInSeconds;
|
---|
119 | #ifndef DONT_USE_UPLOADTOBLOB
|
---|
120 | IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE uploadToBlobHandle;
|
---|
121 | #endif
|
---|
122 | #ifdef USE_EDGE_MODULES
|
---|
123 | IOTHUB_CLIENT_EDGE_HANDLE methodHandle;
|
---|
124 | #endif
|
---|
125 | uint32_t data_msg_id;
|
---|
126 | bool complete_twin_update_encountered;
|
---|
127 | IOTHUB_AUTHORIZATION_HANDLE authorization_module;
|
---|
128 | STRING_HANDLE product_info;
|
---|
129 | IOTHUB_DIAGNOSTIC_SETTING_DATA diagnostic_setting;
|
---|
130 | SINGLYLINKEDLIST_HANDLE event_callbacks; // List of IOTHUB_EVENT_CALLBACK's
|
---|
131 | }IOTHUB_CLIENT_CORE_LL_HANDLE_DATA;
|
---|
132 |
|
---|
133 | static const char HOSTNAME_TOKEN[] = "HostName";
|
---|
134 | static const char DEVICEID_TOKEN[] = "DeviceId";
|
---|
135 | static const char X509_TOKEN[] = "x509";
|
---|
136 | static const char X509_TOKEN_ONLY_ACCEPTABLE_VALUE[] = "true";
|
---|
137 | static const char DEVICEKEY_TOKEN[] = "SharedAccessKey";
|
---|
138 | static const char DEVICESAS_TOKEN[] = "SharedAccessSignature";
|
---|
139 | static const char PROTOCOL_GATEWAY_HOST_TOKEN[] = "GatewayHostName";
|
---|
140 | static const char MODULE_ID_TOKEN[] = "ModuleId";
|
---|
141 | static const char PROVISIONING_TOKEN[] = "UseProvisioning";
|
---|
142 | static const char PROVISIONING_ACCEPTABLE_VALUE[] = "true";
|
---|
143 |
|
---|
144 |
|
---|
145 | #ifdef USE_EDGE_MODULES
|
---|
146 | /*The following section should be moved to iothub_module_client_ll.c during impending refactor*/
|
---|
147 |
|
---|
148 | static const char* ENVIRONMENT_VAR_EDGEHUB_CONNECTIONSTRING = "EdgeHubConnectionString";
|
---|
149 | static const char* ENVIRONMENT_VAR_EDGEHUB_CACERTIFICATEFILE = "EdgeModuleCACertificateFile";
|
---|
150 | static const char* ENVIRONMENT_VAR_EDGEAUTHSCHEME = "IOTEDGE_AUTHSCHEME";
|
---|
151 | static const char* ENVIRONMENT_VAR_EDGEDEVICEID = "IOTEDGE_DEVICEID";
|
---|
152 | static const char* ENVIRONMENT_VAR_EDGEMODULEID = "IOTEDGE_MODULEID";
|
---|
153 | static const char* ENVIRONMENT_VAR_EDGEHUBHOSTNAME = "IOTEDGE_IOTHUBHOSTNAME";
|
---|
154 | static const char* ENVIRONMENT_VAR_EDGEGATEWAYHOST = "IOTEDGE_GATEWAYHOSTNAME";
|
---|
155 | static const char* SAS_TOKEN_AUTH = "sasToken";
|
---|
156 |
|
---|
157 |
|
---|
158 | typedef struct EDGE_ENVIRONMENT_VARIABLES_TAG
|
---|
159 | {
|
---|
160 | const char* connection_string;
|
---|
161 | const char* ca_trusted_certificate_file;
|
---|
162 | const char* auth_scheme;
|
---|
163 | const char* device_id;
|
---|
164 | const char* iothub_name;
|
---|
165 | const char* iothub_suffix;
|
---|
166 | const char* gatewayhostname;
|
---|
167 | const char* module_id;
|
---|
168 | char* iothub_buffer;
|
---|
169 | } EDGE_ENVIRONMENT_VARIABLES;
|
---|
170 |
|
---|
171 |
|
---|
172 | static int retrieve_edge_environment_variabes(EDGE_ENVIRONMENT_VARIABLES *edge_environment_variables)
|
---|
173 | {
|
---|
174 | int result;
|
---|
175 | const char* edgehubhostname;
|
---|
176 | char* edgehubhostname_separator;
|
---|
177 |
|
---|
178 | if ((edge_environment_variables->connection_string = environment_get_variable(ENVIRONMENT_VAR_EDGEHUB_CONNECTIONSTRING)) != NULL)
|
---|
179 | {
|
---|
180 | if ((edge_environment_variables->ca_trusted_certificate_file = environment_get_variable(ENVIRONMENT_VAR_EDGEHUB_CACERTIFICATEFILE)) == NULL)
|
---|
181 | {
|
---|
182 | LogError("Environment variable %s is missing. When %s is set, it is required", ENVIRONMENT_VAR_EDGEHUB_CACERTIFICATEFILE, ENVIRONMENT_VAR_EDGEHUB_CONNECTIONSTRING);
|
---|
183 | result = MU_FAILURE;
|
---|
184 | }
|
---|
185 | else
|
---|
186 | {
|
---|
187 | // If we can read in the connection string and trusted certs, we're done.
|
---|
188 | result = 0;
|
---|
189 | }
|
---|
190 | }
|
---|
191 | else
|
---|
192 | {
|
---|
193 | // We're NOT using pre-configured EdgeConnection string / certificates. In this case, we use these environment variables when
|
---|
194 | // communicating to Edge service.
|
---|
195 | if ((edge_environment_variables->auth_scheme = environment_get_variable(ENVIRONMENT_VAR_EDGEAUTHSCHEME)) == NULL)
|
---|
196 | {
|
---|
197 | LogError("Environment %s not set", ENVIRONMENT_VAR_EDGEAUTHSCHEME);
|
---|
198 | result = MU_FAILURE;
|
---|
199 | }
|
---|
200 | else if (strcmp(edge_environment_variables->auth_scheme, SAS_TOKEN_AUTH) != 0)
|
---|
201 | {
|
---|
202 | LogError("Environment %s was set to %s, but only support for %s", ENVIRONMENT_VAR_EDGEAUTHSCHEME, edge_environment_variables->auth_scheme, SAS_TOKEN_AUTH);
|
---|
203 | result = MU_FAILURE;
|
---|
204 | }
|
---|
205 | else if ((edge_environment_variables->device_id = environment_get_variable(ENVIRONMENT_VAR_EDGEDEVICEID)) == NULL)
|
---|
206 | {
|
---|
207 | LogError("Environment %s not set", ENVIRONMENT_VAR_EDGEDEVICEID);
|
---|
208 | result = MU_FAILURE;
|
---|
209 | }
|
---|
210 | else if ((edgehubhostname = environment_get_variable(ENVIRONMENT_VAR_EDGEHUBHOSTNAME)) == NULL)
|
---|
211 | {
|
---|
212 | LogError("Environment %s not set", ENVIRONMENT_VAR_EDGEHUBHOSTNAME);
|
---|
213 | result = MU_FAILURE;
|
---|
214 | }
|
---|
215 | else if ((edge_environment_variables->gatewayhostname = environment_get_variable(ENVIRONMENT_VAR_EDGEGATEWAYHOST)) == NULL)
|
---|
216 | {
|
---|
217 | LogError("Environment %s not set", ENVIRONMENT_VAR_EDGEGATEWAYHOST);
|
---|
218 | result = MU_FAILURE;
|
---|
219 | }
|
---|
220 | else if ((edge_environment_variables->module_id = environment_get_variable(ENVIRONMENT_VAR_EDGEMODULEID)) == NULL)
|
---|
221 | {
|
---|
222 | LogError("Environment %s not set", ENVIRONMENT_VAR_EDGEMODULEID);
|
---|
223 | result = MU_FAILURE;
|
---|
224 | }
|
---|
225 | // Make a copy of just ENVIRONMENT_VAR_EDGEHUBHOSTNAME. We need to make changes in place (namely inserting a '\0')
|
---|
226 | // and can't do this with system environment variable safely.
|
---|
227 | else if (mallocAndStrcpy_s(&edge_environment_variables->iothub_buffer, edgehubhostname) != 0)
|
---|
228 | {
|
---|
229 | LogError("Unable to copy buffer");
|
---|
230 | result = MU_FAILURE;
|
---|
231 | }
|
---|
232 | else if ((edgehubhostname_separator = strchr(edge_environment_variables->iothub_buffer, '.')) == NULL)
|
---|
233 | {
|
---|
234 | LogError("Environment edgehub %s invalid, requires '.' separator", edge_environment_variables->iothub_buffer);
|
---|
235 | result = MU_FAILURE;
|
---|
236 | }
|
---|
237 | else if (*(edgehubhostname_separator + 1) == 0)
|
---|
238 | {
|
---|
239 | LogError("Environment edgehub %s invalid, no content after '.' separator", edge_environment_variables->iothub_buffer);
|
---|
240 | result = MU_FAILURE;
|
---|
241 | }
|
---|
242 | else
|
---|
243 | {
|
---|
244 | edge_environment_variables->iothub_name = edge_environment_variables->iothub_buffer;
|
---|
245 | *edgehubhostname_separator = 0;
|
---|
246 | edge_environment_variables->iothub_suffix = edgehubhostname_separator + 1;
|
---|
247 | result = 0;
|
---|
248 | }
|
---|
249 | }
|
---|
250 |
|
---|
251 | return result;
|
---|
252 | }
|
---|
253 |
|
---|
254 | IOTHUB_CLIENT_EDGE_HANDLE IoTHubClientCore_LL_GetEdgeHandle(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle)
|
---|
255 | {
|
---|
256 | IOTHUB_CLIENT_EDGE_HANDLE result;
|
---|
257 | if (iotHubClientHandle != NULL)
|
---|
258 | {
|
---|
259 | result = iotHubClientHandle->methodHandle;
|
---|
260 | }
|
---|
261 | else
|
---|
262 | {
|
---|
263 | result = NULL;
|
---|
264 | }
|
---|
265 |
|
---|
266 | return result;
|
---|
267 | }
|
---|
268 | #endif /* USE_EDGE_MODULES */
|
---|
269 |
|
---|
270 | static void setTransportProtocol(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, TRANSPORT_PROVIDER* protocol)
|
---|
271 | {
|
---|
272 | handleData->IoTHubTransport_SendMessageDisposition = protocol->IoTHubTransport_SendMessageDisposition;
|
---|
273 | handleData->IoTHubTransport_GetHostname = protocol->IoTHubTransport_GetHostname;
|
---|
274 | handleData->IoTHubTransport_SetOption = protocol->IoTHubTransport_SetOption;
|
---|
275 | handleData->IoTHubTransport_Create = protocol->IoTHubTransport_Create;
|
---|
276 | handleData->IoTHubTransport_Destroy = protocol->IoTHubTransport_Destroy;
|
---|
277 | handleData->IoTHubTransport_Register = protocol->IoTHubTransport_Register;
|
---|
278 | handleData->IoTHubTransport_Unregister = protocol->IoTHubTransport_Unregister;
|
---|
279 | handleData->IoTHubTransport_Subscribe = protocol->IoTHubTransport_Subscribe;
|
---|
280 | handleData->IoTHubTransport_Unsubscribe = protocol->IoTHubTransport_Unsubscribe;
|
---|
281 | handleData->IoTHubTransport_DoWork = protocol->IoTHubTransport_DoWork;
|
---|
282 | handleData->IoTHubTransport_SetRetryPolicy = protocol->IoTHubTransport_SetRetryPolicy;
|
---|
283 | handleData->IoTHubTransport_GetSendStatus = protocol->IoTHubTransport_GetSendStatus;
|
---|
284 | handleData->IoTHubTransport_ProcessItem = protocol->IoTHubTransport_ProcessItem;
|
---|
285 | handleData->IoTHubTransport_Subscribe_DeviceTwin = protocol->IoTHubTransport_Subscribe_DeviceTwin;
|
---|
286 | handleData->IoTHubTransport_Unsubscribe_DeviceTwin = protocol->IoTHubTransport_Unsubscribe_DeviceTwin;
|
---|
287 | handleData->IoTHubTransport_GetTwinAsync = protocol->IoTHubTransport_GetTwinAsync;
|
---|
288 | handleData->IoTHubTransport_Subscribe_DeviceMethod = protocol->IoTHubTransport_Subscribe_DeviceMethod;
|
---|
289 | handleData->IoTHubTransport_Unsubscribe_DeviceMethod = protocol->IoTHubTransport_Unsubscribe_DeviceMethod;
|
---|
290 | handleData->IoTHubTransport_DeviceMethod_Response = protocol->IoTHubTransport_DeviceMethod_Response;
|
---|
291 | handleData->IoTHubTransport_Subscribe_InputQueue = protocol->IoTHubTransport_Subscribe_InputQueue;
|
---|
292 | handleData->IoTHubTransport_Unsubscribe_InputQueue = protocol->IoTHubTransport_Unsubscribe_InputQueue;
|
---|
293 | handleData->IoTHubTransport_SetCallbackContext = protocol->IoTHubTransport_SetCallbackContext;
|
---|
294 | }
|
---|
295 |
|
---|
296 | static bool is_event_equal(IOTHUB_EVENT_CALLBACK *event_callback, const char *input_name)
|
---|
297 | {
|
---|
298 | bool result;
|
---|
299 |
|
---|
300 | if (event_callback != NULL)
|
---|
301 | {
|
---|
302 | const char* event_input_name = STRING_c_str(event_callback->inputName);
|
---|
303 | if ((event_input_name != NULL) && (input_name != NULL))
|
---|
304 | {
|
---|
305 | // Matched the input queue name of a named handler
|
---|
306 | result = (strcmp(event_input_name, input_name) == 0);
|
---|
307 | }
|
---|
308 | else if ((input_name == NULL) && (event_input_name == NULL))
|
---|
309 | {
|
---|
310 | // Matched the default handler
|
---|
311 | result = true;
|
---|
312 | }
|
---|
313 | else
|
---|
314 | {
|
---|
315 | result = false;
|
---|
316 | }
|
---|
317 | }
|
---|
318 | else
|
---|
319 | {
|
---|
320 | result = false;
|
---|
321 | }
|
---|
322 | return result;
|
---|
323 | }
|
---|
324 |
|
---|
325 | static bool is_event_equal_for_match(LIST_ITEM_HANDLE list_item, const void* match_context)
|
---|
326 | {
|
---|
327 | return is_event_equal((IOTHUB_EVENT_CALLBACK*)singlylinkedlist_item_get_value(list_item), (const char*)match_context);
|
---|
328 | }
|
---|
329 |
|
---|
330 | static void device_twin_data_destroy(IOTHUB_DEVICE_TWIN* client_item)
|
---|
331 | {
|
---|
332 | CONSTBUFFER_DecRef(client_item->report_data_handle);
|
---|
333 | free(client_item);
|
---|
334 | }
|
---|
335 |
|
---|
336 | static int create_edge_handle(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handle_data, const IOTHUB_CLIENT_CONFIG* config, const char* module_id)
|
---|
337 | {
|
---|
338 | int result;
|
---|
339 | (void)config;
|
---|
340 | (void)module_id;
|
---|
341 | #ifdef USE_EDGE_MODULES
|
---|
342 | /* There is no way to currently distinguish a regular module from a edge module, so this handle is created regardless of if appropriate.
|
---|
343 | However, as a gateway hostname is required in order to create an Edge Handle, we need to at least make sure that exists
|
---|
344 | in order to prevent errors.
|
---|
345 |
|
---|
346 | The end result is that all edge modules will have an EdgeHandle, but only some non-edge modules will have it.
|
---|
347 | Regardless, non-edge modules will never be able to use the handle.
|
---|
348 | */
|
---|
349 | if (config->protocolGatewayHostName != NULL)
|
---|
350 | {
|
---|
351 | handle_data->methodHandle = IoTHubClient_EdgeHandle_Create(config, handle_data->authorization_module, module_id);
|
---|
352 |
|
---|
353 | if (handle_data->methodHandle == NULL)
|
---|
354 | {
|
---|
355 | LogError("Unable to IoTHubModuleClient_LL_MethodHandle_Create");
|
---|
356 | result = MU_FAILURE;
|
---|
357 | }
|
---|
358 | else
|
---|
359 | {
|
---|
360 | result = 0;
|
---|
361 | }
|
---|
362 | }
|
---|
363 | else
|
---|
364 | {
|
---|
365 | result = 0;
|
---|
366 | }
|
---|
367 |
|
---|
368 | #else
|
---|
369 | (void)handle_data;
|
---|
370 | result = 0;
|
---|
371 | #endif
|
---|
372 | return result;
|
---|
373 | }
|
---|
374 |
|
---|
375 | static int create_blob_upload_module(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handle_data, const IOTHUB_CLIENT_CONFIG* config)
|
---|
376 | {
|
---|
377 | int result;
|
---|
378 | (void)handle_data;
|
---|
379 | (void)config;
|
---|
380 | #ifndef DONT_USE_UPLOADTOBLOB
|
---|
381 | handle_data->uploadToBlobHandle = IoTHubClient_LL_UploadToBlob_Create(config, handle_data->authorization_module);
|
---|
382 | if (handle_data->uploadToBlobHandle == NULL)
|
---|
383 | {
|
---|
384 | LogError("unable to IoTHubClientCore_LL_UploadToBlob_Create");
|
---|
385 | result = MU_FAILURE;
|
---|
386 | }
|
---|
387 | else
|
---|
388 | {
|
---|
389 | result = 0;
|
---|
390 | }
|
---|
391 | #else
|
---|
392 | result = 0;
|
---|
393 | #endif
|
---|
394 | return result;
|
---|
395 | }
|
---|
396 |
|
---|
397 | static void destroy_blob_upload_module(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handle_data)
|
---|
398 | {
|
---|
399 | (void)handle_data;
|
---|
400 | #ifndef DONT_USE_UPLOADTOBLOB
|
---|
401 | /*Codes_SRS_IOTHUBCLIENT_LL_02_046: [ If creating the TICK_COUNTER_HANDLE fails then IoTHubClientCore_LL_Create shall fail and return NULL. ]*/
|
---|
402 | IoTHubClient_LL_UploadToBlob_Destroy(handle_data->uploadToBlobHandle);
|
---|
403 | #endif
|
---|
404 | }
|
---|
405 |
|
---|
406 | static void destroy_module_method_module(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handle_data)
|
---|
407 | {
|
---|
408 | (void)handle_data;
|
---|
409 | #ifdef USE_EDGE_MODULES
|
---|
410 | IoTHubClient_EdgeHandle_Destroy(handle_data->methodHandle);
|
---|
411 | #endif
|
---|
412 | }
|
---|
413 |
|
---|
414 | static bool invoke_message_callback(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, MESSAGE_CALLBACK_INFO* messageData)
|
---|
415 | {
|
---|
416 | bool result;
|
---|
417 | /* Codes_SRS_IOTHUBCLIENT_LL_09_004: [IoTHubClient_LL_GetLastMessageReceiveTime shall return lastMessageReceiveTime in localtime] */
|
---|
418 | handleData->lastMessageReceiveTime = get_time(NULL);
|
---|
419 |
|
---|
420 | switch (handleData->messageCallback.type)
|
---|
421 | {
|
---|
422 | case CALLBACK_TYPE_NONE:
|
---|
423 | {
|
---|
424 | /*Codes_SRS_IOTHUBCLIENT_LL_02_032: [If the client is not subscribed to receive messages then IoTHubClient_LL_MessageCallback shall return false.] */
|
---|
425 | LogError("Invalid workflow - not currently set up to accept messages");
|
---|
426 | result = false;
|
---|
427 | break;
|
---|
428 | }
|
---|
429 | case CALLBACK_TYPE_SYNC:
|
---|
430 | {
|
---|
431 | /*Codes_SRS_IOTHUBCLIENT_LL_02_030: [If messageCallbackType is LEGACY then IoTHubClient_LL_MessageCallback shall invoke the last callback function (the parameter messageCallback to IoTHubClient_LL_SetMessageCallback) passing the message and the passed userContextCallback.]*/
|
---|
432 | IOTHUBMESSAGE_DISPOSITION_RESULT cb_result = handleData->messageCallback.callbackSync(messageData->messageHandle, handleData->messageCallback.userContextCallback);
|
---|
433 |
|
---|
434 | /*Codes_SRS_IOTHUBCLIENT_LL_10_007: [If messageCallbackType is LEGACY then IoTHubClient_LL_MessageCallback shall send the message disposition as returned by the client to the underlying layer.] */
|
---|
435 | if (handleData->IoTHubTransport_SendMessageDisposition(messageData, cb_result) != IOTHUB_CLIENT_OK)
|
---|
436 | {
|
---|
437 | LogError("IoTHubTransport_SendMessageDisposition failed");
|
---|
438 | }
|
---|
439 | result = true;
|
---|
440 | break;
|
---|
441 | }
|
---|
442 | case CALLBACK_TYPE_ASYNC:
|
---|
443 | {
|
---|
444 | /* Codes_SRS_IOTHUBCLIENT_LL_10_009: [If messageCallbackType is ASYNC then IoTHubClient_LL_MessageCallback shall return what messageCallbacEx returns.] */
|
---|
445 | result = handleData->messageCallback.callbackAsync(messageData, handleData->messageCallback.userContextCallback);
|
---|
446 | if (!result)
|
---|
447 | {
|
---|
448 | LogError("messageCallbackEx failed");
|
---|
449 | }
|
---|
450 | break;
|
---|
451 | }
|
---|
452 | default:
|
---|
453 | {
|
---|
454 | LogError("Invalid state");
|
---|
455 | result = false;
|
---|
456 | break;
|
---|
457 | }
|
---|
458 | }
|
---|
459 |
|
---|
460 | return result;
|
---|
461 | }
|
---|
462 |
|
---|
463 | /*Codes_SRS_IOTHUBCLIENT_LL_10_032: ["product_info" - takes a char string as an argument to specify the product information(e.g. `"ProductName/ProductVersion"`). ]*/
|
---|
464 | /*Codes_SRS_IOTHUBCLIENT_LL_10_034: ["product_info" - shall store the given string concatenated with the sdk information and the platform information in the form(ProductInfo DeviceSDKName / DeviceSDKVersion(OSName OSVersion; Architecture). ]*/
|
---|
465 | static STRING_HANDLE make_product_info(const char* product)
|
---|
466 | {
|
---|
467 | STRING_HANDLE result;
|
---|
468 | STRING_HANDLE pfi = platform_get_platform_info(PLATFORM_INFO_OPTION_DEFAULT);
|
---|
469 | if (pfi == NULL)
|
---|
470 | {
|
---|
471 | result = NULL;
|
---|
472 | }
|
---|
473 | else
|
---|
474 | {
|
---|
475 | if (product == NULL)
|
---|
476 | {
|
---|
477 | result = STRING_construct_sprintf("%s %s", CLIENT_DEVICE_TYPE_PREFIX CLIENT_DEVICE_BACKSLASH IOTHUB_SDK_VERSION, STRING_c_str(pfi));
|
---|
478 | }
|
---|
479 | else
|
---|
480 | {
|
---|
481 | result = STRING_construct_sprintf("%s %s %s", product, CLIENT_DEVICE_TYPE_PREFIX CLIENT_DEVICE_BACKSLASH IOTHUB_SDK_VERSION, STRING_c_str(pfi));
|
---|
482 | }
|
---|
483 | STRING_delete(pfi);
|
---|
484 | }
|
---|
485 | return result;
|
---|
486 | }
|
---|
487 |
|
---|
488 | static void IoTHubClientCore_LL_SendComplete(PDLIST_ENTRY completed, IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* ctx)
|
---|
489 | {
|
---|
490 | /*Codes_SRS_IOTHUBCLIENT_LL_02_022: [If parameter completed is NULL, or parameter handle is NULL then IoTHubClientCore_LL_SendBatch shall return.]*/
|
---|
491 | if (
|
---|
492 | (ctx == NULL) ||
|
---|
493 | (completed == NULL)
|
---|
494 | )
|
---|
495 | {
|
---|
496 | /*"shall return"*/
|
---|
497 | LogError("invalid arg");
|
---|
498 | }
|
---|
499 | else
|
---|
500 | {
|
---|
501 | /*Codes_SRS_IOTHUBCLIENT_LL_02_027: [If parameter result is IOTHUB_CLIENT_CONFIRMATION_ERROR then IoTHubClientCore_LL_SendComplete shall call all the non-NULL callbacks with the result parameter set to IOTHUB_CLIENT_CONFIRMATION_ERROR and the context set to the context passed originally in the SendEventAsync call.] */
|
---|
502 | /*Codes_SRS_IOTHUBCLIENT_LL_02_025: [If parameter result is IOTHUB_CLIENT_CONFIRMATION_OK then IoTHubClientCore_LL_SendComplete shall call all the non-NULL callbacks with the result parameter set to IOTHUB_CLIENT_CONFIRMATION_OK and the context set to the context passed originally in the SendEventAsync call.]*/
|
---|
503 | PDLIST_ENTRY oldest;
|
---|
504 | while ((oldest = DList_RemoveHeadList(completed)) != completed)
|
---|
505 | {
|
---|
506 | IOTHUB_MESSAGE_LIST* messageList = (IOTHUB_MESSAGE_LIST*)containingRecord(oldest, IOTHUB_MESSAGE_LIST, entry);
|
---|
507 | /*Codes_SRS_IOTHUBCLIENT_LL_02_026: [If any callback is NULL then there shall not be a callback call.]*/
|
---|
508 | if (messageList->callback != NULL)
|
---|
509 | {
|
---|
510 | messageList->callback(result, messageList->context);
|
---|
511 | }
|
---|
512 | IoTHubMessage_Destroy(messageList->messageHandle);
|
---|
513 | free(messageList);
|
---|
514 | }
|
---|
515 | }
|
---|
516 | }
|
---|
517 |
|
---|
518 | static void IoTHubClientCore_LL_RetrievePropertyComplete(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* ctx)
|
---|
519 | {
|
---|
520 | if (ctx == NULL)
|
---|
521 | {
|
---|
522 | /* Codes_SRS_IOTHUBCLIENT_LL_07_013: [ If handle is NULL then IoTHubClientCore_LL_RetrievePropertyComplete shall do nothing.] */
|
---|
523 | LogError("Invalid argument ctx NULL");
|
---|
524 | }
|
---|
525 | else
|
---|
526 | {
|
---|
527 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
|
---|
528 | /* Codes_SRS_IOTHUBCLIENT_LL_07_014: [ If deviceTwinCallback is NULL then IoTHubClientCore_LL_RetrievePropertyComplete shall do nothing.] */
|
---|
529 | if (handleData->deviceTwinCallback)
|
---|
530 | {
|
---|
531 | /* Codes_SRS_IOTHUBCLIENT_LL_07_015: [ If the the update_state parameter is DEVICE_TWIN_UPDATE_PARTIAL and a DEVICE_TWIN_UPDATE_COMPLETE has not been previously recieved then IoTHubClientCore_LL_RetrievePropertyComplete shall do nothing.] */
|
---|
532 | if (update_state == DEVICE_TWIN_UPDATE_COMPLETE)
|
---|
533 | {
|
---|
534 | handleData->complete_twin_update_encountered = true;
|
---|
535 | }
|
---|
536 | if (handleData->complete_twin_update_encountered)
|
---|
537 | {
|
---|
538 | /* Codes_SRS_IOTHUBCLIENT_LL_07_016: [ If deviceTwinCallback is set and DEVICE_TWIN_UPDATE_COMPLETE has been encountered then IoTHubClientCore_LL_RetrievePropertyComplete shall call deviceTwinCallback.] */
|
---|
539 | handleData->deviceTwinCallback(update_state, payLoad, size, handleData->deviceTwinContextCallback);
|
---|
540 | }
|
---|
541 | }
|
---|
542 | }
|
---|
543 | }
|
---|
544 |
|
---|
545 | static void IoTHubClientCore_LL_ReportedStateComplete(uint32_t item_id, int status_code, void* ctx)
|
---|
546 | {
|
---|
547 | /* Codes_SRS_IOTHUBCLIENT_LL_07_002: [ if handle or queue_handle are NULL then IoTHubClientCore_LL_ReportedStateComplete shall do nothing. ] */
|
---|
548 | if (ctx == NULL)
|
---|
549 | {
|
---|
550 | /*"shall return"*/
|
---|
551 | LogError("Invalid argument handle=%p", ctx);
|
---|
552 | }
|
---|
553 | else
|
---|
554 | {
|
---|
555 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
|
---|
556 |
|
---|
557 | /* Codes_SRS_IOTHUBCLIENT_LL_07_003: [ IoTHubClientCore_LL_ReportedStateComplete shall enumerate through the IOTHUB_DEVICE_TWIN structures in queue_handle. ]*/
|
---|
558 | DLIST_ENTRY* client_item = handleData->iot_ack_queue.Flink;
|
---|
559 | while (client_item != &(handleData->iot_ack_queue)) /*while we are not at the end of the list*/
|
---|
560 | {
|
---|
561 | PDLIST_ENTRY next_item = client_item->Flink;
|
---|
562 | IOTHUB_DEVICE_TWIN* queue_data = containingRecord(client_item, IOTHUB_DEVICE_TWIN, entry);
|
---|
563 | if (queue_data->item_id == item_id)
|
---|
564 | {
|
---|
565 | if (queue_data->reported_state_callback != NULL)
|
---|
566 | {
|
---|
567 | queue_data->reported_state_callback(status_code, queue_data->context);
|
---|
568 | }
|
---|
569 | /*Codes_SRS_IOTHUBCLIENT_LL_07_009: [ IoTHubClientCore_LL_ReportedStateComplete shall remove the IOTHUB_DEVICE_TWIN item from the ack queue.]*/
|
---|
570 | DList_RemoveEntryList(client_item);
|
---|
571 | device_twin_data_destroy(queue_data);
|
---|
572 | break;
|
---|
573 | }
|
---|
574 | client_item = next_item;
|
---|
575 | }
|
---|
576 | }
|
---|
577 | }
|
---|
578 |
|
---|
579 | static void IoTHubClientCore_LL_ConnectionStatusCallBack(IOTHUB_CLIENT_CONNECTION_STATUS status, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void* ctx)
|
---|
580 | {
|
---|
581 | /*Codes_SRS_IOTHUBCLIENT_LL_25_113: [If parameter connectionStatus is NULL or parameter handle is NULL then IoTHubClientCore_LL_ConnectionStatusCallBack shall return.]*/
|
---|
582 | if (ctx == NULL)
|
---|
583 | {
|
---|
584 | /*"shall return"*/
|
---|
585 | LogError("invalid arg");
|
---|
586 | }
|
---|
587 | else
|
---|
588 | {
|
---|
589 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
|
---|
590 |
|
---|
591 | /*Codes_SRS_IOTHUBCLIENT_LL_25_114: [IoTHubClientCore_LL_ConnectionStatusCallBack shall call non-callback set by the user from IoTHubClientCore_LL_SetConnectionStatusCallback passing the status, reason and the passed userContextCallback.]*/
|
---|
592 | if (handleData->conStatusCallback != NULL)
|
---|
593 | {
|
---|
594 | handleData->conStatusCallback(status, reason, handleData->conStatusUserContextCallback);
|
---|
595 | }
|
---|
596 | }
|
---|
597 |
|
---|
598 | }
|
---|
599 |
|
---|
600 | static const char* IoTHubClientCore_LL_GetProductInfo(void* ctx)
|
---|
601 | {
|
---|
602 | const char* result;
|
---|
603 | if (ctx == NULL)
|
---|
604 | {
|
---|
605 | result = NULL;
|
---|
606 | LogError("invalid argument ctx %p", ctx);
|
---|
607 | }
|
---|
608 | else
|
---|
609 | {
|
---|
610 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* iothub_data = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
|
---|
611 | result = STRING_c_str(iothub_data->product_info);
|
---|
612 | }
|
---|
613 | return result;
|
---|
614 | }
|
---|
615 |
|
---|
616 | static bool IoTHubClientCore_LL_MessageCallbackFromInput(MESSAGE_CALLBACK_INFO* messageData, void* ctx)
|
---|
617 | {
|
---|
618 | bool result;
|
---|
619 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
|
---|
620 |
|
---|
621 | if ((handleData == NULL) || messageData == NULL)
|
---|
622 | {
|
---|
623 | // Codes_SRS_IOTHUBCLIENT_LL_31_137: [ If either parameter `handle` or `messageData` is `NULL` then `IoTHubClient_LL_MessageCallbackFromInput` shall return `false`.** ]
|
---|
624 | LogError("invalid argument: handle(%p), messageData(%p)", handleData, messageData);
|
---|
625 | result = false;
|
---|
626 | }
|
---|
627 | else if (messageData->messageHandle == NULL)
|
---|
628 | {
|
---|
629 | // Codes_SRS_IOTHUBCLIENT_LL_31_137: [ If either parameter `handle` or `messageData` is `NULL` then `IoTHubClient_LL_MessageCallbackFromInput` shall return `false`.** ]
|
---|
630 | LogError("invalid argument messageData->messageHandle(NULL)");
|
---|
631 | result = false;
|
---|
632 | }
|
---|
633 | else if (handleData->event_callbacks == NULL)
|
---|
634 | {
|
---|
635 | LogError("Callback from input called but no input specific callbacks registered");
|
---|
636 | result = false;
|
---|
637 | }
|
---|
638 | else
|
---|
639 | {
|
---|
640 | const char* inputName = IoTHubMessage_GetInputName(messageData->messageHandle);
|
---|
641 |
|
---|
642 | LIST_ITEM_HANDLE item_handle = NULL;
|
---|
643 |
|
---|
644 | item_handle = singlylinkedlist_find(handleData->event_callbacks, is_event_equal_for_match, (const void*)inputName);
|
---|
645 |
|
---|
646 | if (item_handle == NULL)
|
---|
647 | {
|
---|
648 | // Codes_SRS_IOTHUBCLIENT_LL_31_138: [ If there is no registered handler for the inputName from `IoTHubMessage_GetInputName`, then `IoTHubClient_LL_MessageCallbackFromInput` shall attempt invoke the default handler handler.** ]
|
---|
649 | item_handle = singlylinkedlist_find(handleData->event_callbacks, is_event_equal_for_match, NULL);
|
---|
650 | }
|
---|
651 |
|
---|
652 | if (item_handle == NULL)
|
---|
653 | {
|
---|
654 | LogError("Could not find callback (explicit or default) for input queue %s", inputName);
|
---|
655 | result = false;
|
---|
656 | }
|
---|
657 | else
|
---|
658 | {
|
---|
659 | IOTHUB_EVENT_CALLBACK* event_callback = (IOTHUB_EVENT_CALLBACK*)singlylinkedlist_item_get_value(item_handle);
|
---|
660 | if (NULL == event_callback)
|
---|
661 | {
|
---|
662 | LogError("singlylinkedlist_item_get_value for event_callback failed");
|
---|
663 | result = false;
|
---|
664 | }
|
---|
665 | else
|
---|
666 | {
|
---|
667 | // Codes_SRS_IOTHUBCLIENT_LL_09_004: [IoTHubClient_LL_GetLastMessageReceiveTime shall return lastMessageReceiveTime in localtime]
|
---|
668 | handleData->lastMessageReceiveTime = get_time(NULL);
|
---|
669 |
|
---|
670 | if (event_callback->callbackAsyncEx != NULL)
|
---|
671 | {
|
---|
672 | // Codes_SRS_IOTHUBCLIENT_LL_31_139: [ `IoTHubClient_LL_MessageCallbackFromInput` shall the callback from the given inputName queue if it has been registered.** ]
|
---|
673 | result = event_callback->callbackAsyncEx(messageData, event_callback->userContextCallbackEx);
|
---|
674 | }
|
---|
675 | else
|
---|
676 | {
|
---|
677 | // Codes_SRS_IOTHUBCLIENT_LL_31_139: [ `IoTHubClient_LL_MessageCallbackFromInput` shall the callback from the given inputName queue if it has been registered.** ]
|
---|
678 | IOTHUBMESSAGE_DISPOSITION_RESULT cb_result = event_callback->callbackAsync(messageData->messageHandle, event_callback->userContextCallback);
|
---|
679 |
|
---|
680 | // Codes_SRS_IOTHUBCLIENT_LL_31_140: [ `IoTHubClient_LL_MessageCallbackFromInput` shall send the message disposition as returned by the client to the underlying layer and return `true` if an input queue match is found.** ]
|
---|
681 | if (handleData->IoTHubTransport_SendMessageDisposition(messageData, cb_result) != IOTHUB_CLIENT_OK)
|
---|
682 | {
|
---|
683 | LogError("IoTHubTransport_SendMessageDisposition failed");
|
---|
684 | }
|
---|
685 | result = true;
|
---|
686 | }
|
---|
687 | }
|
---|
688 | }
|
---|
689 | }
|
---|
690 | return result;
|
---|
691 | }
|
---|
692 |
|
---|
693 | static bool IoTHubClientCore_LL_MessageCallback(MESSAGE_CALLBACK_INFO* messageData, void* ctx)
|
---|
694 | {
|
---|
695 | bool result;
|
---|
696 | if ((ctx == NULL) || messageData == NULL)
|
---|
697 | {
|
---|
698 | /*Codes_SRS_IOTHUBCLIENT_LL_02_029: [If parameter handle is NULL then IoTHubClient_LL_MessageCallback shall return IOTHUBMESSAGE_ABANDONED.] */
|
---|
699 | LogError("invalid argument: ctx(%p), messageData(%p)", ctx, messageData);
|
---|
700 | result = false;
|
---|
701 | }
|
---|
702 | else if (messageData->messageHandle == NULL)
|
---|
703 | {
|
---|
704 | /*Codes_SRS_IOTHUBCLIENT_LL_10_004: [If messageHandle field of paramger messageData is NULL then IoTHubClient_LL_MessageCallback shall return IOTHUBMESSAGE_ABANDONED.] */
|
---|
705 | LogError("invalid argument messageData->messageHandle(NULL)");
|
---|
706 | result = false;
|
---|
707 | }
|
---|
708 | else
|
---|
709 | {
|
---|
710 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
|
---|
711 | return invoke_message_callback(handleData, messageData);
|
---|
712 | }
|
---|
713 | return result;
|
---|
714 | }
|
---|
715 |
|
---|
716 | static int IoTHubClientCore_LL_DeviceMethodComplete(const char* method_name, const unsigned char* payLoad, size_t size, METHOD_HANDLE response_id, void* ctx)
|
---|
717 | {
|
---|
718 | int result;
|
---|
719 | if (ctx == NULL)
|
---|
720 | {
|
---|
721 | /* Codes_SRS_IOTHUBCLIENT_LL_07_017: [ If handle or response is NULL then IoTHubClientCore_LL_DeviceMethodComplete shall return 500. ] */
|
---|
722 | LogError("Invalid argument ctx=%p", ctx);
|
---|
723 | result = MU_FAILURE;
|
---|
724 | }
|
---|
725 | else
|
---|
726 | {
|
---|
727 | /* Codes_SRS_IOTHUBCLIENT_LL_07_018: [ If deviceMethodCallback is not NULL IoTHubClientCore_LL_DeviceMethodComplete shall execute deviceMethodCallback and return the status. ] */
|
---|
728 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)ctx;
|
---|
729 | switch (handleData->methodCallback.type)
|
---|
730 | {
|
---|
731 | case CALLBACK_TYPE_SYNC:
|
---|
732 | {
|
---|
733 | unsigned char* payload_resp = NULL;
|
---|
734 | size_t response_size = 0;
|
---|
735 | result = handleData->methodCallback.callbackSync(method_name, payLoad, size, &payload_resp, &response_size, handleData->methodCallback.userContextCallback);
|
---|
736 | /* Codes_SRS_IOTHUBCLIENT_LL_07_020: [ deviceMethodCallback shall build the BUFFER_HANDLE with the response payload from the IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC callback. ] */
|
---|
737 | if (payload_resp != NULL && response_size > 0)
|
---|
738 | {
|
---|
739 | result = handleData->IoTHubTransport_DeviceMethod_Response(handleData->deviceHandle, response_id, payload_resp, response_size, result);
|
---|
740 | }
|
---|
741 | else
|
---|
742 | {
|
---|
743 | result = MU_FAILURE;
|
---|
744 | }
|
---|
745 | if (payload_resp != NULL)
|
---|
746 | {
|
---|
747 | free(payload_resp);
|
---|
748 | }
|
---|
749 | break;
|
---|
750 | }
|
---|
751 | case CALLBACK_TYPE_ASYNC:
|
---|
752 | result = handleData->methodCallback.callbackAsync(method_name, payLoad, size, response_id, handleData->methodCallback.userContextCallback);
|
---|
753 | break;
|
---|
754 | default:
|
---|
755 | /* Codes_SRS_IOTHUBCLIENT_LL_07_019: [ If deviceMethodCallback is NULL IoTHubClientCore_LL_DeviceMethodComplete shall return 404. ] */
|
---|
756 | result = 0;
|
---|
757 | break;
|
---|
758 | }
|
---|
759 | }
|
---|
760 | return result;
|
---|
761 | }
|
---|
762 |
|
---|
763 | static IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* initialize_iothub_client(const IOTHUB_CLIENT_CONFIG* client_config, const IOTHUB_CLIENT_DEVICE_CONFIG* device_config, bool use_dev_auth, const char* module_id)
|
---|
764 | {
|
---|
765 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* result;
|
---|
766 | srand((unsigned int)time(NULL));
|
---|
767 | STRING_HANDLE product_info = make_product_info(NULL);
|
---|
768 | if (product_info == NULL)
|
---|
769 | {
|
---|
770 | LogError("failed to initialize product info");
|
---|
771 | result = NULL;
|
---|
772 | }
|
---|
773 | else
|
---|
774 | {
|
---|
775 | result = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)malloc(sizeof(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA));
|
---|
776 | if (result == NULL)
|
---|
777 | {
|
---|
778 | LogError("failure allocating IOTHUB_CLIENT_CORE_LL_HANDLE_DATA");
|
---|
779 | STRING_delete(product_info);
|
---|
780 | }
|
---|
781 | else
|
---|
782 | {
|
---|
783 | IOTHUB_CLIENT_CONFIG actual_config;
|
---|
784 | const IOTHUB_CLIENT_CONFIG* config = NULL;
|
---|
785 | char* IoTHubName = NULL;
|
---|
786 | char* IoTHubSuffix = NULL;
|
---|
787 |
|
---|
788 | memset(result, 0, sizeof(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA));
|
---|
789 | if (use_dev_auth)
|
---|
790 | {
|
---|
791 | if ((result->authorization_module = IoTHubClient_Auth_CreateFromDeviceAuth(client_config->deviceId, module_id)) == NULL)
|
---|
792 | {
|
---|
793 | LogError("Failed create authorization module");
|
---|
794 | free(result);
|
---|
795 | STRING_delete(product_info);
|
---|
796 | result = NULL;
|
---|
797 | }
|
---|
798 | }
|
---|
799 | else
|
---|
800 | {
|
---|
801 | const char* device_key;
|
---|
802 | const char* device_id;
|
---|
803 | const char* sas_token;
|
---|
804 | if (device_config == NULL)
|
---|
805 | {
|
---|
806 | device_key = client_config->deviceKey;
|
---|
807 | device_id = client_config->deviceId;
|
---|
808 | sas_token = client_config->deviceSasToken;
|
---|
809 | }
|
---|
810 | else
|
---|
811 | {
|
---|
812 | device_key = device_config->deviceKey;
|
---|
813 | device_id = device_config->deviceId;
|
---|
814 | sas_token = device_config->deviceSasToken;
|
---|
815 | }
|
---|
816 |
|
---|
817 | /* Codes_SRS_IOTHUBCLIENT_LL_07_029: [ IoTHubClientCore_LL_Create shall create the Auth module with the device_key, device_id, and/or deviceSasToken values ] */
|
---|
818 | if ((result->authorization_module = IoTHubClient_Auth_Create(device_key, device_id, sas_token, module_id)) == NULL)
|
---|
819 | {
|
---|
820 | LogError("Failed create authorization module");
|
---|
821 | free(result);
|
---|
822 | STRING_delete(product_info);
|
---|
823 | result = NULL;
|
---|
824 | }
|
---|
825 | }
|
---|
826 |
|
---|
827 | if (result != NULL)
|
---|
828 | {
|
---|
829 | TRANSPORT_CALLBACKS_INFO transport_cb;
|
---|
830 | memset(&transport_cb, 0, sizeof(TRANSPORT_CALLBACKS_INFO));
|
---|
831 | transport_cb.send_complete_cb = IoTHubClientCore_LL_SendComplete;
|
---|
832 | transport_cb.twin_retrieve_prop_complete_cb = IoTHubClientCore_LL_RetrievePropertyComplete;
|
---|
833 | transport_cb.twin_rpt_state_complete_cb = IoTHubClientCore_LL_ReportedStateComplete;
|
---|
834 | transport_cb.connection_status_cb = IoTHubClientCore_LL_ConnectionStatusCallBack;
|
---|
835 | transport_cb.prod_info_cb = IoTHubClientCore_LL_GetProductInfo;
|
---|
836 | transport_cb.msg_input_cb = IoTHubClientCore_LL_MessageCallbackFromInput;
|
---|
837 | transport_cb.msg_cb = IoTHubClientCore_LL_MessageCallback;
|
---|
838 | transport_cb.method_complete_cb = IoTHubClientCore_LL_DeviceMethodComplete;
|
---|
839 |
|
---|
840 | if (client_config != NULL)
|
---|
841 | {
|
---|
842 | IOTHUBTRANSPORT_CONFIG lowerLayerConfig;
|
---|
843 | memset(&lowerLayerConfig, 0, sizeof(IOTHUBTRANSPORT_CONFIG));
|
---|
844 | /*Codes_SRS_IOTHUBCLIENT_LL_02_006: [IoTHubClientCore_LL_Create shall populate a structure of type IOTHUBTRANSPORT_CONFIG with the information from config parameter and the previous DLIST and shall pass that to the underlying layer _Create function.]*/
|
---|
845 | lowerLayerConfig.upperConfig = client_config;
|
---|
846 | lowerLayerConfig.waitingToSend = &(result->waitingToSend);
|
---|
847 | lowerLayerConfig.auth_module_handle = result->authorization_module;
|
---|
848 | lowerLayerConfig.moduleId = module_id;
|
---|
849 |
|
---|
850 | setTransportProtocol(result, (TRANSPORT_PROVIDER*)client_config->protocol());
|
---|
851 | if ((result->transportHandle = result->IoTHubTransport_Create(&lowerLayerConfig, &transport_cb, result)) == NULL)
|
---|
852 | {
|
---|
853 | /*Codes_SRS_IOTHUBCLIENT_LL_02_007: [If the underlaying layer _Create function fails them IoTHubClientCore_LL_Create shall fail and return NULL.] */
|
---|
854 | LogError("underlying transport failed");
|
---|
855 | destroy_blob_upload_module(result);
|
---|
856 | destroy_module_method_module(result);
|
---|
857 | tickcounter_destroy(result->tickCounter);
|
---|
858 | IoTHubClient_Auth_Destroy(result->authorization_module);
|
---|
859 | STRING_delete(product_info);
|
---|
860 | free(result);
|
---|
861 | result = NULL;
|
---|
862 | }
|
---|
863 | else
|
---|
864 | {
|
---|
865 | /*Codes_SRS_IOTHUBCLIENT_LL_02_008: [Otherwise, IoTHubClientCore_LL_Create shall succeed and return a non-NULL handle.] */
|
---|
866 | result->isSharedTransport = false;
|
---|
867 | config = client_config;
|
---|
868 | }
|
---|
869 | }
|
---|
870 | else
|
---|
871 | {
|
---|
872 | STRING_HANDLE transport_hostname = NULL;
|
---|
873 |
|
---|
874 | result->transportHandle = device_config->transportHandle;
|
---|
875 | setTransportProtocol(result, (TRANSPORT_PROVIDER*)device_config->protocol());
|
---|
876 |
|
---|
877 | if (result->IoTHubTransport_SetCallbackContext(result->transportHandle, result) != 0)
|
---|
878 | {
|
---|
879 | LogError("unable to set transport callbacks");
|
---|
880 | IoTHubClient_Auth_Destroy(result->authorization_module);
|
---|
881 | STRING_delete(product_info);
|
---|
882 | free(result);
|
---|
883 | result = NULL;
|
---|
884 | }
|
---|
885 | else if ((transport_hostname = result->IoTHubTransport_GetHostname(result->transportHandle)) == NULL)
|
---|
886 | {
|
---|
887 | /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClientCore_LL_CreateWithTransport shall fail and return NULL. ]*/
|
---|
888 | LogError("unable to determine the transport IoTHub name");
|
---|
889 | IoTHubClient_Auth_Destroy(result->authorization_module);
|
---|
890 | STRING_delete(product_info);
|
---|
891 | free(result);
|
---|
892 | result = NULL;
|
---|
893 | }
|
---|
894 | else
|
---|
895 | {
|
---|
896 | const char* hostname = STRING_c_str(transport_hostname);
|
---|
897 | /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClientCore_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/
|
---|
898 | /*the first '.' says where the iothubname finishes*/
|
---|
899 | const char* whereIsDot = strchr(hostname, '.');
|
---|
900 | if (whereIsDot == NULL)
|
---|
901 | {
|
---|
902 | /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClientCore_LL_CreateWithTransport shall fail and return NULL. ]*/
|
---|
903 | LogError("unable to determine the IoTHub name");
|
---|
904 | IoTHubClient_Auth_Destroy(result->authorization_module);
|
---|
905 | STRING_delete(product_info);
|
---|
906 | free(result);
|
---|
907 | result = NULL;
|
---|
908 | }
|
---|
909 | else
|
---|
910 | {
|
---|
911 | size_t suffix_len = strlen(whereIsDot);
|
---|
912 | /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClientCore_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/
|
---|
913 | IoTHubName = (char*)malloc(whereIsDot - hostname + 1);
|
---|
914 | if (IoTHubName == NULL)
|
---|
915 | {
|
---|
916 | /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClientCore_LL_CreateWithTransport shall fail and return NULL. ]*/
|
---|
917 | LogError("unable to malloc");
|
---|
918 | IoTHubClient_Auth_Destroy(result->authorization_module);
|
---|
919 | STRING_delete(product_info);
|
---|
920 | free(result);
|
---|
921 | result = NULL;
|
---|
922 | }
|
---|
923 | else if ((IoTHubSuffix = (char*)malloc(suffix_len + 1)) == NULL)
|
---|
924 | {
|
---|
925 | /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClientCore_LL_CreateWithTransport shall fail and return NULL. ]*/
|
---|
926 | LogError("unable to malloc");
|
---|
927 | IoTHubClient_Auth_Destroy(result->authorization_module);
|
---|
928 | STRING_delete(product_info);
|
---|
929 | free(result);
|
---|
930 | result = NULL;
|
---|
931 | }
|
---|
932 | else
|
---|
933 | {
|
---|
934 | memset(IoTHubName, 0, whereIsDot - hostname + 1);
|
---|
935 | (void)memcpy(IoTHubName, hostname, whereIsDot - hostname);
|
---|
936 | (void)strcpy(IoTHubSuffix, whereIsDot+1);
|
---|
937 |
|
---|
938 | actual_config.deviceId = device_config->deviceId;
|
---|
939 | actual_config.deviceKey = device_config->deviceKey;
|
---|
940 | actual_config.deviceSasToken = device_config->deviceSasToken;
|
---|
941 | actual_config.iotHubName = IoTHubName;
|
---|
942 | actual_config.iotHubSuffix = IoTHubSuffix;
|
---|
943 | actual_config.protocol = NULL; /*irrelevant to IoTHubClientCore_LL_UploadToBlob*/
|
---|
944 | actual_config.protocolGatewayHostName = NULL; /*irrelevant to IoTHubClientCore_LL_UploadToBlob*/
|
---|
945 |
|
---|
946 | config = &actual_config;
|
---|
947 |
|
---|
948 | /*Codes_SRS_IOTHUBCLIENT_LL_02_008: [Otherwise, IoTHubClientCore_LL_Create shall succeed and return a non-NULL handle.] */
|
---|
949 | result->isSharedTransport = true;
|
---|
950 | }
|
---|
951 | }
|
---|
952 | }
|
---|
953 | STRING_delete(transport_hostname);
|
---|
954 | }
|
---|
955 | }
|
---|
956 | if (result != NULL)
|
---|
957 | {
|
---|
958 | if (create_blob_upload_module(result, config) != 0)
|
---|
959 | {
|
---|
960 | LogError("unable to create blob upload");
|
---|
961 | // Codes_SRS_IOTHUBCLIENT_LL_09_010: [ If any failure occurs `IoTHubClientCore_LL_Create` shall destroy the `transportHandle` only if it has created it ]
|
---|
962 | if (!result->isSharedTransport)
|
---|
963 | {
|
---|
964 | result->IoTHubTransport_Destroy(result->transportHandle);
|
---|
965 | }
|
---|
966 | destroy_blob_upload_module(result);
|
---|
967 | IoTHubClient_Auth_Destroy(result->authorization_module);
|
---|
968 | STRING_delete(product_info);
|
---|
969 | free(result);
|
---|
970 | result = NULL;
|
---|
971 | }
|
---|
972 | else if ((module_id != NULL) && create_edge_handle(result, config, module_id) != 0)
|
---|
973 | {
|
---|
974 | LogError("unable to create module method handle");
|
---|
975 | if (!result->isSharedTransport)
|
---|
976 | {
|
---|
977 | result->IoTHubTransport_Destroy(result->transportHandle);
|
---|
978 | }
|
---|
979 | destroy_blob_upload_module(result);
|
---|
980 | IoTHubClient_Auth_Destroy(result->authorization_module);
|
---|
981 | STRING_delete(product_info);
|
---|
982 | free(result);
|
---|
983 | result = NULL;
|
---|
984 | }
|
---|
985 | else
|
---|
986 | {
|
---|
987 | if ((result->tickCounter = tickcounter_create()) == NULL)
|
---|
988 | {
|
---|
989 | LogError("unable to get a tickcounter");
|
---|
990 | // Codes_SRS_IOTHUBCLIENT_LL_09_010: [ If any failure occurs `IoTHubClientCore_LL_Create` shall destroy the `transportHandle` only if it has created it ]
|
---|
991 | if (!result->isSharedTransport)
|
---|
992 | {
|
---|
993 | result->IoTHubTransport_Destroy(result->transportHandle);
|
---|
994 | }
|
---|
995 | destroy_blob_upload_module(result);
|
---|
996 | destroy_module_method_module(result);
|
---|
997 | IoTHubClient_Auth_Destroy(result->authorization_module);
|
---|
998 | STRING_delete(product_info);
|
---|
999 | free(result);
|
---|
1000 | result = NULL;
|
---|
1001 | }
|
---|
1002 | else
|
---|
1003 | {
|
---|
1004 | /*Codes_SRS_IOTHUBCLIENT_LL_02_004: [Otherwise IoTHubClientCore_LL_Create shall initialize a new DLIST (further called "waitingToSend") containing records with fields of the following types: IOTHUB_MESSAGE_HANDLE, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, void*.]*/
|
---|
1005 | DList_InitializeListHead(&(result->waitingToSend));
|
---|
1006 | DList_InitializeListHead(&(result->iot_msg_queue));
|
---|
1007 | DList_InitializeListHead(&(result->iot_ack_queue));
|
---|
1008 | result->messageCallback.type = CALLBACK_TYPE_NONE;
|
---|
1009 | result->lastMessageReceiveTime = INDEFINITE_TIME;
|
---|
1010 | result->data_msg_id = 1;
|
---|
1011 | result->product_info = product_info;
|
---|
1012 |
|
---|
1013 | IOTHUB_DEVICE_CONFIG deviceConfig;
|
---|
1014 | deviceConfig.deviceId = config->deviceId;
|
---|
1015 | deviceConfig.deviceKey = config->deviceKey;
|
---|
1016 | deviceConfig.deviceSasToken = config->deviceSasToken;
|
---|
1017 | deviceConfig.authorization_module = result->authorization_module;
|
---|
1018 | deviceConfig.moduleId = module_id;
|
---|
1019 |
|
---|
1020 | /*Codes_SRS_IOTHUBCLIENT_LL_17_008: [IoTHubClientCore_LL_Create shall call the transport _Register function with a populated structure of type IOTHUB_DEVICE_CONFIG and waitingToSend list.] */
|
---|
1021 | if ((result->deviceHandle = result->IoTHubTransport_Register(result->transportHandle, &deviceConfig, &(result->waitingToSend))) == NULL)
|
---|
1022 | {
|
---|
1023 | LogError("Registering device in transport failed");
|
---|
1024 | IoTHubClient_Auth_Destroy(result->authorization_module);
|
---|
1025 | // Codes_SRS_IOTHUBCLIENT_LL_09_010: [ If any failure occurs `IoTHubClientCore_LL_Create` shall destroy the `transportHandle` only if it has created it ]
|
---|
1026 | if (!result->isSharedTransport)
|
---|
1027 | {
|
---|
1028 | result->IoTHubTransport_Destroy(result->transportHandle);
|
---|
1029 | }
|
---|
1030 | destroy_blob_upload_module(result);
|
---|
1031 | destroy_module_method_module(result);
|
---|
1032 | tickcounter_destroy(result->tickCounter);
|
---|
1033 | STRING_delete(product_info);
|
---|
1034 | free(result);
|
---|
1035 | result = NULL;
|
---|
1036 | }
|
---|
1037 | else
|
---|
1038 | {
|
---|
1039 | /*Codes_SRS_IOTHUBCLIENT_LL_02_042: [ By default, messages shall not timeout. ]*/
|
---|
1040 | result->currentMessageTimeout = 0;
|
---|
1041 | result->current_device_twin_timeout = 0;
|
---|
1042 |
|
---|
1043 | result->diagnostic_setting.currentMessageNumber = 0;
|
---|
1044 | result->diagnostic_setting.diagSamplingPercentage = 0;
|
---|
1045 | /*Codes_SRS_IOTHUBCLIENT_LL_25_124: [ `IoTHubClientCore_LL_Create` shall set the default retry policy as Exponential backoff with jitter and if succeed and return a `non-NULL` handle. ]*/
|
---|
1046 | if (IoTHubClientCore_LL_SetRetryPolicy(result, IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER, 0) != IOTHUB_CLIENT_OK)
|
---|
1047 | {
|
---|
1048 | LogError("Setting default retry policy in transport failed");
|
---|
1049 | result->IoTHubTransport_Unregister(result->deviceHandle);
|
---|
1050 | IoTHubClient_Auth_Destroy(result->authorization_module);
|
---|
1051 | // Codes_SRS_IOTHUBCLIENT_LL_09_010: [ If any failure occurs `IoTHubClientCore_LL_Create` shall destroy the `transportHandle` only if it has created it ]
|
---|
1052 | if (!result->isSharedTransport)
|
---|
1053 | {
|
---|
1054 | result->IoTHubTransport_Destroy(result->transportHandle);
|
---|
1055 | }
|
---|
1056 | destroy_blob_upload_module(result);
|
---|
1057 | destroy_module_method_module(result);
|
---|
1058 | tickcounter_destroy(result->tickCounter);
|
---|
1059 | STRING_delete(product_info);
|
---|
1060 | free(result);
|
---|
1061 | result = NULL;
|
---|
1062 | }
|
---|
1063 | }
|
---|
1064 | }
|
---|
1065 | }
|
---|
1066 | }
|
---|
1067 | if (IoTHubName)
|
---|
1068 | {
|
---|
1069 | free(IoTHubName);
|
---|
1070 | }
|
---|
1071 | if (IoTHubSuffix)
|
---|
1072 | {
|
---|
1073 | free(IoTHubSuffix);
|
---|
1074 | }
|
---|
1075 | }
|
---|
1076 | }
|
---|
1077 | return result;
|
---|
1078 | }
|
---|
1079 |
|
---|
1080 | static uint32_t get_next_item_id(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData)
|
---|
1081 | {
|
---|
1082 | if (handleData->data_msg_id+1 >= UINT32_MAX)
|
---|
1083 | {
|
---|
1084 | handleData->data_msg_id = 1;
|
---|
1085 | }
|
---|
1086 | else
|
---|
1087 | {
|
---|
1088 | handleData->data_msg_id++;
|
---|
1089 | }
|
---|
1090 | return handleData->data_msg_id;
|
---|
1091 | }
|
---|
1092 |
|
---|
1093 | static IOTHUB_DEVICE_TWIN* dev_twin_data_create(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, uint32_t id, const unsigned char* reportedState, size_t size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reportedStateCallback, void* userContextCallback)
|
---|
1094 | {
|
---|
1095 | IOTHUB_DEVICE_TWIN* result = (IOTHUB_DEVICE_TWIN*)malloc(sizeof(IOTHUB_DEVICE_TWIN) );
|
---|
1096 | if (result != NULL)
|
---|
1097 | {
|
---|
1098 | result->report_data_handle = CONSTBUFFER_Create(reportedState, size);
|
---|
1099 | if (result->report_data_handle == NULL)
|
---|
1100 | {
|
---|
1101 | LogError("Failure allocating reported state data");
|
---|
1102 | free(result);
|
---|
1103 | result = NULL;
|
---|
1104 | }
|
---|
1105 | else
|
---|
1106 | {
|
---|
1107 | result->item_id = id;
|
---|
1108 | result->ms_timesOutAfter = 0;
|
---|
1109 | result->context = userContextCallback;
|
---|
1110 | result->reported_state_callback = reportedStateCallback;
|
---|
1111 | result->client_handle = handleData;
|
---|
1112 | result->device_handle = handleData->deviceHandle;
|
---|
1113 | }
|
---|
1114 | }
|
---|
1115 | else
|
---|
1116 | {
|
---|
1117 | LogError("Failure allocating device twin information");
|
---|
1118 | }
|
---|
1119 | return result;
|
---|
1120 | }
|
---|
1121 |
|
---|
1122 | static void on_get_device_twin_completed(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* userContextCallback)
|
---|
1123 | {
|
---|
1124 | if (userContextCallback == NULL)
|
---|
1125 | {
|
---|
1126 | LogError("Invalid argument (userContextCallback=NULL)");
|
---|
1127 | }
|
---|
1128 | else
|
---|
1129 | {
|
---|
1130 | GET_TWIN_CONTEXT* getTwinCtx = (GET_TWIN_CONTEXT*)userContextCallback;
|
---|
1131 |
|
---|
1132 | getTwinCtx->callback(update_state, payLoad, size, getTwinCtx->context);
|
---|
1133 |
|
---|
1134 | free(getTwinCtx);
|
---|
1135 | }
|
---|
1136 | }
|
---|
1137 |
|
---|
1138 | static void delete_event(IOTHUB_EVENT_CALLBACK* event_callback)
|
---|
1139 | {
|
---|
1140 | STRING_delete(event_callback->inputName);
|
---|
1141 | free(event_callback->userContextCallbackEx);
|
---|
1142 | free(event_callback);
|
---|
1143 | }
|
---|
1144 |
|
---|
1145 | static void delete_event_callback(const void* item, const void* action_context, bool* continue_processing)
|
---|
1146 | {
|
---|
1147 | (void)action_context;
|
---|
1148 | delete_event((IOTHUB_EVENT_CALLBACK*)item);
|
---|
1149 | *continue_processing = true;
|
---|
1150 | }
|
---|
1151 |
|
---|
1152 | static void delete_event_callback_list(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData)
|
---|
1153 | {
|
---|
1154 | if (handleData->event_callbacks != NULL)
|
---|
1155 | {
|
---|
1156 | singlylinkedlist_foreach(handleData->event_callbacks, delete_event_callback, NULL);
|
---|
1157 | singlylinkedlist_destroy(handleData->event_callbacks);
|
---|
1158 | handleData->event_callbacks = NULL;
|
---|
1159 | }
|
---|
1160 | }
|
---|
1161 |
|
---|
1162 |
|
---|
1163 | IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientCore_LL_CreateFromDeviceAuth(const char* iothub_uri, const char* device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
|
---|
1164 | {
|
---|
1165 | IOTHUB_CLIENT_CORE_LL_HANDLE result;
|
---|
1166 | if (iothub_uri == NULL || protocol == NULL || device_id == NULL)
|
---|
1167 | {
|
---|
1168 | LogError("Input parameter is NULL: iothub_uri: %p protocol: %p device_id: %p", iothub_uri, protocol, device_id);
|
---|
1169 | result = NULL;
|
---|
1170 | }
|
---|
1171 | else
|
---|
1172 | {
|
---|
1173 | #ifdef USE_PROV_MODULE
|
---|
1174 | IOTHUB_CLIENT_CONFIG* config = (IOTHUB_CLIENT_CONFIG*)malloc(sizeof(IOTHUB_CLIENT_CONFIG));
|
---|
1175 | if (config == NULL)
|
---|
1176 | {
|
---|
1177 | /* Codes_SRS_IOTHUBCLIENT_LL_12_012: [If the allocation failed IoTHubClientCore_LL_CreateFromConnectionString returns NULL] */
|
---|
1178 | LogError("Malloc failed");
|
---|
1179 | result = NULL;
|
---|
1180 | }
|
---|
1181 | else
|
---|
1182 | {
|
---|
1183 | const char* iterator;
|
---|
1184 | const char* initial;
|
---|
1185 | char* iothub_name = NULL;
|
---|
1186 | char* iothub_suffix = NULL;
|
---|
1187 |
|
---|
1188 | memset(config, 0, sizeof(IOTHUB_CLIENT_CONFIG));
|
---|
1189 | config->protocol = protocol;
|
---|
1190 | config->deviceId = device_id;
|
---|
1191 |
|
---|
1192 | // Find the iothub suffix
|
---|
1193 | initial = iterator = iothub_uri;
|
---|
1194 | while (iterator != NULL && *iterator != '\0')
|
---|
1195 | {
|
---|
1196 | if (*iterator == '.')
|
---|
1197 | {
|
---|
1198 | size_t length = iterator - initial;
|
---|
1199 | iothub_name = (char*)malloc(length + 1);
|
---|
1200 | if (iothub_name != NULL)
|
---|
1201 | {
|
---|
1202 | memset(iothub_name, 0, length + 1);
|
---|
1203 | memcpy(iothub_name, initial, length);
|
---|
1204 | config->iotHubName = iothub_name;
|
---|
1205 |
|
---|
1206 | length = strlen(initial) - length - 1;
|
---|
1207 | iothub_suffix = (char*)malloc(length + 1);
|
---|
1208 | if (iothub_suffix != NULL)
|
---|
1209 | {
|
---|
1210 | memset(iothub_suffix, 0, length + 1);
|
---|
1211 | memcpy(iothub_suffix, iterator + 1, length);
|
---|
1212 | config->iotHubSuffix = iothub_suffix;
|
---|
1213 | break;
|
---|
1214 | }
|
---|
1215 | else
|
---|
1216 | {
|
---|
1217 | LogError("Failed to allocate iothub suffix");
|
---|
1218 | free(iothub_name);
|
---|
1219 | iothub_name = NULL;
|
---|
1220 | result = NULL;
|
---|
1221 | }
|
---|
1222 | }
|
---|
1223 | else
|
---|
1224 | {
|
---|
1225 | LogError("Failed to allocate iothub name");
|
---|
1226 | result = NULL;
|
---|
1227 | }
|
---|
1228 | }
|
---|
1229 | iterator++;
|
---|
1230 | }
|
---|
1231 |
|
---|
1232 | if (config->iotHubName == NULL || config->iotHubSuffix == NULL)
|
---|
1233 | {
|
---|
1234 | LogError("initialize iothub client");
|
---|
1235 | result = NULL;
|
---|
1236 | }
|
---|
1237 | else
|
---|
1238 | {
|
---|
1239 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = initialize_iothub_client(config, NULL, true, NULL);
|
---|
1240 | if (handleData == NULL)
|
---|
1241 | {
|
---|
1242 | LogError("initialize iothub client");
|
---|
1243 | result = NULL;
|
---|
1244 | }
|
---|
1245 | else
|
---|
1246 | {
|
---|
1247 | result = handleData;
|
---|
1248 | }
|
---|
1249 | }
|
---|
1250 |
|
---|
1251 | free(iothub_name);
|
---|
1252 | free(iothub_suffix);
|
---|
1253 | free(config);
|
---|
1254 | }
|
---|
1255 | #else
|
---|
1256 | LogError("HSM module is not included");
|
---|
1257 | result = NULL;
|
---|
1258 | #endif
|
---|
1259 | }
|
---|
1260 | return result;
|
---|
1261 | }
|
---|
1262 |
|
---|
1263 | IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientCore_LL_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
|
---|
1264 | {
|
---|
1265 | IOTHUB_CLIENT_CORE_LL_HANDLE result;
|
---|
1266 |
|
---|
1267 | /* Codes_SRS_IOTHUBCLIENT_LL_12_003: [IoTHubClientCore_LL_CreateFromConnectionString shall verify the input parameter and if it is NULL then return NULL] */
|
---|
1268 | if (connectionString == NULL)
|
---|
1269 | {
|
---|
1270 | LogError("Input parameter is NULL: connectionString");
|
---|
1271 | result = NULL;
|
---|
1272 | }
|
---|
1273 | else if (protocol == NULL)
|
---|
1274 | {
|
---|
1275 | LogError("Input parameter is NULL: protocol");
|
---|
1276 | result = NULL;
|
---|
1277 | }
|
---|
1278 | else
|
---|
1279 | {
|
---|
1280 | /* Codes_SRS_IOTHUBCLIENT_LL_12_004: [IoTHubClientCore_LL_CreateFromConnectionString shall allocate IOTHUB_CLIENT_CONFIG structure] */
|
---|
1281 | IOTHUB_CLIENT_CONFIG* config = (IOTHUB_CLIENT_CONFIG*) malloc(sizeof(IOTHUB_CLIENT_CONFIG));
|
---|
1282 | if (config == NULL)
|
---|
1283 | {
|
---|
1284 | /* Codes_SRS_IOTHUBCLIENT_LL_12_012: [If the allocation failed IoTHubClientCore_LL_CreateFromConnectionString returns NULL] */
|
---|
1285 | LogError("Malloc failed");
|
---|
1286 | result = NULL;
|
---|
1287 | }
|
---|
1288 | else
|
---|
1289 | {
|
---|
1290 | STRING_TOKENIZER_HANDLE tokenizer1 = NULL;
|
---|
1291 | STRING_HANDLE connString = NULL;
|
---|
1292 | STRING_HANDLE tokenString = NULL;
|
---|
1293 | STRING_HANDLE valueString = NULL;
|
---|
1294 | STRING_HANDLE hostNameString = NULL;
|
---|
1295 | STRING_HANDLE hostSuffixString = NULL;
|
---|
1296 | STRING_HANDLE deviceIdString = NULL;
|
---|
1297 | STRING_HANDLE deviceKeyString = NULL;
|
---|
1298 | STRING_HANDLE deviceSasTokenString = NULL;
|
---|
1299 | STRING_HANDLE protocolGateway = NULL;
|
---|
1300 | STRING_HANDLE moduleId = NULL;
|
---|
1301 |
|
---|
1302 | memset(config, 0, sizeof(*config));
|
---|
1303 | config->protocol = protocol;
|
---|
1304 |
|
---|
1305 | /* Codes_SRS_IOTHUBCLIENT_LL_04_002: [If it does not, it shall pass the protocolGatewayHostName NULL.] */
|
---|
1306 | config->protocolGatewayHostName = NULL;
|
---|
1307 |
|
---|
1308 | if ((connString = STRING_construct(connectionString)) == NULL)
|
---|
1309 | {
|
---|
1310 | LogError("Error constructing connectiong String");
|
---|
1311 | result = NULL;
|
---|
1312 | }
|
---|
1313 | else if ((tokenizer1 = STRING_TOKENIZER_create(connString)) == NULL)
|
---|
1314 | {
|
---|
1315 | LogError("Error creating Tokenizer");
|
---|
1316 | result = NULL;
|
---|
1317 | }
|
---|
1318 | else if ((tokenString = STRING_new()) == NULL)
|
---|
1319 | {
|
---|
1320 | LogError("Error creating Token String");
|
---|
1321 | result = NULL;
|
---|
1322 | }
|
---|
1323 | else if ((valueString = STRING_new()) == NULL)
|
---|
1324 | {
|
---|
1325 | LogError("Error creating Value String");
|
---|
1326 | result = NULL;
|
---|
1327 | }
|
---|
1328 | else if ((hostNameString = STRING_new()) == NULL)
|
---|
1329 | {
|
---|
1330 | LogError("Error creating HostName String");
|
---|
1331 | result = NULL;
|
---|
1332 | }
|
---|
1333 | else if ((hostSuffixString = STRING_new()) == NULL)
|
---|
1334 | {
|
---|
1335 | LogError("Error creating HostSuffix String");
|
---|
1336 | result = NULL;
|
---|
1337 | }
|
---|
1338 | /* Codes_SRS_IOTHUBCLIENT_LL_12_005: [IoTHubClientCore_LL_CreateFromConnectionString shall try to parse the connectionString input parameter for the following structure: "Key1=value1;key2=value2;key3=value3..."] */
|
---|
1339 | /* Codes_SRS_IOTHUBCLIENT_LL_12_006: [IoTHubClientCore_LL_CreateFromConnectionString shall verify the existence of the following Key/Value pairs in the connection string: HostName, DeviceId, SharedAccessKey, SharedAccessSignature or x509] */
|
---|
1340 | else
|
---|
1341 | {
|
---|
1342 | int isx509found = 0;
|
---|
1343 | bool use_provisioning = false;
|
---|
1344 | while ((STRING_TOKENIZER_get_next_token(tokenizer1, tokenString, "=") == 0))
|
---|
1345 | {
|
---|
1346 | if (STRING_TOKENIZER_get_next_token(tokenizer1, valueString, ";") != 0)
|
---|
1347 | {
|
---|
1348 | LogError("Tokenizer error");
|
---|
1349 | break;
|
---|
1350 | }
|
---|
1351 | else
|
---|
1352 | {
|
---|
1353 | if (tokenString != NULL)
|
---|
1354 | {
|
---|
1355 | /* Codes_SRS_IOTHUBCLIENT_LL_12_010: [IoTHubClientCore_LL_CreateFromConnectionString shall fill up the IOTHUB_CLIENT_CONFIG structure using the following mapping: iotHubName = Name, iotHubSuffix = Suffix, deviceId = DeviceId, deviceKey = SharedAccessKey or deviceSasToken = SharedAccessSignature] */
|
---|
1356 | const char* s_token = STRING_c_str(tokenString);
|
---|
1357 | if (strcmp(s_token, HOSTNAME_TOKEN) == 0)
|
---|
1358 | {
|
---|
1359 | /* Codes_SRS_IOTHUBCLIENT_LL_12_009: [IoTHubClientCore_LL_CreateFromConnectionString shall split the value of HostName to Name and Suffix using the first "." as a separator] */
|
---|
1360 | STRING_TOKENIZER_HANDLE tokenizer2 = NULL;
|
---|
1361 | if ((tokenizer2 = STRING_TOKENIZER_create(valueString)) == NULL)
|
---|
1362 | {
|
---|
1363 | LogError("Error creating Tokenizer");
|
---|
1364 | break;
|
---|
1365 | }
|
---|
1366 | else
|
---|
1367 | {
|
---|
1368 | /* Codes_SRS_IOTHUBCLIENT_LL_12_015: [If the string split failed, IoTHubClientCore_LL_CreateFromConnectionString returns NULL ] */
|
---|
1369 | if (STRING_TOKENIZER_get_next_token(tokenizer2, hostNameString, ".") != 0)
|
---|
1370 | {
|
---|
1371 | LogError("Tokenizer error");
|
---|
1372 | STRING_TOKENIZER_destroy(tokenizer2);
|
---|
1373 | break;
|
---|
1374 | }
|
---|
1375 | else
|
---|
1376 | {
|
---|
1377 | config->iotHubName = STRING_c_str(hostNameString);
|
---|
1378 | if (STRING_TOKENIZER_get_next_token(tokenizer2, hostSuffixString, ";") != 0)
|
---|
1379 | {
|
---|
1380 | LogError("Tokenizer error");
|
---|
1381 | STRING_TOKENIZER_destroy(tokenizer2);
|
---|
1382 | break;
|
---|
1383 | }
|
---|
1384 | else
|
---|
1385 | {
|
---|
1386 | config->iotHubSuffix = STRING_c_str(hostSuffixString);
|
---|
1387 | }
|
---|
1388 | }
|
---|
1389 | STRING_TOKENIZER_destroy(tokenizer2);
|
---|
1390 | }
|
---|
1391 | }
|
---|
1392 | else if (strcmp(s_token, DEVICEID_TOKEN) == 0)
|
---|
1393 | {
|
---|
1394 | deviceIdString = STRING_clone(valueString);
|
---|
1395 | if (deviceIdString != NULL)
|
---|
1396 | {
|
---|
1397 | config->deviceId = STRING_c_str(deviceIdString);
|
---|
1398 | }
|
---|
1399 | else
|
---|
1400 | {
|
---|
1401 | LogError("Failure cloning device id string");
|
---|
1402 | break;
|
---|
1403 | }
|
---|
1404 | }
|
---|
1405 | else if (strcmp(s_token, DEVICEKEY_TOKEN) == 0)
|
---|
1406 | {
|
---|
1407 | deviceKeyString = STRING_clone(valueString);
|
---|
1408 | if (deviceKeyString != NULL)
|
---|
1409 | {
|
---|
1410 | config->deviceKey = STRING_c_str(deviceKeyString);
|
---|
1411 | }
|
---|
1412 | else
|
---|
1413 | {
|
---|
1414 | LogError("Failure cloning device key string");
|
---|
1415 | break;
|
---|
1416 | }
|
---|
1417 | }
|
---|
1418 | else if (strcmp(s_token, DEVICESAS_TOKEN) == 0)
|
---|
1419 | {
|
---|
1420 | deviceSasTokenString = STRING_clone(valueString);
|
---|
1421 | if (deviceSasTokenString != NULL)
|
---|
1422 | {
|
---|
1423 | config->deviceSasToken = STRING_c_str(deviceSasTokenString);
|
---|
1424 | }
|
---|
1425 | else
|
---|
1426 | {
|
---|
1427 | LogError("Failure cloning device sasToken string");
|
---|
1428 | break;
|
---|
1429 | }
|
---|
1430 | }
|
---|
1431 | else if (strcmp(s_token, X509_TOKEN) == 0)
|
---|
1432 | {
|
---|
1433 | if (strcmp(STRING_c_str(valueString), X509_TOKEN_ONLY_ACCEPTABLE_VALUE) != 0)
|
---|
1434 | {
|
---|
1435 | LogError("x509 option has wrong value, the only acceptable one is \"true\"");
|
---|
1436 | break;
|
---|
1437 | }
|
---|
1438 | else
|
---|
1439 | {
|
---|
1440 | isx509found = 1;
|
---|
1441 | }
|
---|
1442 | }
|
---|
1443 | else if (strcmp(s_token, PROVISIONING_TOKEN) == 0)
|
---|
1444 | {
|
---|
1445 | if (strcmp(STRING_c_str(valueString), PROVISIONING_ACCEPTABLE_VALUE) != 0)
|
---|
1446 | {
|
---|
1447 | LogError("provisioning option has wrong value, the only acceptable one is \"true\"");
|
---|
1448 | break;
|
---|
1449 | }
|
---|
1450 | else
|
---|
1451 | {
|
---|
1452 | use_provisioning = 1;
|
---|
1453 | }
|
---|
1454 | }
|
---|
1455 |
|
---|
1456 | /* Codes_SRS_IOTHUBCLIENT_LL_04_001: [IoTHubClientCore_LL_CreateFromConnectionString shall verify the existence of key/value pair GatewayHostName. If it does exist it shall pass the value to IoTHubClientCore_LL_Create API.] */
|
---|
1457 | else if (strcmp(s_token, PROTOCOL_GATEWAY_HOST_TOKEN) == 0)
|
---|
1458 | {
|
---|
1459 | protocolGateway = STRING_clone(valueString);
|
---|
1460 | if (protocolGateway != NULL)
|
---|
1461 | {
|
---|
1462 | config->protocolGatewayHostName = STRING_c_str(protocolGateway);
|
---|
1463 | }
|
---|
1464 | else
|
---|
1465 | {
|
---|
1466 | LogError("Failure cloning protocol Gateway Name");
|
---|
1467 | break;
|
---|
1468 | }
|
---|
1469 | }
|
---|
1470 | /*Codes_SRS_IOTHUBCLIENT_LL_31_126: [IoTHubClient_LL_CreateFromConnectionString shall optionally parse ModuleId, if present.] */
|
---|
1471 | else if (strcmp(s_token, MODULE_ID_TOKEN) == 0)
|
---|
1472 | {
|
---|
1473 | moduleId = STRING_clone(valueString);
|
---|
1474 | if (moduleId == NULL)
|
---|
1475 | {
|
---|
1476 | LogError("Failure cloning moduleId string");
|
---|
1477 | break;
|
---|
1478 | }
|
---|
1479 | }
|
---|
1480 | else
|
---|
1481 | {
|
---|
1482 | // If we get an unknown token, log it to error stream but do not cause a fatal error.
|
---|
1483 | LogError("Unknown token <%s> in connection string. Ignoring error and continuing to parse", s_token);
|
---|
1484 | }
|
---|
1485 | }
|
---|
1486 | }
|
---|
1487 | }
|
---|
1488 | /* parsing is done - check the result */
|
---|
1489 | if (config->iotHubName == NULL)
|
---|
1490 | {
|
---|
1491 | LogError("iotHubName is not found");
|
---|
1492 | result = NULL;
|
---|
1493 | }
|
---|
1494 | else if (config->iotHubSuffix == NULL)
|
---|
1495 | {
|
---|
1496 | LogError("iotHubSuffix is not found");
|
---|
1497 | result = NULL;
|
---|
1498 | }
|
---|
1499 | else if (config->deviceId == NULL)
|
---|
1500 | {
|
---|
1501 | LogError("deviceId is not found");
|
---|
1502 | result = NULL;
|
---|
1503 | }
|
---|
1504 | else if (!(
|
---|
1505 | ((!use_provisioning && !isx509found) && (config->deviceSasToken == NULL) ^ (config->deviceKey == NULL)) ||
|
---|
1506 | ((use_provisioning || isx509found) && (config->deviceSasToken == NULL) && (config->deviceKey == NULL))
|
---|
1507 | ))
|
---|
1508 | {
|
---|
1509 | LogError("invalid combination of x509, provisioning, deviceSasToken and deviceKey");
|
---|
1510 | result = NULL;
|
---|
1511 | }
|
---|
1512 | else
|
---|
1513 | {
|
---|
1514 | /* Codes_SRS_IOTHUBCLIENT_LL_12_011: [IoTHubClientCore_LL_CreateFromConnectionString shall call into the IoTHubClientCore_LL_Create API with the current structure and returns with the return value of it] */
|
---|
1515 | result = initialize_iothub_client(config, NULL, use_provisioning, STRING_c_str(moduleId));
|
---|
1516 | if (result == NULL)
|
---|
1517 | {
|
---|
1518 | LogError("IoTHubClientCore_LL_Create failed");
|
---|
1519 | }
|
---|
1520 | else
|
---|
1521 | {
|
---|
1522 | /*return as is*/
|
---|
1523 | }
|
---|
1524 | }
|
---|
1525 | }
|
---|
1526 | if (deviceSasTokenString != NULL)
|
---|
1527 | STRING_delete(deviceSasTokenString);
|
---|
1528 | if (deviceKeyString != NULL)
|
---|
1529 | STRING_delete(deviceKeyString);
|
---|
1530 | if (deviceIdString != NULL)
|
---|
1531 | STRING_delete(deviceIdString);
|
---|
1532 | if (hostSuffixString != NULL)
|
---|
1533 | STRING_delete(hostSuffixString);
|
---|
1534 | if (hostNameString != NULL)
|
---|
1535 | STRING_delete(hostNameString);
|
---|
1536 | if (valueString != NULL)
|
---|
1537 | STRING_delete(valueString);
|
---|
1538 | if (tokenString != NULL)
|
---|
1539 | STRING_delete(tokenString);
|
---|
1540 | if (connString != NULL)
|
---|
1541 | STRING_delete(connString);
|
---|
1542 | if (protocolGateway != NULL)
|
---|
1543 | STRING_delete(protocolGateway);
|
---|
1544 | if (moduleId != NULL)
|
---|
1545 | STRING_delete(moduleId);
|
---|
1546 |
|
---|
1547 | if (tokenizer1 != NULL)
|
---|
1548 | STRING_TOKENIZER_destroy(tokenizer1);
|
---|
1549 |
|
---|
1550 | free(config);
|
---|
1551 | }
|
---|
1552 | }
|
---|
1553 | return result;
|
---|
1554 | }
|
---|
1555 |
|
---|
1556 | IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientCore_LL_CreateImpl(const IOTHUB_CLIENT_CONFIG* config, const char* module_id, bool use_dev_auth)
|
---|
1557 | {
|
---|
1558 | IOTHUB_CLIENT_CORE_LL_HANDLE result;
|
---|
1559 | /*Codes_SRS_IOTHUBCLIENT_LL_02_001: [IoTHubClientCore_LL_Create shall return NULL if config parameter is NULL or protocol field is NULL.]*/
|
---|
1560 | if(
|
---|
1561 | (config == NULL) ||
|
---|
1562 | (config->protocol == NULL)
|
---|
1563 | )
|
---|
1564 | {
|
---|
1565 | result = NULL;
|
---|
1566 | LogError("invalid configuration (NULL detected)");
|
---|
1567 | }
|
---|
1568 | else
|
---|
1569 | {
|
---|
1570 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = initialize_iothub_client(config, NULL, use_dev_auth, module_id);
|
---|
1571 | if (handleData == NULL)
|
---|
1572 | {
|
---|
1573 | LogError("initialize iothub client");
|
---|
1574 | result = NULL;
|
---|
1575 | }
|
---|
1576 | else
|
---|
1577 | {
|
---|
1578 | result = handleData;
|
---|
1579 | }
|
---|
1580 | }
|
---|
1581 |
|
---|
1582 | return result;
|
---|
1583 | }
|
---|
1584 |
|
---|
1585 | IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientCore_LL_Create(const IOTHUB_CLIENT_CONFIG* config)
|
---|
1586 | {
|
---|
1587 | return IoTHubClientCore_LL_CreateImpl(config, NULL, false);
|
---|
1588 | }
|
---|
1589 |
|
---|
1590 | #ifdef USE_EDGE_MODULES
|
---|
1591 | IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientCore_LL_CreateFromEnvironment(IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
|
---|
1592 | {
|
---|
1593 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* result;
|
---|
1594 | EDGE_ENVIRONMENT_VARIABLES edge_environment_variables;
|
---|
1595 |
|
---|
1596 | memset(&edge_environment_variables, 0, sizeof(edge_environment_variables));
|
---|
1597 |
|
---|
1598 | if (retrieve_edge_environment_variabes(&edge_environment_variables) != 0)
|
---|
1599 | {
|
---|
1600 | LogError("retrieve_edge_environment_variabes failed");
|
---|
1601 | result = NULL;
|
---|
1602 | }
|
---|
1603 | // The presence of a connection string environment variable means we use it, ignoring other settings
|
---|
1604 | else if (edge_environment_variables.connection_string != NULL)
|
---|
1605 | {
|
---|
1606 | if ((result = IoTHubClientCore_LL_CreateFromConnectionString(edge_environment_variables.connection_string, protocol)) == NULL)
|
---|
1607 | {
|
---|
1608 | LogError("IoTHubClientCore_LL_CreateFromConnectionString fails");
|
---|
1609 | }
|
---|
1610 | }
|
---|
1611 | else if (iothub_security_init(IOTHUB_SECURITY_TYPE_HTTP_EDGE) != 0)
|
---|
1612 | {
|
---|
1613 | LogError("iothub_security_init failed");
|
---|
1614 | result = NULL;
|
---|
1615 | }
|
---|
1616 | else
|
---|
1617 | {
|
---|
1618 | IOTHUB_CLIENT_CONFIG client_config;
|
---|
1619 |
|
---|
1620 | memset(&client_config, 0, sizeof(client_config));
|
---|
1621 | client_config.protocol = protocol;
|
---|
1622 | client_config.deviceId = edge_environment_variables.device_id;
|
---|
1623 | client_config.iotHubName = edge_environment_variables.iothub_name;
|
---|
1624 | client_config.iotHubSuffix = edge_environment_variables.iothub_suffix;
|
---|
1625 | client_config.protocolGatewayHostName = edge_environment_variables.gatewayhostname;
|
---|
1626 |
|
---|
1627 | if ((result = IoTHubClientCore_LL_CreateImpl(&client_config, edge_environment_variables.module_id, true)) == NULL)
|
---|
1628 | {
|
---|
1629 | LogError("IoTHubClientCore_LL_CreateImpl fails");
|
---|
1630 | }
|
---|
1631 | }
|
---|
1632 |
|
---|
1633 | if (result != NULL)
|
---|
1634 | {
|
---|
1635 | // Because the Edge Hub almost always use self-signed certificates, we need to specify which certificates to trust. We need to do
|
---|
1636 | // this regardless of how we created the underlying IOTHUB_CLIENT_CORE_LL_HANDLE_DATA.
|
---|
1637 | IOTHUB_CLIENT_RESULT setTrustResult;
|
---|
1638 | char* trustedCertificate = IoTHubClient_Auth_Get_TrustBundle(result->authorization_module, edge_environment_variables.ca_trusted_certificate_file);
|
---|
1639 |
|
---|
1640 | if (trustedCertificate == NULL)
|
---|
1641 | {
|
---|
1642 | LogError("IoTHubClient_Auth_Get_TrustBundle failed");
|
---|
1643 | IoTHubClientCore_LL_Destroy(result);
|
---|
1644 | result = NULL;
|
---|
1645 | }
|
---|
1646 | else if ((setTrustResult = IoTHubClientCore_LL_SetOption(result, OPTION_TRUSTED_CERT, trustedCertificate)) != IOTHUB_CLIENT_OK)
|
---|
1647 | {
|
---|
1648 | LogError("IoTHubClientCore_LL_SetOption failed, err = %d", setTrustResult);
|
---|
1649 | IoTHubClientCore_LL_Destroy(result);
|
---|
1650 | result = NULL;
|
---|
1651 | }
|
---|
1652 |
|
---|
1653 | free(trustedCertificate);
|
---|
1654 | }
|
---|
1655 |
|
---|
1656 | free(edge_environment_variables.iothub_buffer);
|
---|
1657 | return result;
|
---|
1658 | }
|
---|
1659 | #endif
|
---|
1660 |
|
---|
1661 |
|
---|
1662 | IOTHUB_CLIENT_CORE_LL_HANDLE IoTHubClientCore_LL_CreateWithTransport(const IOTHUB_CLIENT_DEVICE_CONFIG * config)
|
---|
1663 | {
|
---|
1664 | IOTHUB_CLIENT_CORE_LL_HANDLE result;
|
---|
1665 | /*Codes_SRS_IOTHUBCLIENT_LL_17_001: [IoTHubClientCore_LL_CreateWithTransport shall return NULL if config parameter is NULL, or protocol field is NULL or transportHandle is NULL.]*/
|
---|
1666 | if (
|
---|
1667 | (config == NULL) ||
|
---|
1668 | (config->protocol == NULL) ||
|
---|
1669 | (config->transportHandle == NULL) ||
|
---|
1670 | /*Codes_SRS_IOTHUBCLIENT_LL_02_098: [ IoTHubClientCore_LL_CreateWithTransport shall fail and return NULL if both config->deviceKey AND config->deviceSasToken are NULL. ]*/
|
---|
1671 | ((config->deviceKey == NULL) && (config->deviceSasToken == NULL))
|
---|
1672 | )
|
---|
1673 | {
|
---|
1674 | result = NULL;
|
---|
1675 | LogError("invalid configuration (NULL detected)");
|
---|
1676 | }
|
---|
1677 | else
|
---|
1678 | {
|
---|
1679 | result = initialize_iothub_client(NULL, config, false, NULL);
|
---|
1680 | }
|
---|
1681 | return result;
|
---|
1682 | }
|
---|
1683 |
|
---|
1684 | void IoTHubClientCore_LL_Destroy(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle)
|
---|
1685 | {
|
---|
1686 | /*Codes_SRS_IOTHUBCLIENT_LL_02_009: [IoTHubClientCore_LL_Destroy shall do nothing if parameter iotHubClientHandle is NULL.]*/
|
---|
1687 | if (iotHubClientHandle != NULL)
|
---|
1688 | {
|
---|
1689 | PDLIST_ENTRY unsend;
|
---|
1690 | /*Codes_SRS_IOTHUBCLIENT_LL_17_010: [IoTHubClientCore_LL_Destroy shall call the underlaying layer's _Unregister function] */
|
---|
1691 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
1692 | handleData->IoTHubTransport_Unregister(handleData->deviceHandle);
|
---|
1693 | if (handleData->isSharedTransport == false)
|
---|
1694 | {
|
---|
1695 | /*Codes_SRS_IOTHUBCLIENT_LL_02_010: [If iotHubClientHandle was not created by IoTHubClientCore_LL_CreateWithTransport, IoTHubClientCore_LL_Destroy shall call the underlaying layer's _Destroy function.] */
|
---|
1696 | handleData->IoTHubTransport_Destroy(handleData->transportHandle);
|
---|
1697 | }
|
---|
1698 | /*if any, remove the items currently not send*/
|
---|
1699 | while ((unsend = DList_RemoveHeadList(&(handleData->waitingToSend))) != &(handleData->waitingToSend))
|
---|
1700 | {
|
---|
1701 | IOTHUB_MESSAGE_LIST* temp = containingRecord(unsend, IOTHUB_MESSAGE_LIST, entry);
|
---|
1702 | /*Codes_SRS_IOTHUBCLIENT_LL_02_033: [Otherwise, IoTHubClientCore_LL_Destroy shall complete all the event message callbacks that are in the waitingToSend list with the result IOTHUB_CLIENT_CONFIRMATION_BECAUSE_DESTROY.] */
|
---|
1703 | if (temp->callback != NULL)
|
---|
1704 | {
|
---|
1705 | temp->callback(IOTHUB_CLIENT_CONFIRMATION_BECAUSE_DESTROY, temp->context);
|
---|
1706 | }
|
---|
1707 | IoTHubMessage_Destroy(temp->messageHandle);
|
---|
1708 | free(temp);
|
---|
1709 | }
|
---|
1710 |
|
---|
1711 | /* Codes_SRS_IOTHUBCLIENT_LL_07_007: [ IoTHubClientCore_LL_Destroy shall iterate the device twin queues and destroy any remaining items. ] */
|
---|
1712 | while ((unsend = DList_RemoveHeadList(&(handleData->iot_msg_queue))) != &(handleData->iot_msg_queue))
|
---|
1713 | {
|
---|
1714 | IOTHUB_DEVICE_TWIN* temp = containingRecord(unsend, IOTHUB_DEVICE_TWIN, entry);
|
---|
1715 | device_twin_data_destroy(temp);
|
---|
1716 | }
|
---|
1717 | while ((unsend = DList_RemoveHeadList(&(handleData->iot_ack_queue))) != &(handleData->iot_ack_queue))
|
---|
1718 | {
|
---|
1719 | IOTHUB_DEVICE_TWIN* temp = containingRecord(unsend, IOTHUB_DEVICE_TWIN, entry);
|
---|
1720 | device_twin_data_destroy(temp);
|
---|
1721 | }
|
---|
1722 |
|
---|
1723 | /* Codes_SRS_IOTHUBCLIENT_LL_31_141: [ IoTHubClient_LL_Destroy shall iterate registered callbacks for input queues and destroy any remaining items. ] */
|
---|
1724 | delete_event_callback_list(handleData);
|
---|
1725 |
|
---|
1726 | /*Codes_SRS_IOTHUBCLIENT_LL_17_011: [IoTHubClientCore_LL_Destroy shall free the resources allocated by IoTHubClient (if any).] */
|
---|
1727 | IoTHubClient_Auth_Destroy(handleData->authorization_module);
|
---|
1728 | tickcounter_destroy(handleData->tickCounter);
|
---|
1729 | #ifndef DONT_USE_UPLOADTOBLOB
|
---|
1730 | IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle);
|
---|
1731 | #endif
|
---|
1732 | #ifdef USE_EDGE_MODULES
|
---|
1733 | IoTHubClient_EdgeHandle_Destroy(handleData->methodHandle);
|
---|
1734 | #endif
|
---|
1735 | STRING_delete(handleData->product_info);
|
---|
1736 | free(handleData);
|
---|
1737 | }
|
---|
1738 | }
|
---|
1739 |
|
---|
1740 | /*Codes_SRS_IOTHUBCLIENT_LL_02_044: [ Messages already delivered to IoTHubClientCore_LL shall not have their timeouts modified by a new call to IoTHubClientCore_LL_SetOption. ]*/
|
---|
1741 | /*returns 0 on success, any other value is error*/
|
---|
1742 | static int attach_ms_timesOutAfter(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, IOTHUB_MESSAGE_LIST *newEntry)
|
---|
1743 | {
|
---|
1744 | int result;
|
---|
1745 | /*Codes_SRS_IOTHUBCLIENT_LL_02_043: [ Calling IoTHubClientCore_LL_SetOption with value set to "0" shall disable the timeout mechanism for all new messages. ]*/
|
---|
1746 | if (handleData->currentMessageTimeout == 0)
|
---|
1747 | {
|
---|
1748 | newEntry->ms_timesOutAfter = 0; /*do not timeout*/
|
---|
1749 | newEntry->message_timeout_value = 0;
|
---|
1750 | result = 0;
|
---|
1751 | }
|
---|
1752 | else
|
---|
1753 | {
|
---|
1754 | /*Codes_SRS_IOTHUBCLIENT_LL_02_039: [ "messageTimeout" - once IoTHubClientCore_LL_SendEventAsync is called the message shall timeout after value miliseconds. Value is a pointer to a tickcounter_ms_t. ]*/
|
---|
1755 | if (tickcounter_get_current_ms(handleData->tickCounter, &newEntry->ms_timesOutAfter) != 0)
|
---|
1756 | {
|
---|
1757 | result = MU_FAILURE;
|
---|
1758 | LogError("unable to get the current relative tickcount");
|
---|
1759 | }
|
---|
1760 | else
|
---|
1761 | {
|
---|
1762 | newEntry->message_timeout_value = handleData->currentMessageTimeout;
|
---|
1763 | result = 0;
|
---|
1764 | }
|
---|
1765 | }
|
---|
1766 | return result;
|
---|
1767 | }
|
---|
1768 |
|
---|
1769 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SendEventAsync(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
|
---|
1770 | {
|
---|
1771 | IOTHUB_CLIENT_RESULT result;
|
---|
1772 | /*Codes_SRS_IOTHUBCLIENT_LL_02_011: [IoTHubClientCore_LL_SendEventAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle or eventMessageHandle is NULL.]*/
|
---|
1773 | if (
|
---|
1774 | (iotHubClientHandle == NULL) ||
|
---|
1775 | (eventMessageHandle == NULL) ||
|
---|
1776 | /*Codes_SRS_IOTHUBCLIENT_LL_02_012: [IoTHubClientCore_LL_SendEventAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter eventConfirmationCallback is NULL and userContextCallback is not NULL.] */
|
---|
1777 | ((eventConfirmationCallback == NULL) && (userContextCallback != NULL))
|
---|
1778 | )
|
---|
1779 | {
|
---|
1780 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
1781 | LOG_ERROR_RESULT;
|
---|
1782 | }
|
---|
1783 | else
|
---|
1784 | {
|
---|
1785 | IOTHUB_MESSAGE_LIST *newEntry = (IOTHUB_MESSAGE_LIST*)malloc(sizeof(IOTHUB_MESSAGE_LIST));
|
---|
1786 | if (newEntry == NULL)
|
---|
1787 | {
|
---|
1788 | result = IOTHUB_CLIENT_ERROR;
|
---|
1789 | LOG_ERROR_RESULT;
|
---|
1790 | }
|
---|
1791 | else
|
---|
1792 | {
|
---|
1793 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
1794 |
|
---|
1795 | if (attach_ms_timesOutAfter(handleData, newEntry) != 0)
|
---|
1796 | {
|
---|
1797 | result = IOTHUB_CLIENT_ERROR;
|
---|
1798 | LOG_ERROR_RESULT;
|
---|
1799 | free(newEntry);
|
---|
1800 | }
|
---|
1801 | else
|
---|
1802 | {
|
---|
1803 | /*Codes_SRS_IOTHUBCLIENT_LL_02_013: [IoTHubClientCore_LL_SendEventAsync shall add the DLIST waitingToSend a new record cloning the information from eventMessageHandle, eventConfirmationCallback, userContextCallback.]*/
|
---|
1804 | if ((newEntry->messageHandle = IoTHubMessage_Clone(eventMessageHandle)) == NULL)
|
---|
1805 | {
|
---|
1806 | result = IOTHUB_CLIENT_ERROR;
|
---|
1807 | free(newEntry);
|
---|
1808 | LOG_ERROR_RESULT;
|
---|
1809 | }
|
---|
1810 | else if (IoTHubClient_Diagnostic_AddIfNecessary(&handleData->diagnostic_setting, newEntry->messageHandle) != 0)
|
---|
1811 | {
|
---|
1812 | /*Codes_SRS_IOTHUBCLIENT_LL_02_014: [If cloning and/or adding the information/diagnostic fails for any reason, IoTHubClientCore_LL_SendEventAsync shall fail and return IOTHUB_CLIENT_ERROR.] */
|
---|
1813 | result = IOTHUB_CLIENT_ERROR;
|
---|
1814 | IoTHubMessage_Destroy(newEntry->messageHandle);
|
---|
1815 | free(newEntry);
|
---|
1816 | LOG_ERROR_RESULT;
|
---|
1817 | }
|
---|
1818 | else
|
---|
1819 | {
|
---|
1820 | /*Codes_SRS_IOTHUBCLIENT_LL_02_013: [IoTHubClientCore_LL_SendEventAsync shall add the DLIST waitingToSend a new record cloning the information from eventMessageHandle, eventConfirmationCallback, userContextCallback.]*/
|
---|
1821 | newEntry->callback = eventConfirmationCallback;
|
---|
1822 | newEntry->context = userContextCallback;
|
---|
1823 | DList_InsertTailList(&(iotHubClientHandle->waitingToSend), &(newEntry->entry));
|
---|
1824 | /*Codes_SRS_IOTHUBCLIENT_LL_02_015: [Otherwise IoTHubClientCore_LL_SendEventAsync shall succeed and return IOTHUB_CLIENT_OK.] */
|
---|
1825 | result = IOTHUB_CLIENT_OK;
|
---|
1826 | }
|
---|
1827 | }
|
---|
1828 | }
|
---|
1829 | }
|
---|
1830 | return result;
|
---|
1831 | }
|
---|
1832 |
|
---|
1833 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetMessageCallback(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback, void* userContextCallback)
|
---|
1834 | {
|
---|
1835 | IOTHUB_CLIENT_RESULT result;
|
---|
1836 | if (iotHubClientHandle == NULL)
|
---|
1837 | {
|
---|
1838 | /*Codes_SRS_IOTHUBCLIENT_LL_02_016: [IoTHubClientCore_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.] */
|
---|
1839 | LogError("Invalid argument - iotHubClientHandle is NULL");
|
---|
1840 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
1841 | }
|
---|
1842 | else
|
---|
1843 | {
|
---|
1844 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
1845 | if (messageCallback == NULL)
|
---|
1846 | {
|
---|
1847 | if (handleData->messageCallback.type == CALLBACK_TYPE_NONE)
|
---|
1848 | {
|
---|
1849 | /*Codes_SRS_IOTHUBCLIENT_LL_10_010: [If parameter messageCallback is NULL and the _SetMessageCallback had not been called to subscribe for messages, then IoTHubClientCore_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR.] */
|
---|
1850 | LogError("not currently set to accept or process incoming messages.");
|
---|
1851 | result = IOTHUB_CLIENT_ERROR;
|
---|
1852 | }
|
---|
1853 | else if (handleData->messageCallback.type == CALLBACK_TYPE_ASYNC)
|
---|
1854 | {
|
---|
1855 | /*Codes_SRS_IOTHUBCLIENT_LL_10_010: [If parameter messageCallback is NULL and the _SetMessageCallback had not been called to subscribe for messages, then IoTHubClientCore_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR.] */
|
---|
1856 | LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetMessageCallback_Ex function.");
|
---|
1857 | result = IOTHUB_CLIENT_ERROR;
|
---|
1858 | }
|
---|
1859 | else
|
---|
1860 | {
|
---|
1861 | /*Codes_SRS_IOTHUBCLIENT_LL_02_019: [If parameter messageCallback is NULL then IoTHubClientCore_LL_SetMessageCallback shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */
|
---|
1862 | handleData->IoTHubTransport_Unsubscribe(handleData->deviceHandle);
|
---|
1863 | handleData->messageCallback.type = CALLBACK_TYPE_NONE;
|
---|
1864 | handleData->messageCallback.callbackSync = NULL;
|
---|
1865 | handleData->messageCallback.callbackAsync = NULL;
|
---|
1866 | handleData->messageCallback.userContextCallback = NULL;
|
---|
1867 | result = IOTHUB_CLIENT_OK;
|
---|
1868 | }
|
---|
1869 | }
|
---|
1870 | else
|
---|
1871 | {
|
---|
1872 | if (handleData->messageCallback.type == CALLBACK_TYPE_ASYNC)
|
---|
1873 | {
|
---|
1874 | /* Codes_SRS_IOTHUBCLIENT_LL_10_011: [If parameter messageCallback is non-NULL and the _SetMessageCallback_Ex had been used to susbscribe for messages, then IoTHubClientCore_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR.] */
|
---|
1875 | LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetMessageCallback_Ex function before subscribing with MessageCallback.");
|
---|
1876 | result = IOTHUB_CLIENT_ERROR;
|
---|
1877 | }
|
---|
1878 | else
|
---|
1879 | {
|
---|
1880 | if (handleData->IoTHubTransport_Subscribe(handleData->deviceHandle) == 0)
|
---|
1881 | {
|
---|
1882 | /*Codes_SRS_IOTHUBCLIENT_LL_02_017: [If parameter messageCallback is non-NULL then IoTHubClientCore_LL_SetMessageCallback shall call the underlying layer's _Subscribe function.]*/
|
---|
1883 | handleData->messageCallback.type = CALLBACK_TYPE_SYNC;
|
---|
1884 | handleData->messageCallback.callbackSync = messageCallback;
|
---|
1885 | handleData->messageCallback.userContextCallback = userContextCallback;
|
---|
1886 | result = IOTHUB_CLIENT_OK;
|
---|
1887 | }
|
---|
1888 | else
|
---|
1889 | {
|
---|
1890 | /*Codes_SRS_IOTHUBCLIENT_LL_02_018: [If the underlying layer's _Subscribe function fails, then IoTHubClientCore_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR. Otherwise IoTHubClientCore_LL_SetMessageCallback shall succeed and return IOTHUB_CLIENT_OK.]*/
|
---|
1891 | LogError("IoTHubTransport_Subscribe failed");
|
---|
1892 | handleData->messageCallback.type = CALLBACK_TYPE_NONE;
|
---|
1893 | handleData->messageCallback.callbackSync = NULL;
|
---|
1894 | handleData->messageCallback.callbackAsync = NULL;
|
---|
1895 | handleData->messageCallback.userContextCallback = NULL;
|
---|
1896 | result = IOTHUB_CLIENT_ERROR;
|
---|
1897 | }
|
---|
1898 | }
|
---|
1899 | }
|
---|
1900 | }
|
---|
1901 | return result;
|
---|
1902 | }
|
---|
1903 |
|
---|
1904 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetMessageCallback_Ex(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX messageCallback, void* userContextCallback)
|
---|
1905 | {
|
---|
1906 | IOTHUB_CLIENT_RESULT result;
|
---|
1907 | if (iotHubClientHandle == NULL)
|
---|
1908 | {
|
---|
1909 | /*Codes_SRS_IOTHUBCLIENT_LL_10_021: [IoTHubClientCore_LL_SetMessageCallback_Ex shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.]*/
|
---|
1910 | LogError("Invalid argument - iotHubClientHandle is NULL");
|
---|
1911 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
1912 | }
|
---|
1913 | else
|
---|
1914 | {
|
---|
1915 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
1916 | if (messageCallback == NULL)
|
---|
1917 | {
|
---|
1918 | if (handleData->messageCallback.type == CALLBACK_TYPE_NONE)
|
---|
1919 | {
|
---|
1920 | /*Codes_SRS_IOTHUBCLIENT_LL_10_018: [If parameter messageCallback is NULL and IoTHubClientCore_LL_SetMessageCallback_Ex had not been used to subscribe for messages, then IoTHubClientCore_LL_SetMessageCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR.] */
|
---|
1921 | LogError("not currently set to accept or process incoming messages.");
|
---|
1922 | result = IOTHUB_CLIENT_ERROR;
|
---|
1923 | }
|
---|
1924 | else if (handleData->messageCallback.type == CALLBACK_TYPE_SYNC)
|
---|
1925 | {
|
---|
1926 | /*Codes_SRS_IOTHUBCLIENT_LL_10_019: [If parameter messageCallback is NULL and IoTHubClientCore_LL_SetMessageCallback had been used to subscribe for messages, then IoTHubClientCore_LL_SetMessageCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR.] */
|
---|
1927 | LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetMessageCallback function.");
|
---|
1928 | result = IOTHUB_CLIENT_ERROR;
|
---|
1929 | }
|
---|
1930 | else
|
---|
1931 | {
|
---|
1932 | /*Codes_SRS_IOTHUBCLIENT_LL_10_023: [If parameter messageCallback is NULL then IoTHubClientCore_LL_SetMessageCallback_Ex shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */
|
---|
1933 | handleData->IoTHubTransport_Unsubscribe(handleData->deviceHandle);
|
---|
1934 | handleData->messageCallback.type = CALLBACK_TYPE_NONE;
|
---|
1935 | handleData->messageCallback.callbackSync = NULL;
|
---|
1936 | handleData->messageCallback.callbackAsync = NULL;
|
---|
1937 | handleData->messageCallback.userContextCallback = NULL;
|
---|
1938 | result = IOTHUB_CLIENT_OK;
|
---|
1939 | }
|
---|
1940 | }
|
---|
1941 | else
|
---|
1942 | {
|
---|
1943 | if (handleData->messageCallback.type == CALLBACK_TYPE_SYNC)
|
---|
1944 | {
|
---|
1945 | /*Codes_SRS_IOTHUBCLIENT_LL_10_020: [If parameter messageCallback is non-NULL, and IoTHubClientCore_LL_SetMessageCallback had been used to subscribe for messages, then IoTHubClientCore_LL_SetMessageCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR.] */
|
---|
1946 | LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_MessageCallbackEx function before subscribing with MessageCallback.");
|
---|
1947 | result = IOTHUB_CLIENT_ERROR;
|
---|
1948 | }
|
---|
1949 | else
|
---|
1950 | {
|
---|
1951 | if (handleData->IoTHubTransport_Subscribe(handleData->deviceHandle) == 0)
|
---|
1952 | {
|
---|
1953 | /*Codes_SRS_IOTHUBCLIENT_LL_10_024: [If parameter messageCallback is non-NULL then IoTHubClientCore_LL_SetMessageCallback_Ex shall call the underlying layer's _Subscribe function.]*/
|
---|
1954 | handleData->messageCallback.type = CALLBACK_TYPE_ASYNC;
|
---|
1955 | handleData->messageCallback.callbackAsync = messageCallback;
|
---|
1956 | handleData->messageCallback.userContextCallback = userContextCallback;
|
---|
1957 | result = IOTHUB_CLIENT_OK;
|
---|
1958 | }
|
---|
1959 | else
|
---|
1960 | {
|
---|
1961 | /*Codes_SRS_IOTHUBCLIENT_LL_10_025: [If the underlying layer's _Subscribe function fails, then IoTHubClientCore_LL_SetMessageCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR. Otherwise IoTHubClientCore_LL_SetMessageCallback_Ex shall succeed and return IOTHUB_CLIENT_OK.] */
|
---|
1962 | LogError("IoTHubTransport_Subscribe failed");
|
---|
1963 | handleData->messageCallback.type = CALLBACK_TYPE_NONE;
|
---|
1964 | handleData->messageCallback.callbackSync = NULL;
|
---|
1965 | handleData->messageCallback.callbackAsync = NULL;
|
---|
1966 | handleData->messageCallback.userContextCallback = NULL;
|
---|
1967 | result = IOTHUB_CLIENT_ERROR;
|
---|
1968 | }
|
---|
1969 | }
|
---|
1970 | }
|
---|
1971 | }
|
---|
1972 | return result;
|
---|
1973 | }
|
---|
1974 |
|
---|
1975 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SendMessageDisposition(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, MESSAGE_CALLBACK_INFO* message_data, IOTHUBMESSAGE_DISPOSITION_RESULT disposition)
|
---|
1976 | {
|
---|
1977 | IOTHUB_CLIENT_RESULT result;
|
---|
1978 | if ((iotHubClientHandle == NULL) || (message_data == NULL))
|
---|
1979 | {
|
---|
1980 | /*Codes_SRS_IOTHUBCLIENT_LL_10_026: [IoTHubClientCore_LL_SendMessageDisposition shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.]*/
|
---|
1981 | LogError("Invalid argument handle=%p, message=%p", iotHubClientHandle, message_data);
|
---|
1982 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
1983 | }
|
---|
1984 | else
|
---|
1985 | {
|
---|
1986 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
1987 | /*Codes_SRS_IOTHUBCLIENT_LL_10_027: [IoTHubClientCore_LL_SendMessageDisposition shall return the result from calling the underlying layer's _Send_Message_Disposition.]*/
|
---|
1988 | result = handleData->IoTHubTransport_SendMessageDisposition(message_data, disposition);
|
---|
1989 | }
|
---|
1990 | return result;
|
---|
1991 | }
|
---|
1992 |
|
---|
1993 | static void DoTimeouts(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData)
|
---|
1994 | {
|
---|
1995 | tickcounter_ms_t nowTick;
|
---|
1996 | if (tickcounter_get_current_ms(handleData->tickCounter, &nowTick) != 0)
|
---|
1997 | {
|
---|
1998 | LogError("unable to get the current ms, timeouts will not be processed");
|
---|
1999 | }
|
---|
2000 | else
|
---|
2001 | {
|
---|
2002 | DLIST_ENTRY* currentItemInWaitingToSend = handleData->waitingToSend.Flink;
|
---|
2003 | while (currentItemInWaitingToSend != &(handleData->waitingToSend)) /*while we are not at the end of the list*/
|
---|
2004 | {
|
---|
2005 | IOTHUB_MESSAGE_LIST* fullEntry = containingRecord(currentItemInWaitingToSend, IOTHUB_MESSAGE_LIST, entry);
|
---|
2006 | /*Codes_SRS_IOTHUBCLIENT_LL_02_041: [ If more than value miliseconds have passed since the call to IoTHubClientCore_LL_SendEventAsync then the message callback shall be called with a status code of IOTHUB_CLIENT_CONFIRMATION_TIMEOUT. ]*/
|
---|
2007 | if ((fullEntry->ms_timesOutAfter != 0) && ((nowTick - fullEntry->ms_timesOutAfter) > fullEntry->message_timeout_value))
|
---|
2008 | {
|
---|
2009 | PDLIST_ENTRY theNext = currentItemInWaitingToSend->Flink; /*need to save the next item, because the below operations are destructive*/
|
---|
2010 | DList_RemoveEntryList(currentItemInWaitingToSend);
|
---|
2011 | if (fullEntry->callback != NULL)
|
---|
2012 | {
|
---|
2013 | fullEntry->callback(IOTHUB_CLIENT_CONFIRMATION_MESSAGE_TIMEOUT, fullEntry->context);
|
---|
2014 | }
|
---|
2015 | IoTHubMessage_Destroy(fullEntry->messageHandle); /*because it has been cloned*/
|
---|
2016 | free(fullEntry);
|
---|
2017 | currentItemInWaitingToSend = theNext;
|
---|
2018 | }
|
---|
2019 | else
|
---|
2020 | {
|
---|
2021 | currentItemInWaitingToSend = currentItemInWaitingToSend->Flink;
|
---|
2022 | }
|
---|
2023 | }
|
---|
2024 | }
|
---|
2025 | }
|
---|
2026 |
|
---|
2027 | void IoTHubClientCore_LL_DoWork(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle)
|
---|
2028 | {
|
---|
2029 | /*Codes_SRS_IOTHUBCLIENT_LL_02_020: [If parameter iotHubClientHandle is NULL then IoTHubClientCore_LL_DoWork shall not perform any action.] */
|
---|
2030 | if (iotHubClientHandle != NULL)
|
---|
2031 | {
|
---|
2032 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2033 | DoTimeouts(handleData);
|
---|
2034 |
|
---|
2035 | /*Codes_SRS_IOTHUBCLIENT_LL_07_008: [ IoTHubClientCore_LL_DoWork shall iterate the message queue and execute the underlying transports IoTHubTransport_ProcessItem function for each item. ] */
|
---|
2036 | DLIST_ENTRY* client_item = handleData->iot_msg_queue.Flink;
|
---|
2037 | while (client_item != &(handleData->iot_msg_queue)) /*while we are not at the end of the list*/
|
---|
2038 | {
|
---|
2039 | PDLIST_ENTRY next_item = client_item->Flink;
|
---|
2040 |
|
---|
2041 | IOTHUB_DEVICE_TWIN* queue_data = containingRecord(client_item, IOTHUB_DEVICE_TWIN, entry);
|
---|
2042 | IOTHUB_IDENTITY_INFO identity_info;
|
---|
2043 | identity_info.device_twin = queue_data;
|
---|
2044 | IOTHUB_PROCESS_ITEM_RESULT process_results = handleData->IoTHubTransport_ProcessItem(handleData->transportHandle, IOTHUB_TYPE_DEVICE_TWIN, &identity_info);
|
---|
2045 | if (process_results == IOTHUB_PROCESS_CONTINUE || process_results == IOTHUB_PROCESS_NOT_CONNECTED)
|
---|
2046 | {
|
---|
2047 | /*Codes_SRS_IOTHUBCLIENT_LL_07_010: [ If 'IoTHubTransport_ProcessItem' returns IOTHUB_PROCESS_CONTINUE or IOTHUB_PROCESS_NOT_CONNECTED IoTHubClientCore_LL_DoWork shall continue on to call the underlaying layer's _DoWork function. ]*/
|
---|
2048 | break;
|
---|
2049 | }
|
---|
2050 | else
|
---|
2051 | {
|
---|
2052 | DList_RemoveEntryList(client_item);
|
---|
2053 | if (process_results == IOTHUB_PROCESS_OK)
|
---|
2054 | {
|
---|
2055 | /*Codes_SRS_IOTHUBCLIENT_LL_07_011: [ If 'IoTHubTransport_ProcessItem' returns IOTHUB_PROCESS_OK IoTHubClientCore_LL_DoWork shall add the IOTHUB_DEVICE_TWIN to the ack queue. ]*/
|
---|
2056 | DList_InsertTailList(&(iotHubClientHandle->iot_ack_queue), &(queue_data->entry));
|
---|
2057 | }
|
---|
2058 | else
|
---|
2059 | {
|
---|
2060 | /*Codes_SRS_IOTHUBCLIENT_LL_07_012: [ If 'IoTHubTransport_ProcessItem' returns any other value IoTHubClientCore_LL_DoWork shall destroy the IOTHUB_DEVICE_TWIN item. ]*/
|
---|
2061 | LogError("Failure queue processing item");
|
---|
2062 | device_twin_data_destroy(queue_data);
|
---|
2063 | }
|
---|
2064 | }
|
---|
2065 | // Move along to the next item
|
---|
2066 | client_item = next_item;
|
---|
2067 | }
|
---|
2068 |
|
---|
2069 | /*Codes_SRS_IOTHUBCLIENT_LL_02_021: [Otherwise, IoTHubClientCore_LL_DoWork shall invoke the underlaying layer's _DoWork function.]*/
|
---|
2070 | handleData->IoTHubTransport_DoWork(handleData->transportHandle);
|
---|
2071 | }
|
---|
2072 | }
|
---|
2073 |
|
---|
2074 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_GetSendStatus(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
|
---|
2075 | {
|
---|
2076 | IOTHUB_CLIENT_RESULT result;
|
---|
2077 |
|
---|
2078 | /* Codes_SRS_IOTHUBCLIENT_09_007: [IoTHubClient_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter] */
|
---|
2079 | if (iotHubClientHandle == NULL || iotHubClientStatus == NULL)
|
---|
2080 | {
|
---|
2081 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2082 | LOG_ERROR_RESULT;
|
---|
2083 | }
|
---|
2084 | else
|
---|
2085 | {
|
---|
2086 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2087 |
|
---|
2088 | /* Codes_SRS_IOTHUBCLIENT_09_008: [IoTHubClient_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there is currently no items to be sent] */
|
---|
2089 | /* Codes_SRS_IOTHUBCLIENT_09_009: [IoTHubClient_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently items to be sent] */
|
---|
2090 | result = handleData->IoTHubTransport_GetSendStatus(handleData->deviceHandle, iotHubClientStatus);
|
---|
2091 | }
|
---|
2092 |
|
---|
2093 | return result;
|
---|
2094 | }
|
---|
2095 |
|
---|
2096 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetConnectionStatusCallback(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK connectionStatusCallback, void * userContextCallback)
|
---|
2097 | {
|
---|
2098 | IOTHUB_CLIENT_RESULT result;
|
---|
2099 | /*Codes_SRS_IOTHUBCLIENT_LL_25_111: [IoTHubClientCore_LL_SetConnectionStatusCallback shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter iotHubClientHandle**]** */
|
---|
2100 | if (iotHubClientHandle == NULL)
|
---|
2101 | {
|
---|
2102 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2103 | LOG_ERROR_RESULT;
|
---|
2104 | }
|
---|
2105 | else
|
---|
2106 | {
|
---|
2107 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2108 | /*Codes_SRS_IOTHUBCLIENT_LL_25_112: [IoTHubClientCore_LL_SetConnectionStatusCallback shall return IOTHUB_CLIENT_OK and save the callback and userContext as a member of the handle.] */
|
---|
2109 | handleData->conStatusCallback = connectionStatusCallback;
|
---|
2110 | handleData->conStatusUserContextCallback = userContextCallback;
|
---|
2111 | result = IOTHUB_CLIENT_OK;
|
---|
2112 | }
|
---|
2113 |
|
---|
2114 | return result;
|
---|
2115 | }
|
---|
2116 |
|
---|
2117 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetRetryPolicy(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
|
---|
2118 | {
|
---|
2119 | IOTHUB_CLIENT_RESULT result;
|
---|
2120 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2121 |
|
---|
2122 | /* Codes_SRS_IOTHUBCLIENT_LL_25_116: [If iotHubClientHandle, retryPolicy or retryTimeoutLimitinSeconds is NULL, IoTHubClientCore_LL_GetRetryPolicy shall return IOTHUB_CLIENT_INVALID_ARG]*/
|
---|
2123 | if (handleData == NULL)
|
---|
2124 | {
|
---|
2125 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2126 | LOG_ERROR_RESULT;
|
---|
2127 | }
|
---|
2128 | else
|
---|
2129 | {
|
---|
2130 | if (handleData->transportHandle == NULL)
|
---|
2131 | {
|
---|
2132 | result = IOTHUB_CLIENT_ERROR;
|
---|
2133 | LOG_ERROR_RESULT;
|
---|
2134 | }
|
---|
2135 | else
|
---|
2136 | {
|
---|
2137 | if (handleData->IoTHubTransport_SetRetryPolicy(handleData->transportHandle, retryPolicy, retryTimeoutLimitInSeconds) != 0)
|
---|
2138 | {
|
---|
2139 | result = IOTHUB_CLIENT_ERROR;
|
---|
2140 | LOG_ERROR_RESULT;
|
---|
2141 | }
|
---|
2142 | else
|
---|
2143 | {
|
---|
2144 | /* Codes_SRS_IOTHUBCLIENT_LL_25_118: [IoTHubClientCore_LL_SetRetryPolicy shall save connection retry policies specified by the user to retryPolicy in struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA] */
|
---|
2145 | /* Codes_SRS_IOTHUBCLIENT_LL_25_119: [IoTHubClientCore_LL_SetRetryPolicy shall save retryTimeoutLimitInSeconds in seconds to retryTimeout in struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA] */
|
---|
2146 | handleData->retryPolicy = retryPolicy;
|
---|
2147 | handleData->retryTimeoutLimitInSeconds = retryTimeoutLimitInSeconds;
|
---|
2148 | result = IOTHUB_CLIENT_OK;
|
---|
2149 | }
|
---|
2150 | }
|
---|
2151 | }
|
---|
2152 | return result;
|
---|
2153 | }
|
---|
2154 |
|
---|
2155 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_GetRetryPolicy(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY* retryPolicy, size_t* retryTimeoutLimitInSeconds)
|
---|
2156 | {
|
---|
2157 | IOTHUB_CLIENT_RESULT result;
|
---|
2158 |
|
---|
2159 | /* Codes_SRS_IOTHUBCLIENT_LL_09_001: [IoTHubClientCore_LL_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_INVALID_ARG if any of the arguments is NULL] */
|
---|
2160 | if (iotHubClientHandle == NULL || retryPolicy == NULL || retryTimeoutLimitInSeconds == NULL)
|
---|
2161 | {
|
---|
2162 | LogError("Invalid parameter IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle = %p, IOTHUB_CLIENT_RETRY_POLICY* retryPolicy = %p, size_t* retryTimeoutLimitInSeconds = %p", iotHubClientHandle, retryPolicy, retryTimeoutLimitInSeconds);
|
---|
2163 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2164 | }
|
---|
2165 | else
|
---|
2166 | {
|
---|
2167 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2168 |
|
---|
2169 | *retryPolicy = handleData->retryPolicy;
|
---|
2170 | *retryTimeoutLimitInSeconds = handleData->retryTimeoutLimitInSeconds;
|
---|
2171 | result = IOTHUB_CLIENT_OK;
|
---|
2172 | }
|
---|
2173 |
|
---|
2174 | return result;
|
---|
2175 | }
|
---|
2176 |
|
---|
2177 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_GetLastMessageReceiveTime(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, time_t* lastMessageReceiveTime)
|
---|
2178 | {
|
---|
2179 | IOTHUB_CLIENT_RESULT result;
|
---|
2180 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2181 |
|
---|
2182 | /* Codes_SRS_IOTHUBCLIENT_LL_09_001: [IoTHubClientCore_LL_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_INVALID_ARG if any of the arguments is NULL] */
|
---|
2183 | if (handleData == NULL || lastMessageReceiveTime == NULL)
|
---|
2184 | {
|
---|
2185 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2186 | LOG_ERROR_RESULT;
|
---|
2187 | }
|
---|
2188 | else
|
---|
2189 | {
|
---|
2190 | /* Codes_SRS_IOTHUBCLIENT_LL_09_002: [IoTHubClientCore_LL_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_INDEFINITE_TIME - and not set 'lastMessageReceiveTime' - if it is unable to provide the time for the last commands] */
|
---|
2191 | if (handleData->lastMessageReceiveTime == INDEFINITE_TIME)
|
---|
2192 | {
|
---|
2193 | result = IOTHUB_CLIENT_INDEFINITE_TIME;
|
---|
2194 | LOG_ERROR_RESULT;
|
---|
2195 | }
|
---|
2196 | else
|
---|
2197 | {
|
---|
2198 | /* Codes_SRS_IOTHUBCLIENT_LL_09_003: [IoTHubClientCore_LL_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_OK if it wrote in the lastMessageReceiveTime the time when the last command was received] */
|
---|
2199 | /* Codes_SRS_IOTHUBCLIENT_LL_09_004: [IoTHubClientCore_LL_GetLastMessageReceiveTime shall return lastMessageReceiveTime in localtime] */
|
---|
2200 | *lastMessageReceiveTime = handleData->lastMessageReceiveTime;
|
---|
2201 | result = IOTHUB_CLIENT_OK;
|
---|
2202 | }
|
---|
2203 | }
|
---|
2204 |
|
---|
2205 | return result;
|
---|
2206 | }
|
---|
2207 |
|
---|
2208 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetOption(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* optionName, const void* value)
|
---|
2209 | {
|
---|
2210 |
|
---|
2211 | IOTHUB_CLIENT_RESULT result;
|
---|
2212 | /*Codes_SRS_IOTHUBCLIENT_LL_02_034: [If iotHubClientHandle is NULL then IoTHubClientCore_LL_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]*/
|
---|
2213 | /*Codes_SRS_IOTHUBCLIENT_LL_02_035: [If optionName is NULL then IoTHubClientCore_LL_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
|
---|
2214 | /*Codes_SRS_IOTHUBCLIENT_LL_02_036: [If value is NULL then IoTHubClientCore_LL_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
|
---|
2215 | if (
|
---|
2216 | (iotHubClientHandle == NULL) ||
|
---|
2217 | (optionName == NULL) ||
|
---|
2218 | (value == NULL)
|
---|
2219 | )
|
---|
2220 | {
|
---|
2221 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2222 | LogError("invalid argument (NULL)");
|
---|
2223 | }
|
---|
2224 | else
|
---|
2225 | {
|
---|
2226 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2227 |
|
---|
2228 | /*Codes_SRS_IOTHUBCLIENT_LL_02_039: [ "messageTimeout" - once IoTHubClientCore_LL_SendEventAsync is called the message shall timeout after value miliseconds. Value is a pointer to a tickcounter_ms_t. ]*/
|
---|
2229 | if (strcmp(optionName, OPTION_MESSAGE_TIMEOUT) == 0)
|
---|
2230 | {
|
---|
2231 | /*this is an option handled by IoTHubClientCore_LL*/
|
---|
2232 | /*Codes_SRS_IOTHUBCLIENT_LL_02_043: [ Calling IoTHubClientCore_LL_SetOption with value set to "0" shall disable the timeout mechanism for all new messages. ]*/
|
---|
2233 | handleData->currentMessageTimeout = *(const tickcounter_ms_t*)value;
|
---|
2234 | result = IOTHUB_CLIENT_OK;
|
---|
2235 | }
|
---|
2236 | else if (strcmp(optionName, OPTION_PRODUCT_INFO) == 0)
|
---|
2237 | {
|
---|
2238 | /*Codes_SRS_IOTHUBCLIENT_LL_10_033: [repeat calls with "product_info" will erase the previously set product information if applicatble. ]*/
|
---|
2239 | if (handleData->product_info != NULL)
|
---|
2240 | {
|
---|
2241 | STRING_delete(handleData->product_info);
|
---|
2242 | handleData->product_info = NULL;
|
---|
2243 | }
|
---|
2244 |
|
---|
2245 | /*Codes_SRS_IOTHUBCLIENT_LL_10_035: [If string concatenation fails, `IoTHubClientCore_LL_SetOption` shall return `IOTHUB_CLIENT_ERRROR`. Otherwise, `IOTHUB_CLIENT_OK` shall be returned. ]*/
|
---|
2246 | handleData->product_info = make_product_info((const char*)value);
|
---|
2247 | if (handleData->product_info == NULL)
|
---|
2248 | {
|
---|
2249 | LogError("STRING_construct_sprintf failed");
|
---|
2250 | result = IOTHUB_CLIENT_ERROR;
|
---|
2251 | }
|
---|
2252 | else
|
---|
2253 | {
|
---|
2254 | result = IOTHUB_CLIENT_OK;
|
---|
2255 | }
|
---|
2256 | }
|
---|
2257 | else if (strcmp(optionName, OPTION_DIAGNOSTIC_SAMPLING_PERCENTAGE) == 0)
|
---|
2258 | {
|
---|
2259 | uint32_t percentage = *(uint32_t*)value;
|
---|
2260 | if (percentage > 100)
|
---|
2261 | {
|
---|
2262 | /*Codes_SRS_IOTHUBCLIENT_LL_10_036: [Calling IoTHubClientCore_LL_SetOption with value > 100 shall return `IOTHUB_CLIENT_ERRROR`. ]*/
|
---|
2263 | LogError("The value of diag_sampling_percentage is out of range [0, 100]: %u", percentage);
|
---|
2264 | result = IOTHUB_CLIENT_ERROR;
|
---|
2265 | }
|
---|
2266 | else
|
---|
2267 | {
|
---|
2268 | /*Codes_SRS_IOTHUBCLIENT_LL_10_037: [Calling IoTHubClientCore_LL_SetOption with value between [0, 100] shall return `IOTHUB_CLIENT_OK`. ]*/
|
---|
2269 | handleData->diagnostic_setting.diagSamplingPercentage = percentage;
|
---|
2270 | handleData->diagnostic_setting.currentMessageNumber = 0;
|
---|
2271 | result = IOTHUB_CLIENT_OK;
|
---|
2272 | }
|
---|
2273 | }
|
---|
2274 | else if ((strcmp(optionName, OPTION_BLOB_UPLOAD_TIMEOUT_SECS) == 0) || (strcmp(optionName, OPTION_CURL_VERBOSE) == 0))
|
---|
2275 | {
|
---|
2276 | #ifndef DONT_USE_UPLOADTOBLOB
|
---|
2277 | // This option just gets passed down into IoTHubClientCore_LL_UploadToBlob
|
---|
2278 | /*Codes_SRS_IOTHUBCLIENT_LL_30_010: [ blob_xfr_timeout - IoTHubClientCore_LL_SetOption shall pass this option to IoTHubClient_UploadToBlob_SetOption and return its result. ]*/
|
---|
2279 | result = IoTHubClient_LL_UploadToBlob_SetOption(handleData->uploadToBlobHandle, optionName, value);
|
---|
2280 | if(result != IOTHUB_CLIENT_OK)
|
---|
2281 | {
|
---|
2282 | LogError("unable to IoTHubClientCore_LL_UploadToBlob_SetOption, result=%d", result);
|
---|
2283 | }
|
---|
2284 | #else
|
---|
2285 | LogError("%s option being set with DONT_USE_UPLOADTOBLOB compiler switch", optionName);
|
---|
2286 | result = IOTHUB_CLIENT_ERROR;
|
---|
2287 | #endif /*DONT_USE_UPLOADTOBLOB*/
|
---|
2288 | }
|
---|
2289 | // OPTION_SAS_TOKEN_REFRESH_TIME is, but may be updated in the future
|
---|
2290 | // if this becomes necessary
|
---|
2291 | else if (strcmp(optionName, OPTION_SAS_TOKEN_REFRESH_TIME) == 0 || strcmp(optionName, OPTION_SAS_TOKEN_LIFETIME) == 0)
|
---|
2292 | {
|
---|
2293 | if (IoTHubClient_Auth_Set_SasToken_Expiry(handleData->authorization_module, *(size_t*)value) != 0)
|
---|
2294 | {
|
---|
2295 | LogError("Failed setting the Token Expiry time");
|
---|
2296 | result = IOTHUB_CLIENT_ERROR;
|
---|
2297 | }
|
---|
2298 | else
|
---|
2299 | {
|
---|
2300 | result = IOTHUB_CLIENT_OK;
|
---|
2301 | }
|
---|
2302 | }
|
---|
2303 | else
|
---|
2304 | {
|
---|
2305 | // This section is unusual for SetOption calls because it attempts to pass unhandled options
|
---|
2306 | // to two downstream targets (IoTHubTransport_SetOption and IoTHubClientCore_LL_UploadToBlob_SetOption) instead of one.
|
---|
2307 |
|
---|
2308 | /*Codes_SRS_IOTHUBCLIENT_LL_30_011: [ IoTHubClientCore_LL_SetOption shall always pass unhandled options to Transport_SetOption. ]*/
|
---|
2309 | /*Codes_SRS_IOTHUBCLIENT_LL_30_012: [ If Transport_SetOption fails, IoTHubClientCore_LL_SetOption shall return that failure code. ]*/
|
---|
2310 | result = handleData->IoTHubTransport_SetOption(handleData->transportHandle, optionName, value);
|
---|
2311 | if(result != IOTHUB_CLIENT_OK)
|
---|
2312 | {
|
---|
2313 | LogError("unable to IoTHubTransport_SetOption");
|
---|
2314 | }
|
---|
2315 | #ifndef DONT_USE_UPLOADTOBLOB
|
---|
2316 | else
|
---|
2317 | {
|
---|
2318 | /*Codes_SRS_IOTHUBCLIENT_LL_30_013: [ If the DONT_USE_UPLOADTOBLOB compiler switch is undefined, IoTHubClientCore_LL_SetOption shall pass unhandled options to IoTHubClient_UploadToBlob_SetOption and ignore the result. ]*/
|
---|
2319 | (void)IoTHubClient_LL_UploadToBlob_SetOption(handleData->uploadToBlobHandle, optionName, value);
|
---|
2320 | }
|
---|
2321 | #endif /*DONT_USE_UPLOADTOBLOB*/
|
---|
2322 | }
|
---|
2323 | }
|
---|
2324 | return result;
|
---|
2325 | }
|
---|
2326 |
|
---|
2327 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetDeviceTwinCallback(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback)
|
---|
2328 | {
|
---|
2329 | IOTHUB_CLIENT_RESULT result;
|
---|
2330 | /* Codes_SRS_IOTHUBCLIENT_LL_10_001: [ IoTHubClientCore_LL_SetDeviceTwinCallback shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.] */
|
---|
2331 | if (iotHubClientHandle == NULL)
|
---|
2332 | {
|
---|
2333 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2334 | LogError("Invalid argument specified iothubClientHandle=%p", iotHubClientHandle);
|
---|
2335 | }
|
---|
2336 | else
|
---|
2337 | {
|
---|
2338 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2339 | if (deviceTwinCallback == NULL)
|
---|
2340 | {
|
---|
2341 | /* Codes_SRS_IOTHUBCLIENT_LL_10_006: [ If deviceTwinCallback is NULL, then IoTHubClientCore_LL_SetDeviceTwinCallback shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */
|
---|
2342 | handleData->IoTHubTransport_Unsubscribe_DeviceTwin(handleData->transportHandle);
|
---|
2343 | handleData->deviceTwinCallback = NULL;
|
---|
2344 | result = IOTHUB_CLIENT_OK;
|
---|
2345 | }
|
---|
2346 | else
|
---|
2347 | {
|
---|
2348 | /* Codes_SRS_IOTHUBCLIENT_LL_10_002: [ If deviceTwinCallback is not NULL, then IoTHubClientCore_LL_SetDeviceTwinCallback shall call the underlying layer's _Subscribe function.] */
|
---|
2349 | if (handleData->IoTHubTransport_Subscribe_DeviceTwin(handleData->transportHandle) == 0)
|
---|
2350 | {
|
---|
2351 | handleData->deviceTwinCallback = deviceTwinCallback;
|
---|
2352 | handleData->deviceTwinContextCallback = userContextCallback;
|
---|
2353 | /* Codes_SRS_IOTHUBCLIENT_LL_10_005: [ Otherwise IoTHubClientCore_LL_SetDeviceTwinCallback shall succeed and return IOTHUB_CLIENT_OK.] */
|
---|
2354 | result = IOTHUB_CLIENT_OK;
|
---|
2355 | }
|
---|
2356 | else
|
---|
2357 | {
|
---|
2358 | /* Codes_SRS_IOTHUBCLIENT_LL_10_003: [ If the underlying layer's _Subscribe function fails, then IoTHubClientCore_LL_SetDeviceTwinCallback shall fail and return IOTHUB_CLIENT_ERROR.] */
|
---|
2359 | result = IOTHUB_CLIENT_ERROR;
|
---|
2360 | }
|
---|
2361 | }
|
---|
2362 | }
|
---|
2363 | return result;
|
---|
2364 | }
|
---|
2365 |
|
---|
2366 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SendReportedState(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const unsigned char* reportedState, size_t size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reportedStateCallback, void* userContextCallback)
|
---|
2367 | {
|
---|
2368 | IOTHUB_CLIENT_RESULT result;
|
---|
2369 | /* Codes_SRS_IOTHUBCLIENT_LL_10_012: [ IoTHubClientCore_LL_SendReportedState shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL. ] */
|
---|
2370 | /* Codes_SRS_IOTHUBCLIENT_LL_10_013: [ IoTHubClientCore_LL_SendReportedState shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter reportedState is NULL] */
|
---|
2371 | /* Codes_SRS_IOTHUBCLIENT_LL_07_005: [ IoTHubClientCore_LL_SendReportedState shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter size is equal to 0. ] */
|
---|
2372 | if (iotHubClientHandle == NULL || (reportedState == NULL || size == 0) )
|
---|
2373 | {
|
---|
2374 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2375 | LogError("Invalid argument specified iothubClientHandle=%p, reportedState=%p, size=%lu", iotHubClientHandle, reportedState, (unsigned long)size);
|
---|
2376 | }
|
---|
2377 | else
|
---|
2378 | {
|
---|
2379 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2380 | /* Codes_SRS_IOTHUBCLIENT_LL_10_014: [IoTHubClientCore_LL_SendReportedState shall construct and queue the reported a Device_Twin structure for transmition by the underlying transport.] */
|
---|
2381 | IOTHUB_DEVICE_TWIN* client_data = dev_twin_data_create(handleData, get_next_item_id(handleData), reportedState, size, reportedStateCallback, userContextCallback);
|
---|
2382 | if (client_data == NULL)
|
---|
2383 | {
|
---|
2384 | /* Codes_SRS_IOTHUBCLIENT_LL_10_015: [If any error is encountered IoTHubClientCore_LL_SendReportedState shall return IOTHUB_CLIENT_ERROR.] */
|
---|
2385 | LogError("Failure constructing device twin data");
|
---|
2386 | result = IOTHUB_CLIENT_ERROR;
|
---|
2387 | }
|
---|
2388 | else
|
---|
2389 | {
|
---|
2390 | if (handleData->IoTHubTransport_Subscribe_DeviceTwin(handleData->transportHandle) != 0)
|
---|
2391 | {
|
---|
2392 | LogError("Failure adding device twin data to queue");
|
---|
2393 | device_twin_data_destroy(client_data);
|
---|
2394 | result = IOTHUB_CLIENT_ERROR;
|
---|
2395 | }
|
---|
2396 | else
|
---|
2397 | {
|
---|
2398 | /* Codes_SRS_IOTHUBCLIENT_LL_07_001: [ IoTHubClientCore_LL_SendReportedState shall queue the constructed reportedState data to be consumed by the targeted transport. ] */
|
---|
2399 | DList_InsertTailList(&(iotHubClientHandle->iot_msg_queue), &(client_data->entry));
|
---|
2400 |
|
---|
2401 | /* Codes_SRS_IOTHUBCLIENT_LL_10_016: [ Otherwise IoTHubClientCore_LL_SendReportedState shall succeed and return IOTHUB_CLIENT_OK.] */
|
---|
2402 | result = IOTHUB_CLIENT_OK;
|
---|
2403 | }
|
---|
2404 | }
|
---|
2405 | }
|
---|
2406 | return result;
|
---|
2407 | }
|
---|
2408 |
|
---|
2409 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_GetTwinAsync(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback)
|
---|
2410 | {
|
---|
2411 | IOTHUB_CLIENT_RESULT result;
|
---|
2412 |
|
---|
2413 | // Codes_SRS_IOTHUBCLIENT_LL_09_011: [ If `iotHubClientHandle` or `deviceTwinCallback` are `NULL`, `IoTHubClientCore_LL_GetTwinAsync` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]
|
---|
2414 | if (iotHubClientHandle == NULL || deviceTwinCallback == NULL)
|
---|
2415 | {
|
---|
2416 | LogError("Invalid argument iothubClientHandle=%p, deviceTwinCallback=%p", iotHubClientHandle, deviceTwinCallback);
|
---|
2417 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2418 | }
|
---|
2419 | else
|
---|
2420 | {
|
---|
2421 | if (iotHubClientHandle->IoTHubTransport_Subscribe_DeviceTwin(iotHubClientHandle->transportHandle) != 0)
|
---|
2422 | {
|
---|
2423 | LogError("Failure adding device twin data to queue");
|
---|
2424 | result = IOTHUB_CLIENT_ERROR;
|
---|
2425 | }
|
---|
2426 | else
|
---|
2427 | {
|
---|
2428 | GET_TWIN_CONTEXT* getTwinCtx;
|
---|
2429 |
|
---|
2430 | if ((getTwinCtx = (GET_TWIN_CONTEXT*)malloc(sizeof(GET_TWIN_CONTEXT))) == NULL)
|
---|
2431 | {
|
---|
2432 | LogError("Failed creating get-twin context");
|
---|
2433 | result = IOTHUB_CLIENT_ERROR;
|
---|
2434 | }
|
---|
2435 | else
|
---|
2436 | {
|
---|
2437 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2438 |
|
---|
2439 | getTwinCtx->callback = deviceTwinCallback;
|
---|
2440 | getTwinCtx->context = userContextCallback;
|
---|
2441 |
|
---|
2442 | // Codes_SRS_IOTHUBCLIENT_LL_09_012: [ IoTHubClientCore_LL_GetTwinAsync shall invoke IoTHubTransport_GetTwinAsync, passing `on_device_twin_report_received` and the user data as context ]
|
---|
2443 | if (handleData->IoTHubTransport_GetTwinAsync(handleData->deviceHandle, on_get_device_twin_completed, getTwinCtx) != IOTHUB_CLIENT_OK)
|
---|
2444 | {
|
---|
2445 | // Codes_SRS_IOTHUBCLIENT_LL_09_013: [ If IoTHubTransport_GetTwinAsync fails, `IoTHubClientCore_LL_GetTwinAsync` shall fail and return `IOTHUB_CLIENT_ERROR`. ]
|
---|
2446 | LogError("Failed getting device twin document");
|
---|
2447 | free(getTwinCtx);
|
---|
2448 | result = IOTHUB_CLIENT_ERROR;
|
---|
2449 | }
|
---|
2450 | else
|
---|
2451 | {
|
---|
2452 | // Codes_SRS_IOTHUBCLIENT_LL_09_014: [ If no errors occur IoTHubClientCore_LL_GetTwinAsync shall return `IOTHUB_CLIENT_OK`. ]
|
---|
2453 | handleData->complete_twin_update_encountered = true;
|
---|
2454 | result = IOTHUB_CLIENT_OK;
|
---|
2455 | }
|
---|
2456 | }
|
---|
2457 | }
|
---|
2458 | }
|
---|
2459 |
|
---|
2460 | return result;
|
---|
2461 | }
|
---|
2462 |
|
---|
2463 |
|
---|
2464 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetDeviceMethodCallback(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC deviceMethodCallback, void* userContextCallback)
|
---|
2465 | {
|
---|
2466 | IOTHUB_CLIENT_RESULT result;
|
---|
2467 |
|
---|
2468 | /*Codes_SRS_IOTHUBCLIENT_LL_12_017: [ IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL. ] */
|
---|
2469 | if (iotHubClientHandle == NULL)
|
---|
2470 | {
|
---|
2471 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2472 | LOG_ERROR_RESULT;
|
---|
2473 | }
|
---|
2474 | else
|
---|
2475 | {
|
---|
2476 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2477 | if (deviceMethodCallback == NULL)
|
---|
2478 | {
|
---|
2479 | if (handleData->methodCallback.type == CALLBACK_TYPE_NONE)
|
---|
2480 | {
|
---|
2481 | /* Codes_SRS_IOTHUBCLIENT_LL_10_029: [ If deviceMethodCallback is NULL and the client is not subscribed to receive method calls, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */
|
---|
2482 | LogError("not currently set to accept or process incoming messages.");
|
---|
2483 | result = IOTHUB_CLIENT_ERROR;
|
---|
2484 | }
|
---|
2485 | else if (handleData->methodCallback.type == CALLBACK_TYPE_ASYNC)
|
---|
2486 | {
|
---|
2487 | /* Codes_SRS_IOTHUBCLIENT_LL_10_028: [If the user has subscribed using IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */
|
---|
2488 | LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetDeviceMethodCallback_Ex function.");
|
---|
2489 | result = IOTHUB_CLIENT_ERROR;
|
---|
2490 | }
|
---|
2491 | else
|
---|
2492 | {
|
---|
2493 | /*Codes_SRS_IOTHUBCLIENT_LL_02_019: [If parameter messageCallback is NULL then IoTHubClientCore_LL_SetMessageCallback shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */
|
---|
2494 | /*Codes_SRS_IOTHUBCLIENT_LL_12_018: [If deviceMethodCallback is NULL, then IoTHubClientCore_LL_SetDeviceMethodCallback shall call the underlying layer's IoTHubTransport_Unsubscribe_DeviceMethod function and return IOTHUB_CLIENT_OK. ] */
|
---|
2495 | /*Codes_SRS_IOTHUBCLIENT_LL_12_022: [ Otherwise IoTHubClientCore_LL_SetDeviceMethodCallback shall succeed and return IOTHUB_CLIENT_OK. ]*/
|
---|
2496 | handleData->IoTHubTransport_Unsubscribe_DeviceMethod(handleData->deviceHandle);
|
---|
2497 | handleData->methodCallback.type = CALLBACK_TYPE_NONE;
|
---|
2498 | handleData->methodCallback.callbackSync = NULL;
|
---|
2499 | handleData->methodCallback.userContextCallback = NULL;
|
---|
2500 | result = IOTHUB_CLIENT_OK;
|
---|
2501 | }
|
---|
2502 | }
|
---|
2503 | else
|
---|
2504 | {
|
---|
2505 | if (handleData->methodCallback.type == CALLBACK_TYPE_ASYNC)
|
---|
2506 | {
|
---|
2507 | /* Codes_SRS_IOTHUBCLIENT_LL_10_028: [If the user has subscribed using IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */
|
---|
2508 | LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetDeviceMethodCallback_Ex function before subscribing with IoTHubClientCore_LL_SetDeviceMethodCallback.");
|
---|
2509 | result = IOTHUB_CLIENT_ERROR;
|
---|
2510 | }
|
---|
2511 | else
|
---|
2512 | {
|
---|
2513 | /*Codes_SRS_IOTHUBCLIENT_LL_12_019: [ If deviceMethodCallback is not NULL, then IoTHubClientCore_LL_SetDeviceMethodCallback shall call the underlying layer's IoTHubTransport_Subscribe_DeviceMethod function. ]*/
|
---|
2514 | if (handleData->IoTHubTransport_Subscribe_DeviceMethod(handleData->deviceHandle) == 0)
|
---|
2515 | {
|
---|
2516 | /*Codes_SRS_IOTHUBCLIENT_LL_12_022: [ Otherwise IoTHubClientCore_LL_SetDeviceMethodCallback shall succeed and return IOTHUB_CLIENT_OK. ]*/
|
---|
2517 | handleData->methodCallback.type = CALLBACK_TYPE_SYNC;
|
---|
2518 | handleData->methodCallback.callbackSync = deviceMethodCallback;
|
---|
2519 | handleData->methodCallback.callbackAsync = NULL;
|
---|
2520 | handleData->methodCallback.userContextCallback = userContextCallback;
|
---|
2521 | result = IOTHUB_CLIENT_OK;
|
---|
2522 | }
|
---|
2523 | else
|
---|
2524 | {
|
---|
2525 | /*Codes_SRS_IOTHUBCLIENT_LL_12_020: [ If the underlying layer's IoTHubTransport_Subscribe_DeviceMethod function fails, then IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
2526 | /*Codes_SRS_IOTHUBCLIENT_LL_12_021: [ If adding the information fails for any reason, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
2527 | LogError("IoTHubTransport_Subscribe_DeviceMethod failed");
|
---|
2528 | handleData->methodCallback.type = CALLBACK_TYPE_NONE;
|
---|
2529 | handleData->methodCallback.callbackAsync = NULL;
|
---|
2530 | handleData->methodCallback.callbackSync = NULL;
|
---|
2531 | handleData->methodCallback.userContextCallback = NULL;
|
---|
2532 | result = IOTHUB_CLIENT_ERROR;
|
---|
2533 | }
|
---|
2534 | }
|
---|
2535 | }
|
---|
2536 | }
|
---|
2537 | return result;
|
---|
2538 | }
|
---|
2539 |
|
---|
2540 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK inboundDeviceMethodCallback, void* userContextCallback)
|
---|
2541 | {
|
---|
2542 | IOTHUB_CLIENT_RESULT result;
|
---|
2543 | /* Codes_SRS_IOTHUBCLIENT_LL_07_021: [ If handle is NULL then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_INVALID_ARG.] */
|
---|
2544 | if (iotHubClientHandle == NULL)
|
---|
2545 | {
|
---|
2546 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2547 | LOG_ERROR_RESULT;
|
---|
2548 | }
|
---|
2549 | else
|
---|
2550 | {
|
---|
2551 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2552 | if (inboundDeviceMethodCallback == NULL)
|
---|
2553 | {
|
---|
2554 | if (handleData->methodCallback.type == CALLBACK_TYPE_NONE)
|
---|
2555 | {
|
---|
2556 | /* Codes_SRS_IOTHUBCLIENT_LL_10_030: [ If deviceMethodCallback is NULL and the client is not subscribed to receive method calls, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */
|
---|
2557 | LogError("not currently set to accept or process incoming messages.");
|
---|
2558 | result = IOTHUB_CLIENT_ERROR;
|
---|
2559 | }
|
---|
2560 | else if (handleData->methodCallback.type == CALLBACK_TYPE_SYNC)
|
---|
2561 | {
|
---|
2562 | /* Codes_SRS_IOTHUBCLIENT_LL_10_031: [If the user has subscribed using IoTHubClientCore_LL_SetDeviceMethodCallback, IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR. ] */
|
---|
2563 | LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetDeviceMethodCallback function.");
|
---|
2564 | result = IOTHUB_CLIENT_ERROR;
|
---|
2565 | }
|
---|
2566 | else
|
---|
2567 | {
|
---|
2568 | /* Codes_SRS_IOTHUBCLIENT_LL_07_022: [ If inboundDeviceMethodCallback is NULL then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall call the underlying layer's IoTHubTransport_Unsubscribe_DeviceMethod function and return IOTHUB_CLIENT_OK.] */
|
---|
2569 | handleData->IoTHubTransport_Unsubscribe_DeviceMethod(handleData->deviceHandle);
|
---|
2570 | handleData->methodCallback.type = CALLBACK_TYPE_NONE;
|
---|
2571 | handleData->methodCallback.callbackAsync = NULL;
|
---|
2572 | handleData->methodCallback.userContextCallback = NULL;
|
---|
2573 | result = IOTHUB_CLIENT_OK;
|
---|
2574 | }
|
---|
2575 | }
|
---|
2576 | else
|
---|
2577 | {
|
---|
2578 | if (handleData->methodCallback.type == CALLBACK_TYPE_SYNC)
|
---|
2579 | {
|
---|
2580 | /* Codes_SRS_IOTHUBCLIENT_LL_10_031: [If the user has subscribed using IoTHubClientCore_LL_SetDeviceMethodCallback, IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR. ] */
|
---|
2581 | LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetDeviceMethodCallback function before subscribing with IoTHubClientCore_LL_SetDeviceMethodCallback_Ex.");
|
---|
2582 | result = IOTHUB_CLIENT_ERROR;
|
---|
2583 | }
|
---|
2584 | else
|
---|
2585 | {
|
---|
2586 | /* Codes_SRS_IOTHUBCLIENT_LL_07_023: [ If inboundDeviceMethodCallback is non-NULL then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall call the underlying layer's IoTHubTransport_Subscribe_DeviceMethod function.]*/
|
---|
2587 | if (handleData->IoTHubTransport_Subscribe_DeviceMethod(handleData->deviceHandle) == 0)
|
---|
2588 | {
|
---|
2589 | handleData->methodCallback.type = CALLBACK_TYPE_ASYNC;
|
---|
2590 | handleData->methodCallback.callbackAsync = inboundDeviceMethodCallback;
|
---|
2591 | handleData->methodCallback.callbackSync = NULL;
|
---|
2592 | handleData->methodCallback.userContextCallback = userContextCallback;
|
---|
2593 | result = IOTHUB_CLIENT_OK;
|
---|
2594 | }
|
---|
2595 | else
|
---|
2596 | {
|
---|
2597 | /* Codes_SRS_IOTHUBCLIENT_LL_07_025: [ If any error is encountered then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_ERROR.] */
|
---|
2598 | LogError("IoTHubTransport_Subscribe_DeviceMethod failed");
|
---|
2599 | handleData->methodCallback.type = CALLBACK_TYPE_NONE;
|
---|
2600 | handleData->methodCallback.callbackAsync = NULL;
|
---|
2601 | handleData->methodCallback.callbackSync = NULL;
|
---|
2602 | handleData->methodCallback.userContextCallback = NULL;
|
---|
2603 | result = IOTHUB_CLIENT_ERROR;
|
---|
2604 | }
|
---|
2605 | }
|
---|
2606 | }
|
---|
2607 | }
|
---|
2608 | return result;
|
---|
2609 | }
|
---|
2610 |
|
---|
2611 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_DeviceMethodResponse(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, METHOD_HANDLE methodId, const unsigned char* response, size_t response_size, int status_response)
|
---|
2612 | {
|
---|
2613 | IOTHUB_CLIENT_RESULT result;
|
---|
2614 | /* Codes_SRS_IOTHUBCLIENT_LL_07_026: [ If handle or methodId is NULL then IoTHubClientCore_LL_DeviceMethodResponse shall return IOTHUB_CLIENT_INVALID_ARG.] */
|
---|
2615 | if (iotHubClientHandle == NULL || methodId == NULL)
|
---|
2616 | {
|
---|
2617 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2618 | LOG_ERROR_RESULT;
|
---|
2619 | }
|
---|
2620 | else
|
---|
2621 | {
|
---|
2622 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2623 | /* Codes_SRS_IOTHUBCLIENT_LL_07_027: [ IoTHubClientCore_LL_DeviceMethodResponse shall call the IoTHubTransport_DeviceMethod_Response transport function.] */
|
---|
2624 | if (handleData->IoTHubTransport_DeviceMethod_Response(handleData->deviceHandle, methodId, response, response_size, status_response) != 0)
|
---|
2625 | {
|
---|
2626 | LogError("IoTHubTransport_DeviceMethod_Response failed");
|
---|
2627 | result = IOTHUB_CLIENT_ERROR;
|
---|
2628 | }
|
---|
2629 | else
|
---|
2630 | {
|
---|
2631 | result = IOTHUB_CLIENT_OK;
|
---|
2632 | }
|
---|
2633 | }
|
---|
2634 | return result;
|
---|
2635 | }
|
---|
2636 |
|
---|
2637 | #ifndef DONT_USE_UPLOADTOBLOB
|
---|
2638 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadToBlob(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* destinationFileName, const unsigned char* source, size_t size)
|
---|
2639 | {
|
---|
2640 | IOTHUB_CLIENT_RESULT result;
|
---|
2641 | /*Codes_SRS_IOTHUBCLIENT_LL_02_061: [ If iotHubClientHandle is NULL then IoTHubClientCore_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
|
---|
2642 | /*Codes_SRS_IOTHUBCLIENT_LL_02_062: [ If destinationFileName is NULL then IoTHubClientCore_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
|
---|
2643 | /*Codes_SRS_IOTHUBCLIENT_LL_02_063: [ If `source` is `NULL` and size is greater than 0 then `IoTHubClientCore_LL_UploadToBlob` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
|
---|
2644 | if (
|
---|
2645 | (iotHubClientHandle == NULL) ||
|
---|
2646 | (destinationFileName == NULL) ||
|
---|
2647 | ((source == NULL) && (size >0))
|
---|
2648 | )
|
---|
2649 | {
|
---|
2650 | LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, const char* destinationFileName=%s, const unsigned char* source=%p, size_t size=%lu", iotHubClientHandle, destinationFileName, source, (unsigned long)size);
|
---|
2651 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2652 | }
|
---|
2653 | else
|
---|
2654 | {
|
---|
2655 | result = IoTHubClient_LL_UploadToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, source, size);
|
---|
2656 | }
|
---|
2657 | return result;
|
---|
2658 | }
|
---|
2659 |
|
---|
2660 | typedef struct UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT_TAG
|
---|
2661 | {
|
---|
2662 | IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback;
|
---|
2663 | void* context;
|
---|
2664 | } UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT;
|
---|
2665 |
|
---|
2666 |
|
---|
2667 | static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT uploadMultipleBlocksCallbackWrapper(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, unsigned char const ** data, size_t* size, void* context)
|
---|
2668 | {
|
---|
2669 | UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT* wrapperContext = (UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT*)context;
|
---|
2670 | wrapperContext->getDataCallback(result, data, size, wrapperContext->context);
|
---|
2671 | return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK;
|
---|
2672 | }
|
---|
2673 |
|
---|
2674 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadMultipleBlocksToBlob(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback, void* context)
|
---|
2675 | {
|
---|
2676 | IOTHUB_CLIENT_RESULT result;
|
---|
2677 | /*Codes_SRS_IOTHUBCLIENT_LL_99_005: [ If `iotHubClientHandle` is `NULL` then `IoTHubClientCore_LL_UploadMultipleBlocksToBlob(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
|
---|
2678 | /*Codes_SRS_IOTHUBCLIENT_LL_99_006: [ If `destinationFileName` is `NULL` then `IoTHubClientCore_LL_UploadMultipleBlocksToBlob(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
|
---|
2679 | /*Codes_SRS_IOTHUBCLIENT_LL_99_007: [ If `getDataCallback` is `NULL` then `IoTHubClientCore_LL_UploadMultipleBlocksToBlob(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
|
---|
2680 | if (
|
---|
2681 | (iotHubClientHandle == NULL) ||
|
---|
2682 | (destinationFileName == NULL) ||
|
---|
2683 | (getDataCallback == NULL)
|
---|
2684 | )
|
---|
2685 | {
|
---|
2686 | LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, const char* destinationFileName=%p, getDataCallback=%p", iotHubClientHandle, destinationFileName, getDataCallback);
|
---|
2687 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2688 | }
|
---|
2689 | else
|
---|
2690 | {
|
---|
2691 | UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT uploadMultipleBlocksWrapperContext;
|
---|
2692 | uploadMultipleBlocksWrapperContext.getDataCallback = getDataCallback;
|
---|
2693 | uploadMultipleBlocksWrapperContext.context = context;
|
---|
2694 |
|
---|
2695 | result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, uploadMultipleBlocksCallbackWrapper, &uploadMultipleBlocksWrapperContext);
|
---|
2696 | }
|
---|
2697 | return result;
|
---|
2698 | }
|
---|
2699 |
|
---|
2700 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context)
|
---|
2701 | {
|
---|
2702 | IOTHUB_CLIENT_RESULT result;
|
---|
2703 | /*Codes_SRS_IOTHUBCLIENT_LL_99_005: [ If `iotHubClientHandle` is `NULL` then `IoTHubClientCore_LL_UploadMultipleBlocksToBlob(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
|
---|
2704 | /*Codes_SRS_IOTHUBCLIENT_LL_99_006: [ If `destinationFileName` is `NULL` then `IoTHubClientCore_LL_UploadMultipleBlocksToBlob(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
|
---|
2705 | /*Codes_SRS_IOTHUBCLIENT_LL_99_007: [ If `getDataCallback` is `NULL` then `IoTHubClientCore_LL_UploadMultipleBlocksToBlob(Ex)` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
|
---|
2706 | if (
|
---|
2707 | (iotHubClientHandle == NULL) ||
|
---|
2708 | (destinationFileName == NULL) ||
|
---|
2709 | (getDataCallbackEx == NULL)
|
---|
2710 | )
|
---|
2711 | {
|
---|
2712 | LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, destinationFileName=%p, getDataCallbackEx=%p", iotHubClientHandle, destinationFileName, getDataCallbackEx);
|
---|
2713 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2714 | }
|
---|
2715 | else
|
---|
2716 | {
|
---|
2717 | result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, getDataCallbackEx, context);
|
---|
2718 | }
|
---|
2719 | return result;
|
---|
2720 | }
|
---|
2721 | #endif // DONT_USE_UPLOADTOBLOB
|
---|
2722 |
|
---|
2723 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SendEventToOutputAsync(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, const char* outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
|
---|
2724 | {
|
---|
2725 | IOTHUB_CLIENT_RESULT result;
|
---|
2726 |
|
---|
2727 | if ((iotHubClientHandle == NULL) || (outputName == NULL) || (eventMessageHandle == NULL) || ((eventConfirmationCallback == NULL) && (userContextCallback != NULL)))
|
---|
2728 | {
|
---|
2729 | // Codes_SRS_IOTHUBCLIENT_LL_31_127: [ If `iotHubClientHandle`, `outputName`, or `eventConfirmationCallback` is `NULL`, `IoTHubClient_LL_SendEventToOutputAsync` shall return `IOTHUB_CLIENT_INVALID_ARG`. ]
|
---|
2730 | LogError("Invalid argument (iotHubClientHandle=%p, outputName=%p, eventMessageHandle=%p)", iotHubClientHandle, outputName, eventMessageHandle);
|
---|
2731 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2732 | }
|
---|
2733 | else
|
---|
2734 | {
|
---|
2735 | // Codes_SRS_IOTHUBCLIENT_LL_31_128: [ `IoTHubClient_LL_SendEventToOutputAsync` shall set the outputName of the message to send. ]
|
---|
2736 | if (IoTHubMessage_SetOutputName(eventMessageHandle, outputName) != IOTHUB_MESSAGE_OK)
|
---|
2737 | {
|
---|
2738 | LogError("IoTHubMessage_SetOutputName failed");
|
---|
2739 | result = IOTHUB_CLIENT_ERROR;
|
---|
2740 | }
|
---|
2741 | // Codes_SRS_IOTHUBCLIENT_LL_31_129: [ `IoTHubClient_LL_SendEventToOutputAsync` shall invoke `IoTHubClient_LL_SendEventAsync` to send the message. ]
|
---|
2742 | else if ((result = IoTHubClientCore_LL_SendEventAsync(iotHubClientHandle, eventMessageHandle, eventConfirmationCallback, userContextCallback)) != IOTHUB_CLIENT_OK)
|
---|
2743 | {
|
---|
2744 | LogError("Call into IoTHubClient_LL_SendEventAsync failed, result=%d", result);
|
---|
2745 | }
|
---|
2746 | }
|
---|
2747 |
|
---|
2748 | return result;
|
---|
2749 | }
|
---|
2750 |
|
---|
2751 |
|
---|
2752 | static IOTHUB_CLIENT_RESULT create_event_handler_callback(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, const char* inputName, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC callbackSync, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX callbackSyncEx, void* userContextCallback, void* userContextCallbackEx, size_t userContextCallbackExLength)
|
---|
2753 | {
|
---|
2754 | IOTHUB_CLIENT_RESULT result = IOTHUB_CLIENT_ERROR;
|
---|
2755 | bool add_to_list = false;
|
---|
2756 |
|
---|
2757 | if ((handleData->event_callbacks == NULL) && ((handleData->event_callbacks = singlylinkedlist_create()) == NULL))
|
---|
2758 | {
|
---|
2759 | LogError("Could not allocate linked list for callbacks");
|
---|
2760 | result = IOTHUB_CLIENT_ERROR;
|
---|
2761 | }
|
---|
2762 | else
|
---|
2763 | {
|
---|
2764 | IOTHUB_EVENT_CALLBACK* event_callback = NULL;
|
---|
2765 | LIST_ITEM_HANDLE item_handle = singlylinkedlist_find(handleData->event_callbacks, is_event_equal_for_match, (const void*)inputName);
|
---|
2766 | if (item_handle == NULL)
|
---|
2767 | {
|
---|
2768 | // Codes_SRS_IOTHUBCLIENT_LL_31_134: [ `IoTHubClient_LL_SetInputMessageCallback` shall allocate a callback handle to associate callbacks from the transport => client if `inputName` isn't already present in the callback list. ]
|
---|
2769 | event_callback = (IOTHUB_EVENT_CALLBACK*)malloc(sizeof(IOTHUB_EVENT_CALLBACK));
|
---|
2770 | if (event_callback == NULL)
|
---|
2771 | {
|
---|
2772 | LogError("Could not allocate IOTHUB_EVENT_CALLBACK");
|
---|
2773 | result = IOTHUB_CLIENT_ERROR;
|
---|
2774 | }
|
---|
2775 | else
|
---|
2776 | {
|
---|
2777 | memset(event_callback, 0, sizeof(*event_callback));
|
---|
2778 | add_to_list = true;
|
---|
2779 | }
|
---|
2780 | }
|
---|
2781 | else
|
---|
2782 | {
|
---|
2783 | // Codes_SRS_IOTHUBCLIENT_LL_31_135: [ `IoTHubClient_LL_SetInputMessageCallback` shall reuse the existing callback handle if `inputName` is already present in the callback list. ]
|
---|
2784 | event_callback = (IOTHUB_EVENT_CALLBACK*)singlylinkedlist_item_get_value(item_handle);
|
---|
2785 | if (event_callback == NULL)
|
---|
2786 | {
|
---|
2787 | LogError("singlylinkedlist_item_get_value failed looking up event callback");
|
---|
2788 | }
|
---|
2789 | }
|
---|
2790 |
|
---|
2791 | if (event_callback != NULL)
|
---|
2792 | {
|
---|
2793 | if ((inputName != NULL) && (event_callback->inputName == NULL))
|
---|
2794 | {
|
---|
2795 | event_callback->inputName = STRING_construct(inputName);
|
---|
2796 | }
|
---|
2797 |
|
---|
2798 | if ((inputName == NULL) || (event_callback->inputName != NULL))
|
---|
2799 | {
|
---|
2800 | event_callback->callbackAsync = callbackSync;
|
---|
2801 | event_callback->callbackAsyncEx = callbackSyncEx;
|
---|
2802 |
|
---|
2803 | free(event_callback->userContextCallbackEx);
|
---|
2804 | event_callback->userContextCallbackEx = NULL;
|
---|
2805 |
|
---|
2806 | if (userContextCallbackEx == NULL)
|
---|
2807 | {
|
---|
2808 | event_callback->userContextCallback = userContextCallback;
|
---|
2809 | }
|
---|
2810 |
|
---|
2811 | if ((userContextCallbackEx != NULL) &&
|
---|
2812 | (NULL == (event_callback->userContextCallbackEx = malloc(userContextCallbackExLength))))
|
---|
2813 | {
|
---|
2814 | LogError("Unable to allocate userContextCallback");
|
---|
2815 | delete_event(event_callback);
|
---|
2816 | result = IOTHUB_CLIENT_ERROR;
|
---|
2817 | }
|
---|
2818 | else if ((add_to_list == true) && (NULL == singlylinkedlist_add(handleData->event_callbacks, event_callback)))
|
---|
2819 | {
|
---|
2820 | LogError("Unable to add eventCallback to list");
|
---|
2821 | delete_event(event_callback);
|
---|
2822 | result = IOTHUB_CLIENT_ERROR;
|
---|
2823 | }
|
---|
2824 | else
|
---|
2825 | {
|
---|
2826 | if (userContextCallbackEx != NULL)
|
---|
2827 | {
|
---|
2828 | // Codes_SRS_IOTHUBCLIENT_LL_31_141: [`IoTHubClient_LL_SetInputMessageCallbackEx` shall copy the data passed in extended context. ]
|
---|
2829 | memcpy(event_callback->userContextCallbackEx, userContextCallbackEx, userContextCallbackExLength);
|
---|
2830 | }
|
---|
2831 | result = IOTHUB_CLIENT_OK;
|
---|
2832 | }
|
---|
2833 | }
|
---|
2834 | else
|
---|
2835 | {
|
---|
2836 | delete_event(event_callback);
|
---|
2837 | result = IOTHUB_CLIENT_ERROR;
|
---|
2838 | }
|
---|
2839 | }
|
---|
2840 | }
|
---|
2841 |
|
---|
2842 | return result;
|
---|
2843 | }
|
---|
2844 |
|
---|
2845 | static IOTHUB_CLIENT_RESULT remove_event_unsubscribe_if_needed(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, const char* inputName)
|
---|
2846 | {
|
---|
2847 | IOTHUB_CLIENT_RESULT result;
|
---|
2848 |
|
---|
2849 | LIST_ITEM_HANDLE item_handle = singlylinkedlist_find(handleData->event_callbacks, is_event_equal_for_match, (const void*)inputName);
|
---|
2850 | if (item_handle == NULL)
|
---|
2851 | {
|
---|
2852 | // Codes_SRS_IOTHUBCLIENT_LL_31_132: [ If `eventHandlerCallback` is NULL, `IoTHubClient_LL_SetInputMessageCallback` shall return `IOTHUB_CLIENT_ERROR` if the `inputName` is not present. ]
|
---|
2853 | LogError("Input name %s was not present", inputName);
|
---|
2854 | result = IOTHUB_CLIENT_ERROR;
|
---|
2855 | }
|
---|
2856 | else
|
---|
2857 | {
|
---|
2858 | IOTHUB_EVENT_CALLBACK* event_callback = (IOTHUB_EVENT_CALLBACK*)singlylinkedlist_item_get_value(item_handle);
|
---|
2859 | if (event_callback == NULL)
|
---|
2860 | {
|
---|
2861 | LogError("singlylinkedlist_item_get_value failed");
|
---|
2862 | result = IOTHUB_CLIENT_ERROR;
|
---|
2863 | }
|
---|
2864 | else
|
---|
2865 | {
|
---|
2866 | delete_event(event_callback);
|
---|
2867 | // Codes_SRS_IOTHUBCLIENT_LL_31_131: [ If `eventHandlerCallback` is NULL, `IoTHubClient_LL_SetInputMessageCallback` shall remove the `inputName` from its callback list if present. ]
|
---|
2868 | if (singlylinkedlist_remove(handleData->event_callbacks, item_handle) != 0)
|
---|
2869 | {
|
---|
2870 | LogError("singlylinkedlist_remove failed");
|
---|
2871 | result = IOTHUB_CLIENT_ERROR;
|
---|
2872 | }
|
---|
2873 | else
|
---|
2874 | {
|
---|
2875 | if (singlylinkedlist_get_head_item(handleData->event_callbacks) == NULL)
|
---|
2876 | {
|
---|
2877 | // Codes_SRS_IOTHUBCLIENT_LL_31_133: [ If `eventHandlerCallback` is NULL, `IoTHubClient_LL_SetInputMessageCallback` shall invoke `IoTHubTransport_Unsubscribe_InputQueue` if this was the last input callback. ]
|
---|
2878 | handleData->IoTHubTransport_Unsubscribe_InputQueue(handleData);
|
---|
2879 | }
|
---|
2880 | result = IOTHUB_CLIENT_OK;
|
---|
2881 | }
|
---|
2882 | }
|
---|
2883 | }
|
---|
2884 |
|
---|
2885 | return result;
|
---|
2886 | }
|
---|
2887 |
|
---|
2888 |
|
---|
2889 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetInputMessageCallbackImpl(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* inputName, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC eventHandlerCallback, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX eventHandlerCallbackEx, void *userContextCallback, void *userContextCallbackEx, size_t userContextCallbackExLength)
|
---|
2890 | {
|
---|
2891 | IOTHUB_CLIENT_RESULT result;
|
---|
2892 |
|
---|
2893 | if (iotHubClientHandle == NULL)
|
---|
2894 | {
|
---|
2895 | // Codes_SRS_IOTHUBCLIENT_LL_31_130: [ If `iotHubClientHandle` or `inputName` is NULL, `IoTHubClient_LL_SetInputMessageCallback` shall return IOTHUB_CLIENT_INVALID_ARG. ]
|
---|
2896 | LogError("Invalid argument - iotHubClientHandle=%p, inputName=%p", iotHubClientHandle, inputName);
|
---|
2897 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2898 | }
|
---|
2899 | else
|
---|
2900 | {
|
---|
2901 | IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle;
|
---|
2902 | if ((eventHandlerCallback == NULL) && (eventHandlerCallbackEx == NULL))
|
---|
2903 | {
|
---|
2904 | result = (IOTHUB_CLIENT_RESULT)remove_event_unsubscribe_if_needed(handleData, inputName);
|
---|
2905 | }
|
---|
2906 | else
|
---|
2907 | {
|
---|
2908 | bool registered_with_transport_handler = (handleData->event_callbacks != NULL) && (singlylinkedlist_get_head_item(handleData->event_callbacks) != NULL);
|
---|
2909 | if ((result = (IOTHUB_CLIENT_RESULT)create_event_handler_callback(handleData, inputName, eventHandlerCallback, eventHandlerCallbackEx, userContextCallback, userContextCallbackEx, userContextCallbackExLength)) != IOTHUB_CLIENT_OK)
|
---|
2910 | {
|
---|
2911 | LogError("create_event_handler_callback call failed, error = %d", result);
|
---|
2912 | }
|
---|
2913 | // Codes_SRS_IOTHUBCLIENT_LL_31_136: [ `IoTHubClient_LL_SetInputMessageCallback` shall invoke `IoTHubTransport_Subscribe_InputQueue` if this is the first callback being registered. ]
|
---|
2914 | else if (!registered_with_transport_handler && (handleData->IoTHubTransport_Subscribe_InputQueue(handleData->deviceHandle) != 0))
|
---|
2915 | {
|
---|
2916 | LogError("IoTHubTransport_Subscribe_InputQueue failed");
|
---|
2917 | delete_event_callback_list(handleData);
|
---|
2918 | result = IOTHUB_CLIENT_ERROR;
|
---|
2919 | }
|
---|
2920 | else
|
---|
2921 | {
|
---|
2922 | result = IOTHUB_CLIENT_OK;
|
---|
2923 | }
|
---|
2924 | }
|
---|
2925 | }
|
---|
2926 | return result;
|
---|
2927 |
|
---|
2928 | }
|
---|
2929 |
|
---|
2930 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetInputMessageCallbackEx(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* inputName, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX eventHandlerCallbackEx, void *userContextCallbackEx, size_t userContextCallbackExLength)
|
---|
2931 | {
|
---|
2932 | return IoTHubClientCore_LL_SetInputMessageCallbackImpl(iotHubClientHandle, inputName, NULL, eventHandlerCallbackEx, NULL, userContextCallbackEx, userContextCallbackExLength);
|
---|
2933 | }
|
---|
2934 |
|
---|
2935 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetInputMessageCallback(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* inputName, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC eventHandlerCallback, void* userContextCallback)
|
---|
2936 | {
|
---|
2937 | return IoTHubClientCore_LL_SetInputMessageCallbackImpl(iotHubClientHandle, inputName, eventHandlerCallback, NULL, userContextCallback, NULL, 0);
|
---|
2938 | }
|
---|
2939 |
|
---|
2940 | int IoTHubClientCore_LL_GetTransportCallbacks(TRANSPORT_CALLBACKS_INFO* transport_cb)
|
---|
2941 | {
|
---|
2942 | int result;
|
---|
2943 | if (transport_cb == NULL)
|
---|
2944 | {
|
---|
2945 | LogError("Invalid parameter transport callback can not be NULL");
|
---|
2946 | result = MU_FAILURE;
|
---|
2947 | }
|
---|
2948 | else
|
---|
2949 | {
|
---|
2950 | transport_cb->send_complete_cb = IoTHubClientCore_LL_SendComplete;
|
---|
2951 | transport_cb->twin_retrieve_prop_complete_cb = IoTHubClientCore_LL_RetrievePropertyComplete;
|
---|
2952 | transport_cb->twin_rpt_state_complete_cb = IoTHubClientCore_LL_ReportedStateComplete;
|
---|
2953 | transport_cb->connection_status_cb = IoTHubClientCore_LL_ConnectionStatusCallBack;
|
---|
2954 | transport_cb->prod_info_cb = IoTHubClientCore_LL_GetProductInfo;
|
---|
2955 | transport_cb->msg_input_cb = IoTHubClientCore_LL_MessageCallbackFromInput;
|
---|
2956 | transport_cb->msg_cb = IoTHubClientCore_LL_MessageCallback;
|
---|
2957 | transport_cb->method_complete_cb = IoTHubClientCore_LL_DeviceMethodComplete;
|
---|
2958 | result = 0;
|
---|
2959 | }
|
---|
2960 | return result;
|
---|
2961 | }
|
---|
2962 |
|
---|
2963 | #ifdef USE_EDGE_MODULES
|
---|
2964 | /* These should be replaced during iothub_client refactor */
|
---|
2965 | IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_GenericMethodInvoke(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* deviceId, const char* moduleId, const char* methodName, const char* methodPayload, unsigned int timeout, int* responseStatus, unsigned char** responsePayload, size_t* responsePayloadSize)
|
---|
2966 | {
|
---|
2967 | IOTHUB_CLIENT_RESULT result;
|
---|
2968 | if (iotHubClientHandle != NULL)
|
---|
2969 | {
|
---|
2970 | if (moduleId != NULL)
|
---|
2971 | {
|
---|
2972 | result = IoTHubClient_Edge_ModuleMethodInvoke(iotHubClientHandle->methodHandle, deviceId, moduleId, methodName, methodPayload, timeout, responseStatus, responsePayload, responsePayloadSize);
|
---|
2973 | }
|
---|
2974 | else
|
---|
2975 | {
|
---|
2976 | result = IoTHubClient_Edge_DeviceMethodInvoke(iotHubClientHandle->methodHandle, deviceId, methodName, methodPayload, timeout, responseStatus, responsePayload, responsePayloadSize);
|
---|
2977 |
|
---|
2978 | }
|
---|
2979 | }
|
---|
2980 | else
|
---|
2981 | {
|
---|
2982 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
2983 | }
|
---|
2984 | return result;
|
---|
2985 | }
|
---|
2986 | #endif
|
---|
2987 |
|
---|
2988 | /*end*/
|
---|
2989 |
|
---|