1 /**
2 * @file aiot_dynreg_api.c
3 * @brief dynreg模块的API接口实现, 提供获取设备信息的能力
4 *
5 * @copyright Copyright (C) 2015-2020 Alibaba Group Holding Limited
6 *
7 */
8 #include "dynreg_private.h"
9
10 #include "core_string.h"
11 #include "core_log.h"
12 #include "core_auth.h"
13
_dynreg_exec_inc(dynreg_handle_t * dynreg_handle)14 static void _dynreg_exec_inc(dynreg_handle_t *dynreg_handle)
15 {
16 dynreg_handle->sysdep->core_sysdep_mutex_lock(dynreg_handle->data_mutex);
17 dynreg_handle->exec_count++;
18 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
19 }
20
_dynreg_exec_dec(dynreg_handle_t * dynreg_handle)21 static void _dynreg_exec_dec(dynreg_handle_t *dynreg_handle)
22 {
23 dynreg_handle->sysdep->core_sysdep_mutex_lock(dynreg_handle->data_mutex);
24 dynreg_handle->exec_count--;
25 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
26 }
27
_dynreg_sign(dynreg_handle_t * dynreg_handle,char * random,char sign_str[65])28 static int32_t _dynreg_sign(dynreg_handle_t *dynreg_handle, char *random, char sign_str[65])
29 {
30 int32_t res = STATE_SUCCESS;
31 uint8_t sign_hex[32] = {0};
32 char *src_fmt = "deviceName%sproductKey%srandom%s";
33 char *src[] = {dynreg_handle->device_name, dynreg_handle->product_key, random};
34 char *plain_text = NULL;
35
36 res = core_sprintf(dynreg_handle->sysdep, &plain_text, src_fmt, src, sizeof(src) / sizeof(char *), DYNREG_MODULE_NAME);
37 if (res < STATE_SUCCESS) {
38 return res;
39 }
40
41 core_hmac_sha256((const uint8_t *)plain_text, (uint32_t)strlen(plain_text),
42 (const uint8_t *)dynreg_handle->product_secret, (uint32_t)strlen(dynreg_handle->product_secret), sign_hex);
43 core_hex2str(sign_hex, 32, sign_str, 0);
44
45 dynreg_handle->sysdep->core_sysdep_free(plain_text);
46
47 return STATE_SUCCESS;
48 }
49
_dynreg_recv_handler(void * handle,const aiot_http_recv_t * packet,void * userdata)50 static void _dynreg_recv_handler(void *handle, const aiot_http_recv_t *packet, void *userdata)
51 {
52 dynreg_handle_t *dynreg_handle = (dynreg_handle_t *)userdata;
53
54 if (dynreg_handle->recv_handler == NULL) {
55 return;
56 }
57
58 switch (packet->type) {
59 case AIOT_HTTPRECV_STATUS_CODE: {
60 dynreg_handle->response.code = packet->data.status_code.code;
61 }
62 break;
63 case AIOT_HTTPRECV_HEADER: {
64 if ((strlen(packet->data.header.key) == strlen("Content-Length")) &&
65 (memcmp(packet->data.header.key, "Content-Length", strlen(packet->data.header.key)) == 0)) {
66 core_str2uint(packet->data.header.value, (uint8_t)strlen(packet->data.header.value),
67 &dynreg_handle->response.content_total_len);
68 }
69 }
70 break;
71 case AIOT_HTTPRECV_BODY: {
72 uint8_t *content = dynreg_handle->sysdep->core_sysdep_malloc(dynreg_handle->response.content_len + packet->data.body.len
73 + 1,
74 CORE_HTTP_MODULE_NAME);
75 if (content == NULL) {
76 return;
77 }
78 memset(content, 0, dynreg_handle->response.content_len + packet->data.body.len + 1);
79 if (content != NULL) {
80 memcpy(content, dynreg_handle->response.content, dynreg_handle->response.content_len);
81 dynreg_handle->sysdep->core_sysdep_free(dynreg_handle->response.content);
82 }
83 memcpy(content + dynreg_handle->response.content_len, packet->data.body.buffer, packet->data.body.len);
84 dynreg_handle->response.content = content;
85 dynreg_handle->response.content_len = dynreg_handle->response.content_len + packet->data.body.len;
86 }
87 break;
88 default: {
89
90 }
91 break;
92 }
93 }
94
_dynreg_device_info(dynreg_handle_t * dynreg_handle,char ** device_secret)95 static int32_t _dynreg_device_info(dynreg_handle_t *dynreg_handle, char **device_secret)
96 {
97 int32_t res = STATE_SUCCESS;
98 char *tmp_ds = NULL, *ds_key = "deviceSecret";
99 char *ds_value = NULL;
100 uint32_t ds_value_len = 0;
101
102 if (dynreg_handle->response.code != 200) {
103 return STATE_DYNREG_INVALID_STATUS_CODE;
104 }
105
106 if ((res = core_json_value((char *)dynreg_handle->response.content, dynreg_handle->response.content_len, ds_key,
107 strlen(ds_key), &ds_value, &ds_value_len)) < STATE_SUCCESS) {
108 return STATE_DYNREG_INVALID_DEVICE_SECRET;
109 }
110
111 tmp_ds = dynreg_handle->sysdep->core_sysdep_malloc(ds_value_len + 1, DYNREG_MODULE_NAME);
112 if (tmp_ds == NULL) {
113 return STATE_SYS_DEPEND_MALLOC_FAILED;
114 }
115 memset(tmp_ds, 0, ds_value_len + 1);
116 memcpy(tmp_ds, ds_value, ds_value_len);
117
118 *device_secret = tmp_ds;
119
120 return STATE_SUCCESS;
121 }
122
aiot_dynreg_init(void)123 void *aiot_dynreg_init(void)
124 {
125 dynreg_handle_t *dynreg_handle = NULL;
126 aiot_sysdep_portfile_t *sysdep = NULL;
127
128 sysdep = aiot_sysdep_get_portfile();
129 if (sysdep == NULL) {
130 return NULL;
131 }
132
133 dynreg_handle = sysdep->core_sysdep_malloc(sizeof(dynreg_handle_t), DYNREG_MODULE_NAME);
134 if (dynreg_handle == NULL) {
135 return NULL;
136 }
137 memset(dynreg_handle, 0, sizeof(dynreg_handle_t));
138
139 dynreg_handle->sysdep = sysdep;
140 dynreg_handle->response_body_len = DYNREG_RESPONSE_BODY_LEN;
141 dynreg_handle->timeout_ms = DYNREG_DEFAULT_TIMEOUT_MS;
142 dynreg_handle->deinit_timeout_ms = DYNREG_DEFAULT_DEINIT_TIMEOUT_MS;
143 dynreg_handle->send_timeout_ms = DYNREG_DEFAULT_SEND_TIMEOUT;
144 dynreg_handle->recv_timeout_ms = DYNREG_DEFAULT_RECV_TIMEOUT;
145 dynreg_handle->data_mutex = dynreg_handle->sysdep->core_sysdep_mutex_init();
146
147 dynreg_handle->exec_enabled = 1;
148
149 return dynreg_handle;
150 }
151
aiot_dynreg_setopt(void * handle,aiot_dynreg_option_t option,void * data)152 int32_t aiot_dynreg_setopt(void *handle, aiot_dynreg_option_t option, void *data)
153 {
154 int32_t res = STATE_SUCCESS;
155 dynreg_handle_t *dynreg_handle = (dynreg_handle_t *)handle;
156
157 if (dynreg_handle == NULL || data == NULL) {
158 return STATE_USER_INPUT_NULL_POINTER;
159 }
160
161 if (option >= AIOT_DYNREGOPT_MAX) {
162 return STATE_USER_INPUT_OUT_RANGE;
163 }
164
165 if (dynreg_handle->exec_enabled == 0) {
166 return STATE_USER_INPUT_EXEC_DISABLED;
167 }
168
169 _dynreg_exec_inc(dynreg_handle);
170
171 dynreg_handle->sysdep->core_sysdep_mutex_lock(dynreg_handle->data_mutex);
172 switch (option) {
173 case AIOT_DYNREGOPT_NETWORK_CRED: {
174 if (dynreg_handle->cred != NULL) {
175 dynreg_handle->sysdep->core_sysdep_free(dynreg_handle->cred);
176 dynreg_handle->cred = NULL;
177 }
178 dynreg_handle->cred = dynreg_handle->sysdep->core_sysdep_malloc(sizeof(aiot_sysdep_network_cred_t), DYNREG_MODULE_NAME);
179 if (dynreg_handle->cred != NULL) {
180 memset(dynreg_handle->cred, 0, sizeof(aiot_sysdep_network_cred_t));
181 memcpy(dynreg_handle->cred, data, sizeof(aiot_sysdep_network_cred_t));
182 } else {
183 res = STATE_SYS_DEPEND_MALLOC_FAILED;
184 }
185 }
186 break;
187 case AIOT_DYNREGOPT_HOST: {
188 res = core_strdup(dynreg_handle->sysdep, &dynreg_handle->host, data, DYNREG_MODULE_NAME);
189 }
190 break;
191 case AIOT_DYNREGOPT_PORT: {
192 dynreg_handle->port = *(uint16_t *)data;
193 }
194 break;
195 case AIOT_DYNREGOPT_PRODUCT_KEY: {
196 res = core_strdup(dynreg_handle->sysdep, &dynreg_handle->product_key, data, DYNREG_MODULE_NAME);
197 }
198 break;
199 case AIOT_DYNREGOPT_PRODUCT_SECRET: {
200 res = core_strdup(dynreg_handle->sysdep, &dynreg_handle->product_secret, data, DYNREG_MODULE_NAME);
201 }
202 break;
203 case AIOT_DYNREGOPT_DEVICE_NAME: {
204 res = core_strdup(dynreg_handle->sysdep, &dynreg_handle->device_name, data, DYNREG_MODULE_NAME);
205 }
206 break;
207 case AIOT_DYNREGOPT_SEND_TIMEOUT_MS: {
208 dynreg_handle->send_timeout_ms = *(uint32_t *)data;
209 }
210 break;
211 case AIOT_DYNREGOPT_RECV_TIMEOUT_MS: {
212 dynreg_handle->recv_timeout_ms = *(uint32_t *)data;
213 }
214 break;
215 case AIOT_DYNREGOPT_RECV_HANDLER: {
216 dynreg_handle->recv_handler = (aiot_dynreg_recv_handler_t)data;
217 }
218 break;
219 case AIOT_DYNREGOPT_USERDATA: {
220 dynreg_handle->userdata = data;
221 }
222 break;
223 case AIOT_DYNREGOPT_TIMEOUT_MS: {
224 dynreg_handle->timeout_ms = *(uint32_t *)data;
225 }
226 break;
227 case AIOT_DYNREGOPT_DEINIT_TIMEOUT_MS: {
228 dynreg_handle->deinit_timeout_ms = *(uint32_t *)data;
229 }
230 break;
231 default: {
232 res = STATE_USER_INPUT_UNKNOWN_OPTION;
233 }
234 break;
235 }
236 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
237
238 _dynreg_exec_dec(dynreg_handle);
239
240 return res;
241 }
242
aiot_dynreg_deinit(void ** handle)243 int32_t aiot_dynreg_deinit(void **handle)
244 {
245 uint64_t deinit_timestart = 0;
246 dynreg_handle_t *dynreg_handle = NULL;
247 aiot_sysdep_portfile_t *sysdep = NULL;
248
249 if (handle == NULL || *handle == NULL) {
250 return STATE_USER_INPUT_NULL_POINTER;
251 }
252
253 dynreg_handle = *(dynreg_handle_t **)handle;
254 sysdep = dynreg_handle->sysdep;
255
256 if (dynreg_handle->exec_enabled == 0) {
257 return STATE_USER_INPUT_EXEC_DISABLED;
258 }
259
260 dynreg_handle->exec_enabled = 0;
261 deinit_timestart = dynreg_handle->sysdep->core_sysdep_time();
262 do {
263 if (dynreg_handle->exec_count == 0) {
264 break;
265 }
266 dynreg_handle->sysdep->core_sysdep_sleep(DYNREG_DEINIT_INTERVAL_MS);
267 } while ((dynreg_handle->sysdep->core_sysdep_time() - deinit_timestart) < dynreg_handle->deinit_timeout_ms);
268
269 if (dynreg_handle->exec_count != 0) {
270 return STATE_DYNREG_DEINIT_TIMEOUT;
271 }
272
273 *handle = NULL;
274
275 if (dynreg_handle->response.content != NULL) {
276 sysdep->core_sysdep_free(dynreg_handle->response.content);
277 }
278 memset(&dynreg_handle->response, 0, sizeof(core_http_response_t));
279
280 if (dynreg_handle->http_handle != NULL) {
281 core_http_deinit(&dynreg_handle->http_handle);
282 }
283
284 if (dynreg_handle->host != NULL) {
285 sysdep->core_sysdep_free(dynreg_handle->host);
286 }
287
288 if (dynreg_handle->product_key != NULL) {
289 sysdep->core_sysdep_free(dynreg_handle->product_key);
290 }
291
292 if (dynreg_handle->product_secret != NULL) {
293 sysdep->core_sysdep_free(dynreg_handle->product_secret);
294 }
295
296 if (dynreg_handle->device_name != NULL) {
297 sysdep->core_sysdep_free(dynreg_handle->device_name);
298 }
299
300 if (dynreg_handle->cred != NULL) {
301 sysdep->core_sysdep_free(dynreg_handle->cred);
302 }
303
304 sysdep->core_sysdep_mutex_deinit(&dynreg_handle->data_mutex);
305
306 sysdep->core_sysdep_free(dynreg_handle);
307
308 return STATE_SUCCESS;
309 }
310
aiot_dynreg_send_request(void * handle)311 int32_t aiot_dynreg_send_request(void *handle)
312 {
313 int32_t res = STATE_SUCCESS;
314 dynreg_handle_t *dynreg_handle = (dynreg_handle_t *)handle;
315
316 if (dynreg_handle == NULL) {
317 return STATE_USER_INPUT_NULL_POINTER;
318 }
319
320 if (dynreg_handle->host == NULL) {
321 return STATE_USER_INPUT_MISSING_HOST;
322 }
323
324 if (dynreg_handle->product_key == NULL) {
325 return STATE_USER_INPUT_MISSING_PRODUCT_KEY;
326 }
327
328 if (dynreg_handle->product_secret == NULL) {
329 return STATE_USER_INPUT_MISSING_PRODUCT_SECRET;
330 }
331
332 if (dynreg_handle->device_name == NULL) {
333 return STATE_USER_INPUT_MISSING_DEVICE_NAME;
334 }
335
336 if (dynreg_handle->exec_enabled == 0) {
337 return STATE_USER_INPUT_EXEC_DISABLED;
338 }
339
340 _dynreg_exec_inc(dynreg_handle);
341
342 dynreg_handle->sysdep->core_sysdep_mutex_lock(dynreg_handle->data_mutex);
343 if (dynreg_handle->response.content != NULL) {
344 dynreg_handle->sysdep->core_sysdep_free(dynreg_handle->response.content);
345 }
346 memset(&dynreg_handle->response, 0, sizeof(core_http_response_t));
347
348 if (dynreg_handle->http_handle != NULL) {
349 core_http_deinit(&dynreg_handle->http_handle);
350 }
351
352 dynreg_handle->http_handle = core_http_init();
353 if (dynreg_handle->http_handle == NULL) {
354 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
355 _dynreg_exec_dec(dynreg_handle);
356 return STATE_SYS_DEPEND_MALLOC_FAILED;
357 }
358
359 if (((res = core_http_setopt(dynreg_handle->http_handle, CORE_HTTPOPT_HOST,
360 (void *)dynreg_handle->host)) < STATE_SUCCESS) ||
361 ((res = core_http_setopt(dynreg_handle->http_handle, CORE_HTTPOPT_PORT, (void *)&dynreg_handle->port)) < STATE_SUCCESS)
362 ||
363 ((res = core_http_setopt(dynreg_handle->http_handle, CORE_HTTPOPT_NETWORK_CRED,
364 (void *)dynreg_handle->cred)) < STATE_SUCCESS) ||
365 ((res = core_http_setopt(dynreg_handle->http_handle, CORE_HTTPOPT_SEND_TIMEOUT_MS,
366 (void *)&dynreg_handle->send_timeout_ms)) < STATE_SUCCESS) ||
367 ((res = core_http_setopt(dynreg_handle->http_handle, CORE_HTTPOPT_RECV_TIMEOUT_MS,
368 (void *)&dynreg_handle->recv_timeout_ms)) < STATE_SUCCESS) ||
369 ((res = core_http_setopt(dynreg_handle->http_handle, CORE_HTTPOPT_BODY_BUFFER_MAX_LEN,
370 (void *)&dynreg_handle->response_body_len)) < STATE_SUCCESS) ||
371 ((res = core_http_setopt(dynreg_handle->http_handle, CORE_HTTPOPT_RECV_HANDLER,
372 (void *)_dynreg_recv_handler)) < STATE_SUCCESS) ||
373 ((res = core_http_setopt(dynreg_handle->http_handle, CORE_HTTPOPT_USERDATA, (void *)dynreg_handle)) < STATE_SUCCESS)) {
374 core_http_deinit(&dynreg_handle->http_handle);
375 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
376 _dynreg_exec_dec(dynreg_handle);
377 return res;
378 }
379
380 res = core_http_connect(dynreg_handle->http_handle);
381 if (res < STATE_SUCCESS) {
382 core_http_deinit(&dynreg_handle->http_handle);
383 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
384 _dynreg_exec_dec(dynreg_handle);
385 return res;
386 }
387
388 {
389 uint32_t random_num = 0;
390 char random[11] = {0};
391 char sign_str[65] = {0};
392 char *content = NULL;
393 char *content_fmt = "productKey=%s&deviceName=%s&random=%s&sign=%s&signMethod=hmacsha256";
394 char *content_src[] = { dynreg_handle->product_key, dynreg_handle->device_name, (char *)random, sign_str };
395 core_http_request_t request;
396
397 dynreg_handle->sysdep->core_sysdep_rand((uint8_t *)&random_num, 4);
398 core_uint2str(random_num, random, NULL);
399
400 res = _dynreg_sign(dynreg_handle, (char *)random, sign_str);
401 if (res < STATE_SUCCESS) {
402 core_http_deinit(&dynreg_handle->http_handle);
403 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
404 _dynreg_exec_dec(dynreg_handle);
405 return res;
406 }
407
408
409 memset(&request, 0, sizeof(core_http_request_t));
410 res = core_sprintf(dynreg_handle->sysdep, &content, content_fmt, content_src, sizeof(content_src) / sizeof(char *),
411 DYNREG_MODULE_NAME);
412 if (res < STATE_SUCCESS) {
413 core_http_deinit(&dynreg_handle->http_handle);
414 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
415 _dynreg_exec_dec(dynreg_handle);
416 return res;
417 }
418 request.method = "POST";
419 request.path = DYNREG_PATH;
420 request.header = "Accept: text/xml,text/javascript,text/html,application/json\r\n" \
421 "Content-Type: application/x-www-form-urlencoded\r\n";
422 request.content = (uint8_t *)content;
423 request.content_len = (uint32_t)strlen(content);
424
425 res = core_http_send(dynreg_handle->http_handle, &request);
426 dynreg_handle->sysdep->core_sysdep_free(content);
427 if (res < STATE_SUCCESS) {
428 core_http_deinit(&dynreg_handle->http_handle);
429 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
430 _dynreg_exec_dec(dynreg_handle);
431 return res;
432 }
433 }
434 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
435 _dynreg_exec_dec(dynreg_handle);
436
437 return res;
438 }
439
aiot_dynreg_recv(void * handle)440 int32_t aiot_dynreg_recv(void *handle)
441 {
442 int32_t res = STATE_SUCCESS;
443 uint64_t timenow_ms = 0;
444 dynreg_handle_t *dynreg_handle = (dynreg_handle_t *)handle;
445 char *device_secret = NULL;
446 aiot_dynreg_recv_t packet;
447
448 if (dynreg_handle == NULL) {
449 return STATE_USER_INPUT_NULL_POINTER;
450 }
451
452 if (dynreg_handle->http_handle == NULL) {
453 return STATE_DYNREG_NEED_SEND_REQUEST;
454 }
455
456 if (dynreg_handle->exec_enabled == 0) {
457 return STATE_USER_INPUT_EXEC_DISABLED;
458 }
459
460 _dynreg_exec_inc(dynreg_handle);
461
462 dynreg_handle->sysdep->core_sysdep_mutex_lock(dynreg_handle->data_mutex);
463 timenow_ms = dynreg_handle->sysdep->core_sysdep_time();
464 while (1) {
465 if (timenow_ms >= dynreg_handle->sysdep->core_sysdep_time()) {
466 timenow_ms = dynreg_handle->sysdep->core_sysdep_time();
467 }
468 if (dynreg_handle->sysdep->core_sysdep_time() - timenow_ms >= dynreg_handle->timeout_ms) {
469 break;
470 }
471
472 res = core_http_recv(dynreg_handle->http_handle);
473 if (res < STATE_SUCCESS) {
474 break;
475 }
476 }
477
478 if (res < STATE_SUCCESS) {
479 if (res != STATE_HTTP_READ_BODY_FINISHED) {
480 if (dynreg_handle->response.content != NULL) {
481 dynreg_handle->sysdep->core_sysdep_free(dynreg_handle->response.content);
482 memset(&dynreg_handle->response, 0, sizeof(core_http_response_t));
483 }
484 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
485 _dynreg_exec_dec(dynreg_handle);
486 return res;
487 } else {
488 res = STATE_SUCCESS;
489 }
490 } else {
491 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
492 _dynreg_exec_dec(dynreg_handle);
493 return STATE_HTTP_RECV_NOT_FINISHED;
494 }
495
496 if (dynreg_handle->recv_handler != NULL) {
497 packet.type = AIOT_DYNREGRECV_STATUS_CODE;
498 packet.data.status_code.code = dynreg_handle->response.code;
499
500 dynreg_handle->recv_handler(dynreg_handle, &packet, dynreg_handle->userdata);
501 }
502
503 res = _dynreg_device_info(dynreg_handle, &device_secret);
504 dynreg_handle->sysdep->core_sysdep_mutex_unlock(dynreg_handle->data_mutex);
505 if (res < STATE_SUCCESS) {
506 _dynreg_exec_dec(dynreg_handle);
507 return res;
508 }
509
510 memset(&packet, 0, sizeof(aiot_dynreg_recv_t));
511 if (dynreg_handle->recv_handler != NULL) {
512 packet.type = AIOT_DYNREGRECV_DEVICE_INFO;
513 packet.data.device_info.device_secret = device_secret;
514
515 dynreg_handle->recv_handler(dynreg_handle, &packet, dynreg_handle->userdata);
516 }
517 dynreg_handle->sysdep->core_sysdep_free(device_secret);
518
519 _dynreg_exec_dec(dynreg_handle);
520 return STATE_SUCCESS;
521 }
522
523