1 /**
2  * @file aiot_http_api.c
3  * @brief HTTP模块实现, 其中包含了向物联网平台认证和上报数据的API接口
4  * @date 2019-12-27
5  *
6  * @copyright Copyright (C) 2015-2018 Alibaba Group Holding Limited
7  *
8  */
9 
10 #include "core_http.h"
11 
_core_http_exec_inc(core_http_handle_t * http_handle)12 static void _core_http_exec_inc(core_http_handle_t *http_handle)
13 {
14     http_handle->sysdep->core_sysdep_mutex_lock(http_handle->data_mutex);
15     http_handle->core_exec_count++;
16     http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->data_mutex);
17 }
18 
_core_http_exec_dec(core_http_handle_t * http_handle)19 static void _core_http_exec_dec(core_http_handle_t *http_handle)
20 {
21     http_handle->sysdep->core_sysdep_mutex_lock(http_handle->data_mutex);
22     http_handle->core_exec_count--;
23     http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->data_mutex);
24 }
25 
_core_http_sysdep_return(int32_t sysdep_code,int32_t core_code)26 static int32_t _core_http_sysdep_return(int32_t sysdep_code, int32_t core_code)
27 {
28     if (sysdep_code >= (STATE_PORT_BASE - 0x00FF) && sysdep_code < (STATE_PORT_BASE)) {
29         return sysdep_code;
30     } else {
31         return core_code;
32     }
33 }
34 
_core_http_connect(core_http_handle_t * http_handle)35 static int32_t _core_http_connect(core_http_handle_t *http_handle)
36 {
37     int32_t res = STATE_SUCCESS;
38 
39     /* disconnect first if network is already established */
40     if (http_handle->network_handle != NULL) {
41         http_handle->sysdep->core_sysdep_network_deinit(&http_handle->network_handle);
42     }
43 
44     /* establish network connection */
45     core_sysdep_socket_type_t socket_type = CORE_SYSDEP_SOCKET_TCP_CLIENT;
46 
47     if (http_handle->host == NULL) {
48         return STATE_USER_INPUT_MISSING_HOST;
49     }
50 
51     http_handle->network_handle = http_handle->sysdep->core_sysdep_network_init();
52     if (http_handle->network_handle == NULL) {
53         return STATE_SYS_DEPEND_MALLOC_FAILED;
54     }
55 
56     if ((res = http_handle->sysdep->core_sysdep_network_setopt(http_handle->network_handle, CORE_SYSDEP_NETWORK_SOCKET_TYPE,
57                &socket_type)) < 0 ||
58         (res = http_handle->sysdep->core_sysdep_network_setopt(http_handle->network_handle, CORE_SYSDEP_NETWORK_HOST,
59                 http_handle->host)) < 0 ||
60         (res = http_handle->sysdep->core_sysdep_network_setopt(http_handle->network_handle, CORE_SYSDEP_NETWORK_PORT,
61                 &http_handle->port)) < 0 ||
62         (res = http_handle->sysdep->core_sysdep_network_setopt(http_handle->network_handle,
63                 CORE_SYSDEP_NETWORK_CONNECT_TIMEOUT_MS,
64                 &http_handle->connect_timeout_ms)) < 0) {
65         http_handle->sysdep->core_sysdep_network_deinit(&http_handle->network_handle);
66         return _core_http_sysdep_return(res, STATE_SYS_DEPEND_NWK_INVALID_OPTION);
67     }
68 
69     if (http_handle->cred != NULL) {
70         res = http_handle->sysdep->core_sysdep_network_setopt(http_handle->network_handle, CORE_SYSDEP_NETWORK_CRED,
71                 http_handle->cred);
72         if (res < STATE_SUCCESS) {
73             http_handle->sysdep->core_sysdep_network_deinit(&http_handle->network_handle);
74             return _core_http_sysdep_return(res, STATE_SYS_DEPEND_NWK_INVALID_CRED);
75         }
76     }
77 
78     res = http_handle->sysdep->core_sysdep_network_establish(http_handle->network_handle);
79     if (res < STATE_SUCCESS) {
80         http_handle->sysdep->core_sysdep_network_deinit(&http_handle->network_handle);
81         return _core_http_sysdep_return(res, STATE_SYS_DEPEND_NWK_EST_FAILED);
82     }
83 
84     return STATE_SUCCESS;
85 }
86 
_core_http_send(core_http_handle_t * http_handle,uint8_t * buffer,uint32_t len,uint32_t timeout_ms)87 static int32_t _core_http_send(core_http_handle_t *http_handle, uint8_t *buffer, uint32_t len, uint32_t timeout_ms)
88 {
89     int32_t res = STATE_SUCCESS;
90 
91     if (http_handle->network_handle != NULL) {
92         res = http_handle->sysdep->core_sysdep_network_send(http_handle->network_handle, buffer, len, timeout_ms, NULL);
93         if (res < STATE_SUCCESS) {
94             http_handle->sysdep->core_sysdep_network_deinit(&http_handle->network_handle);
95             core_log(http_handle->sysdep, STATE_HTTP_LOG_DISCONNECT, "HTTP network error when sending data, disconnect\r\n");
96             res = _core_http_sysdep_return(res, STATE_SYS_DEPEND_NWK_SEND_ERR);
97         } else if (res != len) {
98             res = STATE_SYS_DEPEND_NWK_WRITE_LESSDATA;
99         }
100     } else {
101         res = STATE_SYS_DEPEND_NWK_CLOSED;
102     }
103 
104     return res;
105 }
106 
_core_http_send_body(core_http_handle_t * http_handle,uint8_t * content,uint32_t len)107 static int32_t _core_http_send_body(core_http_handle_t *http_handle, uint8_t *content, uint32_t len)
108 {
109     int32_t res = STATE_SUCCESS;
110 
111     core_log_hexdump(STATE_HTTP_LOG_SEND_CONTENT, '>', content, len);
112 
113     http_handle->sysdep->core_sysdep_mutex_lock(http_handle->send_mutex);
114     res = _core_http_send(http_handle, content, len, http_handle->send_timeout_ms);
115     http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->send_mutex);
116 
117     return res;
118 }
119 
_core_http_header_print(core_http_handle_t * http_handle,char * prefix,char * header,uint32_t header_len)120 static void _core_http_header_print(core_http_handle_t *http_handle, char *prefix, char *header, uint32_t header_len)
121 {
122     char *prev = header, *pos = header;
123     uint32_t line_len = 0;
124     while (pos != header + header_len) {
125         if (*(pos) == '\n' && *(pos - 1) == '\r') {
126             line_len = (uint32_t)(pos - prev + 1);
127             core_log3(http_handle->sysdep, STATE_HTTP_LOG_SEND_HEADER, "%s %.*s", prefix, &line_len, prev);
128             prev = pos + 1;
129         }
130         pos++;
131     }
132 }
133 
_core_http_send_header(core_http_handle_t * http_handle,char * method,char * path,char * host,char * header,char * content_lenstr)134 static int32_t _core_http_send_header(core_http_handle_t *http_handle, char *method, char *path, char *host,
135                                       char *header, char *content_lenstr)
136 {
137     int32_t res = STATE_SUCCESS;
138     char *combine_header = NULL;
139     char *combine_header_src[] = { method, path, host, header, content_lenstr};
140     uint32_t combine_header_len = 0;
141 
142     res = core_sprintf(http_handle->sysdep, &combine_header, "%s %s HTTP/1.1\r\nHost: %s\r\n%sContent-Length: %s\r\n\r\n",
143                        combine_header_src, sizeof(combine_header_src) / sizeof(char *), CORE_HTTP_MODULE_NAME);
144     if (res < STATE_SUCCESS) {
145         return res;
146     }
147     combine_header_len = (uint32_t)strlen(combine_header);
148 
149     _core_http_header_print(http_handle, ">", combine_header, combine_header_len);
150 
151     http_handle->sysdep->core_sysdep_mutex_lock(http_handle->send_mutex);
152     res = _core_http_send(http_handle, (uint8_t *)combine_header, combine_header_len, http_handle->send_timeout_ms);
153     http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->send_mutex);
154 
155     http_handle->sysdep->core_sysdep_free(combine_header);
156 
157     return res;
158 }
159 
core_http_init(void)160 void *core_http_init(void)
161 {
162     core_http_handle_t *http_handle = NULL;
163     aiot_sysdep_portfile_t *sysdep = NULL;
164 
165     sysdep = aiot_sysdep_get_portfile();
166     if (sysdep == NULL) {
167         return NULL;
168     }
169 
170     http_handle = sysdep->core_sysdep_malloc(sizeof(core_http_handle_t), CORE_HTTP_MODULE_NAME);
171     if (http_handle == NULL) {
172         return NULL;
173     }
174     memset(http_handle, 0, sizeof(core_http_handle_t));
175 
176     http_handle->sysdep = sysdep;
177     http_handle->connect_timeout_ms = CORE_HTTP_DEFAULT_CONNECT_TIMEOUT_MS;
178     http_handle->send_timeout_ms = CORE_HTTP_DEFAULT_SEND_TIMEOUT_MS;
179     http_handle->recv_timeout_ms = CORE_HTTP_DEFAULT_RECV_TIMEOUT_MS;
180     http_handle->header_line_max_len = CORE_HTTP_DEFAULT_HEADER_LINE_MAX_LEN;
181     http_handle->body_buffer_max_len = CORE_HTTP_DEFAULT_BODY_MAX_LEN;
182     http_handle->deinit_timeout_ms = CORE_HTTP_DEFAULT_DEINIT_TIMEOUT_MS;
183 
184     http_handle->data_mutex = http_handle->sysdep->core_sysdep_mutex_init();
185     http_handle->send_mutex = http_handle->sysdep->core_sysdep_mutex_init();
186     http_handle->recv_mutex = http_handle->sysdep->core_sysdep_mutex_init();
187 
188     http_handle->core_exec_enabled = 1;
189 
190     return http_handle;
191 }
192 
core_http_setopt(void * handle,core_http_option_t option,void * data)193 int32_t core_http_setopt(void *handle, core_http_option_t option, void *data)
194 {
195     int32_t res = STATE_SUCCESS;
196     core_http_handle_t *http_handle = (core_http_handle_t *)handle;
197 
198     if (http_handle == NULL || data == NULL) {
199         return STATE_USER_INPUT_NULL_POINTER;
200     }
201 
202     if (option >= CORE_HTTPOPT_MAX) {
203         return STATE_USER_INPUT_OUT_RANGE;
204     }
205 
206     if (http_handle->core_exec_enabled == 0) {
207         return STATE_USER_INPUT_EXEC_DISABLED;
208     }
209 
210     _core_http_exec_inc(http_handle);
211 
212     http_handle->sysdep->core_sysdep_mutex_lock(http_handle->data_mutex);
213     switch (option) {
214         case CORE_HTTPOPT_HOST: {
215             res = core_strdup(http_handle->sysdep, &http_handle->host, (char *)data, CORE_HTTP_MODULE_NAME);
216         }
217         break;
218         case CORE_HTTPOPT_PORT: {
219             http_handle->port = *(uint16_t *)data;
220         }
221         break;
222         case CORE_HTTPOPT_NETWORK_CRED: {
223             if (http_handle->cred != NULL) {
224                 http_handle->sysdep->core_sysdep_free(http_handle->cred);
225                 http_handle->cred = NULL;
226             }
227             http_handle->cred = http_handle->sysdep->core_sysdep_malloc(sizeof(aiot_sysdep_network_cred_t), CORE_HTTP_MODULE_NAME);
228             if (http_handle->cred != NULL) {
229                 memset(http_handle->cred, 0, sizeof(aiot_sysdep_network_cred_t));
230                 memcpy(http_handle->cred, data, sizeof(aiot_sysdep_network_cred_t));
231             } else {
232                 res = STATE_SYS_DEPEND_MALLOC_FAILED;
233             }
234 
235         }
236         break;
237         case CORE_HTTPOPT_CONNECT_TIMEOUT_MS: {
238             http_handle->connect_timeout_ms = *(uint32_t *)data;
239         }
240         break;
241         case CORE_HTTPOPT_SEND_TIMEOUT_MS: {
242             http_handle->send_timeout_ms = *(uint32_t *)data;
243         }
244         break;
245         case CORE_HTTPOPT_RECV_TIMEOUT_MS: {
246             http_handle->recv_timeout_ms = *(uint32_t *)data;
247         }
248         break;
249         case CORE_HTTPOPT_DEINIT_TIMEOUT_MS: {
250             http_handle->deinit_timeout_ms = *(uint32_t *)data;
251         }
252         break;
253         case CORE_HTTPOPT_HEADER_LINE_MAX_LEN: {
254             http_handle->header_line_max_len = *(uint32_t *)data;
255         }
256         break;
257         case CORE_HTTPOPT_BODY_BUFFER_MAX_LEN: {
258             http_handle->body_buffer_max_len = *(uint32_t *)data;
259         }
260         break;
261         case CORE_HTTPOPT_EVENT_HANDLER: {
262             http_handle->event_handler = (aiot_http_event_handler_t)data;
263         }
264         break;
265         case CORE_HTTPOPT_USERDATA: {
266             http_handle->core_userdata = data;
267         }
268         break;
269         case CORE_HTTPOPT_RECV_HANDLER: {
270             http_handle->core_recv_handler = (aiot_http_recv_handler_t)data;
271         }
272         break;
273         default: {
274             res = STATE_USER_INPUT_UNKNOWN_OPTION;
275         }
276         break;
277     }
278     http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->data_mutex);
279 
280     _core_http_exec_dec(http_handle);
281 
282     return res;
283 }
284 
core_http_connect(void * handle)285 int32_t core_http_connect(void *handle)
286 {
287     int32_t res = STATE_SUCCESS;
288     core_http_handle_t *http_handle = (core_http_handle_t *)handle;
289 
290     if (http_handle == NULL) {
291         return STATE_USER_INPUT_NULL_POINTER;
292     }
293 
294     if (http_handle->core_exec_enabled == 0) {
295         return STATE_USER_INPUT_EXEC_DISABLED;
296     }
297 
298     _core_http_exec_inc(http_handle);
299 
300     /* connect to host */
301     http_handle->sysdep->core_sysdep_mutex_lock(http_handle->send_mutex);
302     http_handle->sysdep->core_sysdep_mutex_lock(http_handle->recv_mutex);
303     res = _core_http_connect(http_handle);
304     http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->recv_mutex);
305     http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->send_mutex);
306 
307     _core_http_exec_dec(http_handle);
308 
309     return res;
310 }
311 
core_http_send(void * handle,const core_http_request_t * request)312 int32_t core_http_send(void *handle, const core_http_request_t *request)
313 {
314     int32_t res = STATE_SUCCESS;
315     char content_lenstr[11] = {0};
316     core_http_handle_t *http_handle = (core_http_handle_t *)handle;
317 
318     if (http_handle == NULL || request == NULL ||
319         request->path == NULL || request->method == NULL) {
320         return STATE_USER_INPUT_NULL_POINTER;
321     }
322 
323     if (http_handle->host == NULL) {
324         return STATE_USER_INPUT_MISSING_HOST;
325     }
326 
327     if (http_handle->network_handle == NULL) {
328         return STATE_SYS_DEPEND_NWK_CLOSED;
329     }
330 
331     if (http_handle->core_exec_enabled == 0) {
332         return STATE_USER_INPUT_EXEC_DISABLED;
333     }
334 
335     memset(&http_handle->session, 0, sizeof(core_http_session_t));
336 
337     _core_http_exec_inc(http_handle);
338 
339     /* send http header */
340     core_uint2str(request->content_len, content_lenstr, NULL);
341     res = _core_http_send_header(http_handle, request->method, request->path, http_handle->host, request->header,
342                                  content_lenstr);
343     if (res < STATE_SUCCESS) {
344         _core_http_exec_dec(http_handle);
345         return res;
346     } else {
347         res = STATE_SUCCESS;
348     }
349 
350     /* send http content */
351     if (request->content != NULL && request->content_len > 0) {
352         res = _core_http_send_body(http_handle, request->content, request->content_len);
353         if (res < STATE_SUCCESS) {
354             _core_http_exec_dec(http_handle);
355             return res;
356         }
357     }
358 
359     _core_http_exec_dec(http_handle);
360 
361     return res;
362 }
363 
_core_http_recv_status_code(core_http_handle_t * http_handle,uint32_t status_code)364 static void _core_http_recv_status_code(core_http_handle_t *http_handle, uint32_t status_code)
365 {
366     aiot_http_recv_t packet;
367 
368     if (http_handle->core_recv_handler == NULL) {
369         return;
370     }
371 
372     memset(&packet, 0, sizeof(aiot_http_recv_t));
373     packet.type = AIOT_HTTPRECV_STATUS_CODE;
374     packet.data.status_code.code = status_code;
375 
376     http_handle->core_recv_handler(http_handle, &packet, http_handle->core_userdata);
377 }
378 
_core_http_recv_header_pair(core_http_handle_t * http_handle,char * key,uint32_t key_len,char * value,uint32_t value_len)379 static void _core_http_recv_header_pair(core_http_handle_t *http_handle, char *key, uint32_t key_len, char *value,
380                                         uint32_t value_len)
381 {
382     char *pair_key = NULL, *pair_value = NULL;
383     aiot_http_recv_t packet;
384 
385     if (http_handle->core_recv_handler == NULL) {
386         return;
387     }
388 
389     pair_key = http_handle->sysdep->core_sysdep_malloc(key_len + 1, CORE_HTTP_MODULE_NAME);
390     if (pair_key == NULL) {
391         return;
392     }
393     memset(pair_key, 0, key_len + 1);
394     memcpy(pair_key, key, key_len);
395 
396     pair_value = http_handle->sysdep->core_sysdep_malloc(value_len + 1, CORE_HTTP_MODULE_NAME);
397     if (pair_value == NULL) {
398         http_handle->sysdep->core_sysdep_free(pair_key);
399         return;
400     }
401     memset(pair_value, 0, value_len + 1);
402     memcpy(pair_value, value, value_len);
403 
404     packet.type = AIOT_HTTPRECV_HEADER;
405     packet.data.header.key = pair_key;
406     packet.data.header.value = pair_value;
407 
408     http_handle->core_recv_handler(http_handle, &packet, http_handle->core_userdata);
409 
410     http_handle->sysdep->core_sysdep_free(pair_key);
411     http_handle->sysdep->core_sysdep_free(pair_value);
412 }
413 
_core_http_recv(core_http_handle_t * http_handle,uint8_t * buffer,uint32_t len,uint32_t timeout_ms)414 static int32_t _core_http_recv(core_http_handle_t *http_handle, uint8_t *buffer, uint32_t len, uint32_t timeout_ms)
415 {
416     int32_t res = STATE_SUCCESS;
417 
418     if (http_handle->network_handle != NULL) {
419         res = http_handle->sysdep->core_sysdep_network_recv(http_handle->network_handle, buffer, len, timeout_ms, NULL);
420         if (res < STATE_SUCCESS) {
421             http_handle->sysdep->core_sysdep_network_deinit(&http_handle->network_handle);
422             core_log(http_handle->sysdep, STATE_HTTP_LOG_DISCONNECT, "HTTP network error when receving data, disconnect\r\n");
423             res = _core_http_sysdep_return(res, STATE_SYS_DEPEND_NWK_RECV_ERR);
424         }
425     } else {
426         res = STATE_SYS_DEPEND_NWK_CLOSED;
427     }
428 
429     return res;
430 }
431 
_core_http_recv_header(core_http_handle_t * http_handle,uint32_t * body_total_len)432 static int32_t _core_http_recv_header(core_http_handle_t *http_handle, uint32_t *body_total_len)
433 {
434     int32_t res = STATE_SUCCESS;
435     char *line = NULL;
436     uint32_t idx = 0, line_max_len = http_handle->header_line_max_len;
437     uint64_t timenow_ms = 0;
438 
439     line = http_handle->sysdep->core_sysdep_malloc(line_max_len, CORE_HTTP_MODULE_NAME);
440     if (line == NULL) {
441         return STATE_SYS_DEPEND_MALLOC_FAILED;
442     }
443     memset(line, 0, line_max_len);
444 
445     timenow_ms = http_handle->sysdep->core_sysdep_time();
446     for (idx = 0; idx < line_max_len;) {
447         if (timenow_ms > http_handle->sysdep->core_sysdep_time()) {
448             timenow_ms = http_handle->sysdep->core_sysdep_time();
449         }
450         if (http_handle->sysdep->core_sysdep_time() - timenow_ms >= http_handle->recv_timeout_ms) {
451             res =  STATE_HTTP_HEADER_INVALID;
452             break;
453         }
454         if (idx + 2 > line_max_len) {
455             res = STATE_HTTP_HEADER_BUFFER_TOO_SHORT;
456             break;
457         }
458         /* read http header, "\r\n" in the end */
459         if ((res = _core_http_recv(http_handle, (uint8_t *)&line[idx], 1,
460                                    http_handle->recv_timeout_ms)) < STATE_SUCCESS) {
461             break;
462         }
463         idx++;
464         if (res == 0 || (line[idx - 1] != '\r')) {
465             continue;
466         }
467         if ((res = _core_http_recv(http_handle, (uint8_t *)&line[idx], 1,
468                                    http_handle->recv_timeout_ms)) < STATE_SUCCESS) {
469             break;
470         }
471         idx++;
472         if (res == 0 || (line[idx - 1] != '\n')) {
473             continue;
474         }
475 
476         core_log2(http_handle->sysdep, STATE_HTTP_LOG_RECV_HEADER, "< %.*s", &idx, line);
477         /* next line should be http response body */
478         if (idx == 2) {
479             break;
480         }
481         /* status code */
482         if ((idx > (strlen("HTTP/1.1 ") + 3)) && (memcmp(line, "HTTP/1.1 ", strlen("HTTP/1.1 "))) == 0) {
483             uint32_t status_code = 0, code_idx = 0;
484             for (code_idx = strlen("HTTP/1.1 "); code_idx < idx; code_idx++) {
485                 if (line[code_idx] < '0' || line[code_idx] > '9') {
486                     break;
487                 }
488             }
489             res = core_str2uint(&line[strlen("HTTP/1.1 ")], (code_idx - strlen("HTTP/1.1 ")), &status_code);
490             if (res < STATE_SUCCESS) {
491                 res = STATE_HTTP_STATUS_LINE_INVALID;
492                 break;
493             }
494             _core_http_recv_status_code(http_handle, status_code);
495         }
496         /* header */
497         {
498             uint32_t deli_idx = 0;
499             for (deli_idx = 0; deli_idx < idx; deli_idx++) {
500                 if (line[deli_idx] == ':' && line[deli_idx + 1] == ' ') {
501                     if ((deli_idx + 2 == strlen("Content-Length: ")) && (memcmp(line, "Content-Length: ", deli_idx + 2) == 0)) {
502                         core_str2uint(&line[deli_idx + 2], (uint32_t)(idx - deli_idx - 4), body_total_len);
503                     }
504                     _core_http_recv_header_pair(http_handle, line, deli_idx, &line[deli_idx + 2], (uint32_t)(idx - deli_idx - 4));
505                 }
506             }
507         }
508         idx = 0;
509         memset(line, 0, line_max_len);
510     }
511 
512     http_handle->sysdep->core_sysdep_free(line);
513 
514     return res;
515 }
516 
_core_http_recv_body(core_http_handle_t * http_handle,uint32_t body_total_len)517 static int32_t _core_http_recv_body(core_http_handle_t *http_handle, uint32_t body_total_len)
518 {
519     int32_t res = STATE_SUCCESS;
520     char *buffer = NULL;
521     uint32_t remaining_len = 0, buffer_len = 0;
522 
523     if (http_handle->session.body_total_len == 0 && body_total_len == 0) {
524         return STATE_HTTP_READ_BODY_EMPTY;
525     }
526 
527     if (body_total_len != 0) {
528         http_handle->session.body_total_len = body_total_len;
529         remaining_len = body_total_len;
530     } else {
531         remaining_len = http_handle->session.body_total_len - http_handle->session.body_read_len;
532     }
533 
534     if (remaining_len == 0) {
535         return STATE_HTTP_READ_BODY_FINISHED;
536     }
537 
538     buffer_len = (remaining_len < http_handle->body_buffer_max_len) ? (remaining_len) : (http_handle->body_buffer_max_len);
539 
540     buffer = http_handle->sysdep->core_sysdep_malloc(buffer_len, CORE_HTTP_MODULE_NAME);
541     if (buffer == NULL) {
542         return STATE_SYS_DEPEND_MALLOC_FAILED;
543     }
544     memset(buffer, 0, buffer_len);
545 
546     http_handle->sysdep->core_sysdep_mutex_lock(http_handle->recv_mutex);
547     res = _core_http_recv(http_handle, (uint8_t *)buffer, buffer_len, http_handle->recv_timeout_ms);
548     http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->recv_mutex);
549     if (res > 0) {
550         aiot_http_recv_t packet;
551 
552         core_log_hexdump(STATE_HTTP_LOG_RECV_CONTENT, '<', (uint8_t *)buffer, res);
553 
554         if (http_handle->core_recv_handler != NULL) {
555             http_handle->session.body_read_len += res;
556             memset(&packet, 0, sizeof(aiot_http_recv_t));
557             packet.type = AIOT_HTTPRECV_BODY;
558             packet.data.body.buffer = (uint8_t *)buffer;
559             packet.data.body.len = res;
560 
561             http_handle->core_recv_handler(http_handle, &packet, http_handle->core_userdata);
562         }
563     }
564     http_handle->sysdep->core_sysdep_free(buffer);
565 
566     return res;
567 }
568 
core_http_recv(void * handle)569 int32_t core_http_recv(void *handle)
570 {
571     int32_t res = STATE_SUCCESS;
572     uint32_t body_total_len = 0;
573     core_http_handle_t *http_handle = (core_http_handle_t *)handle;
574 
575     if (http_handle == NULL) {
576         return STATE_USER_INPUT_NULL_POINTER;
577     }
578 
579     if (http_handle->network_handle == NULL) {
580         return STATE_SYS_DEPEND_NWK_CLOSED;
581     }
582 
583     if (http_handle->core_exec_enabled == 0) {
584         return STATE_USER_INPUT_EXEC_DISABLED;
585     }
586 
587     _core_http_exec_inc(http_handle);
588 
589     if (http_handle->session.sm == CORE_HTTP_SM_READ_HEADER) {
590         http_handle->sysdep->core_sysdep_mutex_lock(http_handle->recv_mutex);
591         res = _core_http_recv_header(http_handle, &body_total_len);
592         http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->recv_mutex);
593         if (res < STATE_SUCCESS) {
594             _core_http_exec_dec(http_handle);
595             return res;
596         }
597     }
598     http_handle->session.sm = CORE_HTTP_SM_READ_BODY;
599 
600     res = _core_http_recv_body(http_handle, body_total_len);
601     if (res == STATE_HTTP_READ_BODY_FINISHED || res == STATE_HTTP_READ_BODY_EMPTY) {
602         memset(&http_handle->session, 0, sizeof(core_http_session_t));
603     }
604 
605     _core_http_exec_dec(http_handle);
606 
607     return res;
608 }
609 
core_http_deinit(void ** p_handle)610 int32_t core_http_deinit(void **p_handle)
611 {
612     uint32_t deinit_timeout_ms = 0;
613     core_http_handle_t *http_handle = NULL;
614 
615     if (p_handle == NULL || *p_handle == NULL) {
616         return STATE_USER_INPUT_NULL_POINTER;
617     }
618 
619     http_handle = *(core_http_handle_t **)p_handle;
620 
621     if (http_handle->core_exec_enabled == 0) {
622         return STATE_USER_INPUT_EXEC_DISABLED;
623     }
624 
625     http_handle->exec_enabled = 0;
626     deinit_timeout_ms = http_handle->deinit_timeout_ms;
627     do {
628         if (http_handle->exec_count == 0) {
629             break;
630         }
631         http_handle->sysdep->core_sysdep_sleep(CORE_HTTP_DEINIT_INTERVAL_MS);
632     } while ((deinit_timeout_ms > CORE_HTTP_DEINIT_INTERVAL_MS) && (deinit_timeout_ms - CORE_HTTP_DEINIT_INTERVAL_MS > 0));
633 
634     if (http_handle->exec_count != 0) {
635         return STATE_HTTP_DEINIT_TIMEOUT;
636     }
637 
638     if (http_handle->network_handle != NULL) {
639         http_handle->sysdep->core_sysdep_network_deinit(&http_handle->network_handle);
640     }
641 
642     if (http_handle->host != NULL) {
643         http_handle->sysdep->core_sysdep_free(http_handle->host);
644     }
645     if (http_handle->cred != NULL) {
646         http_handle->sysdep->core_sysdep_free(http_handle->cred);
647     }
648 
649     http_handle->sysdep->core_sysdep_mutex_deinit(&http_handle->data_mutex);
650     http_handle->sysdep->core_sysdep_mutex_deinit(&http_handle->send_mutex);
651     http_handle->sysdep->core_sysdep_mutex_deinit(&http_handle->recv_mutex);
652 
653     http_handle->sysdep->core_sysdep_free(http_handle);
654 
655     *p_handle = NULL;
656 
657     return STATE_SUCCESS;
658 }
659 
660