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