1 #include "core_http.h"
2 
_core_aiot_http_exec_inc(core_http_handle_t * http_handle)3 static void _core_aiot_http_exec_inc(core_http_handle_t *http_handle)
4 {
5     http_handle->sysdep->core_sysdep_mutex_lock(http_handle->data_mutex);
6     http_handle->exec_count++;
7     http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->data_mutex);
8 }
9 
_core_aiot_http_exec_dec(core_http_handle_t * http_handle)10 static void _core_aiot_http_exec_dec(core_http_handle_t *http_handle)
11 {
12     http_handle->sysdep->core_sysdep_mutex_lock(http_handle->data_mutex);
13     http_handle->exec_count--;
14     http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->data_mutex);
15 }
16 
_core_http_auth_recv_handler(void * handle,const aiot_http_recv_t * packet,void * userdata)17 static void _core_http_auth_recv_handler(void *handle, const aiot_http_recv_t *packet, void *userdata)
18 {
19     core_http_handle_t *http_handle = (core_http_handle_t *)handle;
20     core_http_response_t *response = (core_http_response_t *)userdata;
21 
22     switch (packet->type) {
23         case AIOT_HTTPRECV_STATUS_CODE: {
24             response->code = packet->data.status_code.code;
25         }
26         break;
27         case AIOT_HTTPRECV_HEADER: {
28             if ((strlen(packet->data.header.key) == strlen("Content-Length")) &&
29                 (memcmp(packet->data.header.key, "Content-Length", strlen(packet->data.header.key)) == 0)) {
30                 core_str2uint(packet->data.header.value, (uint8_t)strlen(packet->data.header.value), &response->content_total_len);
31             }
32         }
33         break;
34         case AIOT_HTTPRECV_BODY: {
35             uint8_t *content = http_handle->sysdep->core_sysdep_malloc(response->content_len + packet->data.body.len + 1,
36                                CORE_HTTP_MODULE_NAME);
37             if (content == NULL) {
38                 return;
39             }
40             memset(content, 0, response->content_len + packet->data.body.len + 1);
41             if (response->content != NULL) {
42                 memcpy(content, response->content, response->content_len);
43                 http_handle->sysdep->core_sysdep_free(response->content);
44             }
45             memcpy(content + response->content_len, packet->data.body.buffer, packet->data.body.len);
46             response->content = content;
47             response->content_len = response->content_len + packet->data.body.len;
48         }
49         break;
50         default: {
51 
52         }
53         break;
54     }
55 }
56 
_core_http_recv_handler(void * handle,const aiot_http_recv_t * packet,void * userdata)57 static void _core_http_recv_handler(void *handle, const aiot_http_recv_t *packet, void *userdata)
58 {
59     core_http_handle_t *http_handle = (core_http_handle_t *)handle;
60     core_http_response_t *response = (core_http_response_t *)userdata;
61 
62     if (http_handle->recv_handler == NULL) {
63         return;
64     }
65 
66     switch (packet->type) {
67         case AIOT_HTTPRECV_STATUS_CODE: {
68             http_handle->recv_handler(http_handle, packet, http_handle->userdata);
69         }
70         break;
71         case AIOT_HTTPRECV_HEADER: {
72             if ((strlen(packet->data.header.key) == strlen("Content-Length")) &&
73                 (memcmp(packet->data.header.key, "Content-Length", strlen(packet->data.header.key)) == 0)) {
74                 core_str2uint(packet->data.header.value, (uint8_t)strlen(packet->data.header.value), &response->content_total_len);
75             }
76             http_handle->recv_handler(http_handle, packet, http_handle->userdata);
77         }
78         break;
79         case AIOT_HTTPRECV_BODY: {
80             uint8_t *content = http_handle->sysdep->core_sysdep_malloc(response->content_len + packet->data.body.len + 1,
81                                CORE_HTTP_MODULE_NAME);
82             if (content == NULL) {
83                 return;
84             }
85             memset(content, 0, response->content_len + packet->data.body.len + 1);
86             if (response->content != NULL) {
87                 memcpy(content, response->content, response->content_len);
88                 http_handle->sysdep->core_sysdep_free(response->content);
89             }
90             memcpy(content + response->content_len, packet->data.body.buffer, packet->data.body.len);
91             response->content = content;
92             response->content_len = response->content_len + packet->data.body.len;
93         }
94         break;
95         default: {
96 
97         }
98         break;
99     }
100 }
101 
_core_aiot_http_token_expired_event(core_http_handle_t * http_handle,core_http_response_t * response)102 static void _core_aiot_http_token_expired_event(core_http_handle_t *http_handle, core_http_response_t *response)
103 {
104     int32_t res = STATE_SUCCESS;
105     char *code_str = NULL;
106     uint32_t code_strlen = 0, code = 0;
107 
108     res = core_json_value((const char *)response->content, response->content_len, "code", strlen("code"), &code_str,
109                           &code_strlen);
110     if (res < STATE_SUCCESS) {
111         return;
112     }
113 
114     res = core_str2uint(code_str, code_strlen, &code);
115     if (res < STATE_SUCCESS) {
116         return;
117     }
118 
119     if (code == AIOT_HTTP_RSPCODE_TOKEN_EXPIRED ||
120         code == AIOT_HTTP_RSPCODE_TOKEN_CHECK_ERROR) {
121         if (http_handle->event_handler != NULL) {
122             aiot_http_event_t event;
123             event.type = AIOT_HTTPEVT_TOKEN_INVALID;
124 
125             http_handle->event_handler(http_handle, &event, http_handle->userdata);
126         }
127     }
128 }
129 
_core_http_send_auth(core_http_handle_t * http_handle)130 static int32_t _core_http_send_auth(core_http_handle_t *http_handle)
131 {
132     int32_t res = STATE_SUCCESS;
133     char *content = NULL, *path = NULL;
134     char *path_fmt = "/auth?_v=%s&%s";
135     char *path_src[] = { CORE_AUTH_SDK_VERSION, http_handle->extend_devinfo };
136     core_http_request_t request;
137 
138     res = core_auth_http_body(http_handle->sysdep, &content, http_handle->product_key, http_handle->device_name,
139                               http_handle->device_secret, CORE_HTTP_MODULE_NAME);
140     if (res < STATE_SUCCESS) {
141         return res;
142     }
143 
144     res = core_sprintf(http_handle->sysdep, &path, path_fmt, path_src, sizeof(path_src) / sizeof(char *),
145                        CORE_HTTP_MODULE_NAME);
146     if (res < STATE_SUCCESS) {
147         http_handle->sysdep->core_sysdep_free(content);
148         return res;
149     }
150 
151     memset(&request, 0, sizeof(core_http_request_t));
152     request.method = "POST";
153     request.path = path;
154     request.header = (http_handle->long_connection == 0) ? ("Content-Type: application/json\r\nConnection: close\r\n") :
155                      ("Content-Type: application/json\r\n");
156     request.content = (uint8_t *)content;
157     request.content_len = (uint32_t)strlen(content);
158 
159     res = core_http_send(http_handle, &request);
160 
161     http_handle->sysdep->core_sysdep_free(path);
162     http_handle->sysdep->core_sysdep_free(content);
163 
164     return res;
165 }
166 
_core_http_recv_auth(core_http_handle_t * http_handle,core_http_response_t * response)167 static int32_t _core_http_recv_auth(core_http_handle_t *http_handle, core_http_response_t *response)
168 {
169     int32_t res = STATE_SUCCESS;
170     char *token = NULL;
171     uint32_t token_len = 0;
172     uint64_t timenow_ms = http_handle->sysdep->core_sysdep_time();
173 
174     while (1) {
175         if (timenow_ms >= http_handle->sysdep->core_sysdep_time()) {
176             timenow_ms = http_handle->sysdep->core_sysdep_time();
177         }
178         if (http_handle->sysdep->core_sysdep_time() - timenow_ms >= http_handle->auth_timeout_ms) {
179             break;
180         }
181 
182         res = core_http_recv(http_handle);
183         if (res < STATE_SUCCESS) {
184             break;
185         }
186     }
187 
188     if (res < STATE_SUCCESS) {
189         if (res != STATE_HTTP_READ_BODY_FINISHED) {
190             return res;
191         } else {
192             res = STATE_SUCCESS;
193         }
194     } else {
195         return STATE_HTTP_AUTH_NOT_FINISHED;
196     }
197 
198     if (response->code != 200) {
199         return STATE_HTTP_AUTH_CODE_FAILED;
200     }
201     if (response->content == NULL || response->content_len != response->content_total_len) {
202         return STATE_HTTP_AUTH_NOT_EXPECTED;
203     }
204 
205     core_log2(http_handle->sysdep, STATE_HTTP_LOG_AUTH, "%.*s\r\n", &response->content_len, response->content);
206 
207     res = core_json_value((const char *)response->content, response->content_len, "token", strlen("token"), &token,
208                           &token_len);
209     if (res < STATE_SUCCESS) {
210         return STATE_HTTP_AUTH_TOKEN_FAILED;
211     }
212 
213     http_handle->sysdep->core_sysdep_mutex_lock(http_handle->data_mutex);
214     if (http_handle->token != NULL) {
215         http_handle->sysdep->core_sysdep_free(http_handle->token);
216         http_handle->token = NULL;
217     }
218     http_handle->token = http_handle->sysdep->core_sysdep_malloc(token_len + 1, CORE_HTTP_MODULE_NAME);
219     if (http_handle->token == NULL) {
220         http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->data_mutex);
221         return STATE_SYS_DEPEND_MALLOC_FAILED;
222     }
223     memset(http_handle->token, 0, token_len + 1);
224     memcpy(http_handle->token, token, token_len);
225     http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->data_mutex);
226 
227     return STATE_SUCCESS;
228 }
229 
aiot_http_init(void)230 void *aiot_http_init(void)
231 {
232     core_http_handle_t *http_handle = NULL;
233 
234     http_handle = core_http_init();
235     if (http_handle == NULL) {
236         return NULL;
237     }
238 
239     http_handle->auth_timeout_ms = CORE_HTTP_DEFAULT_AUTH_TIMEOUT_MS;
240     http_handle->long_connection = 1;
241 
242     http_handle->exec_enabled = 1;
243 
244     return http_handle;
245 }
246 
aiot_http_setopt(void * handle,aiot_http_option_t option,void * data)247 int32_t aiot_http_setopt(void *handle, aiot_http_option_t option, void *data)
248 {
249     int32_t res = STATE_SUCCESS;
250     core_http_handle_t *http_handle = (core_http_handle_t *)handle;
251 
252     if (http_handle == NULL || data == NULL) {
253         return STATE_USER_INPUT_NULL_POINTER;
254     }
255 
256     if (option >= AIOT_HTTPOPT_MAX) {
257         return STATE_USER_INPUT_OUT_RANGE;
258     }
259 
260     if (http_handle->exec_enabled == 0) {
261         return STATE_USER_INPUT_EXEC_DISABLED;
262     }
263 
264     _core_aiot_http_exec_inc(http_handle);
265 
266     http_handle->sysdep->core_sysdep_mutex_lock(http_handle->data_mutex);
267     switch (option) {
268         case AIOT_HTTPOPT_HOST:
269         case AIOT_HTTPOPT_PORT:
270         case AIOT_HTTPOPT_NETWORK_CRED:
271         case AIOT_HTTPOPT_CONNECT_TIMEOUT_MS:
272         case AIOT_HTTPOPT_SEND_TIMEOUT_MS:
273         case AIOT_HTTPOPT_RECV_TIMEOUT_MS:
274         case AIOT_HTTPOPT_DEINIT_TIMEOUT_MS:
275         case AIOT_HTTPOPT_HEADER_BUFFER_LEN:
276         case AIOT_HTTPOPT_BODY_BUFFER_LEN:
277         case AIOT_HTTPOPT_EVENT_HANDLER: {
278             http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->data_mutex);
279             res = core_http_setopt(handle, (core_http_option_t)option, data);
280             http_handle->sysdep->core_sysdep_mutex_lock(http_handle->data_mutex);
281         }
282         break;
283         case AIOT_HTTPOPT_USERDATA: {
284             http_handle->userdata = data;
285         }
286         break;
287         case AIOT_HTTPOPT_RECV_HANDLER: {
288             http_handle->recv_handler = (aiot_http_recv_handler_t)data;
289         }
290         break;
291         case AIOT_HTTPOPT_PRODUCT_KEY: {
292             res = core_strdup(http_handle->sysdep, &http_handle->product_key, (char *)data, CORE_HTTP_MODULE_NAME);
293         }
294         break;
295         case AIOT_HTTPOPT_DEVICE_NAME: {
296             res = core_strdup(http_handle->sysdep, &http_handle->device_name, (char *)data, CORE_HTTP_MODULE_NAME);
297         }
298         break;
299         case AIOT_HTTPOPT_DEVICE_SECRET: {
300             res = core_strdup(http_handle->sysdep, &http_handle->device_secret, (char *)data, CORE_HTTP_MODULE_NAME);
301         }
302         break;
303         case AIOT_HTTPOPT_EXTEND_DEVINFO: {
304             res = core_strdup(http_handle->sysdep, &http_handle->extend_devinfo, (char *)data, CORE_HTTP_MODULE_NAME);
305         }
306         break;
307         case AIOT_HTTPOPT_AUTH_TIMEOUT_MS: {
308             http_handle->auth_timeout_ms = *(uint32_t *)data;
309         }
310         break;
311         case AIOT_HTTPOPT_LONG_CONNECTION: {
312             http_handle->long_connection = *(uint8_t *)data;
313         }
314         break;
315         default: {
316             res = STATE_USER_INPUT_UNKNOWN_OPTION;
317         }
318         break;
319     }
320     http_handle->sysdep->core_sysdep_mutex_unlock(http_handle->data_mutex);
321 
322     _core_aiot_http_exec_dec(http_handle);
323 
324     return res;
325 }
326 
aiot_http_auth(void * handle)327 int32_t aiot_http_auth(void *handle)
328 {
329     int32_t res = STATE_SUCCESS;
330     core_http_response_t response;
331     core_http_handle_t *http_handle = (core_http_handle_t *)handle;
332 
333     if (http_handle == NULL) {
334         return STATE_USER_INPUT_NULL_POINTER;
335     }
336 
337     if (http_handle->product_key == NULL) {
338         return STATE_USER_INPUT_MISSING_PRODUCT_KEY;
339     }
340 
341     if (http_handle->device_name == NULL) {
342         return STATE_USER_INPUT_MISSING_DEVICE_NAME;
343     }
344 
345     if (http_handle->device_secret == NULL) {
346         return STATE_USER_INPUT_MISSING_DEVICE_SECRET;
347     }
348 
349     if (http_handle->exec_enabled == 0) {
350         return STATE_USER_INPUT_EXEC_DISABLED;
351     }
352 
353     _core_aiot_http_exec_inc(http_handle);
354 
355     memset(&response, 0, sizeof(core_http_response_t));
356 
357     if ((res = core_http_setopt(http_handle, CORE_HTTPOPT_RECV_HANDLER,
358                                 (void *)_core_http_auth_recv_handler)) < STATE_SUCCESS ||
359         (res = core_http_setopt(http_handle, CORE_HTTPOPT_USERDATA, (void *)&response)) < STATE_SUCCESS) {
360         return res;
361     }
362     if (http_handle->network_handle == NULL ||
363         (http_handle->network_handle != NULL && http_handle->long_connection == 0)) {
364         if ((res = core_http_connect(http_handle)) < STATE_SUCCESS) {
365             _core_aiot_http_exec_dec(http_handle);
366             return res;
367         }
368     }
369 
370     /* send auth request */
371     res = _core_http_send_auth(http_handle);
372     if (res < STATE_SUCCESS) {
373         _core_aiot_http_exec_dec(http_handle);
374         return res;
375     }
376 
377     /* recv auth response */
378     res = _core_http_recv_auth(http_handle, &response);
379     if (response.content != NULL) {
380         http_handle->sysdep->core_sysdep_free(response.content);
381     }
382 
383     _core_aiot_http_exec_dec(http_handle);
384 
385     return res;
386 }
387 
aiot_http_send(void * handle,char * topic,uint8_t * payload,uint32_t payload_len)388 int32_t aiot_http_send(void *handle, char *topic, uint8_t *payload, uint32_t payload_len)
389 {
390     int32_t res = STATE_SUCCESS;
391     char *path = NULL, *header = NULL;
392     char *header_src[] = { NULL, NULL };
393     core_http_request_t request;
394     core_http_handle_t *http_handle = (core_http_handle_t *)handle;
395 
396     if (http_handle == NULL || topic == NULL || payload == NULL) {
397         return STATE_USER_INPUT_NULL_POINTER;
398     }
399     if (payload_len == 0) {
400         return STATE_USER_INPUT_OUT_RANGE;
401     }
402     if (http_handle->token == NULL) {
403         return STATE_HTTP_NEED_AUTH;
404     }
405     if (http_handle->exec_enabled == 0) {
406         return STATE_USER_INPUT_EXEC_DISABLED;
407     }
408 
409     _core_aiot_http_exec_inc(http_handle);
410 
411     if (http_handle->network_handle == NULL ||
412         (http_handle->network_handle != NULL && http_handle->long_connection == 0)) {
413         if ((res = core_http_connect(http_handle)) < STATE_SUCCESS) {
414             _core_aiot_http_exec_dec(http_handle);
415             return res;
416         }
417     }
418 
419     /* path */
420     res = core_sprintf(http_handle->sysdep, &path, "/topic%s", (char **)&topic, 1, CORE_HTTP_MODULE_NAME);
421     if (res < STATE_SUCCESS) {
422         _core_aiot_http_exec_dec(http_handle);
423         return res;
424     }
425 
426     /* header */
427     header_src[0] = http_handle->token;
428     if (http_handle->long_connection == 0) {
429         header_src[1] = "Connection: close\r\n";
430     }
431     res = core_sprintf(http_handle->sysdep, &header, "Content-Type: application/octet-stream\r\nPassword: %s\r\n%s",
432                        header_src, sizeof(header_src) / sizeof(char *), CORE_HTTP_MODULE_NAME);
433     if (res < STATE_SUCCESS) {
434         http_handle->sysdep->core_sysdep_free(path);
435         _core_aiot_http_exec_dec(http_handle);
436         return res;
437     }
438 
439     memset(&request, 0, sizeof(core_http_request_t));
440     request.method = "POST";
441     request.path = path;
442     request.header = header;
443     request.content = (uint8_t *)payload;
444     request.content_len = payload_len;
445 
446     res = core_http_send(http_handle, &request);
447     http_handle->sysdep->core_sysdep_free(path);
448     http_handle->sysdep->core_sysdep_free(header);
449 
450     _core_aiot_http_exec_dec(http_handle);
451 
452     return res;
453 }
454 
aiot_http_recv(void * handle)455 int32_t aiot_http_recv(void *handle)
456 {
457     int32_t res = STATE_SUCCESS;
458     uint64_t timenow_ms = 0;
459     core_http_response_t response;
460     core_http_handle_t *http_handle = (core_http_handle_t *)handle;
461 
462     if (http_handle == NULL) {
463         return STATE_USER_INPUT_NULL_POINTER;
464     }
465     if (http_handle->network_handle == NULL) {
466         return STATE_SYS_DEPEND_NWK_CLOSED;
467     }
468     if (http_handle->exec_enabled == 0) {
469         return STATE_USER_INPUT_EXEC_DISABLED;
470     }
471 
472     _core_aiot_http_exec_inc(http_handle);
473 
474     memset(&response, 0, sizeof(core_http_response_t));
475     if ((res = core_http_setopt(http_handle, CORE_HTTPOPT_RECV_HANDLER, (void *)_core_http_recv_handler)) < STATE_SUCCESS ||
476         (res = core_http_setopt(http_handle, CORE_HTTPOPT_USERDATA, (void *)&response)) < STATE_SUCCESS) {
477         return res;
478     }
479     timenow_ms = http_handle->sysdep->core_sysdep_time();
480     while (1) {
481         if (timenow_ms >= http_handle->sysdep->core_sysdep_time()) {
482             timenow_ms = http_handle->sysdep->core_sysdep_time();
483         }
484         if (http_handle->sysdep->core_sysdep_time() - timenow_ms >= http_handle->recv_timeout_ms) {
485             break;
486         }
487 
488         res = core_http_recv(http_handle);
489         if (res < STATE_SUCCESS) {
490             break;
491         }
492     }
493 
494     if (res < STATE_SUCCESS) {
495         if (res != STATE_HTTP_READ_BODY_FINISHED) {
496             _core_aiot_http_exec_dec(http_handle);
497             if (response.content != NULL) {
498                 http_handle->sysdep->core_sysdep_free(response.content);
499             }
500             return res;
501         } else {
502             res = STATE_SUCCESS;
503         }
504     } else {
505         return STATE_HTTP_RECV_NOT_FINISHED;
506     }
507 
508     _core_aiot_http_token_expired_event(http_handle, &response);
509 
510     if (http_handle->recv_handler != NULL) {
511         aiot_http_recv_t packet;
512 
513         packet.type = AIOT_HTTPRECV_BODY;
514         packet.data.body.buffer = response.content;
515         packet.data.body.len = response.content_len;
516 
517         http_handle->recv_handler(http_handle, &packet, http_handle->userdata);
518     }
519     if (response.content != NULL) {
520         http_handle->sysdep->core_sysdep_free(response.content);
521     }
522 
523     _core_aiot_http_exec_dec(http_handle);
524 
525     return res;
526 }
527 
aiot_http_deinit(void ** p_handle)528 int32_t aiot_http_deinit(void **p_handle)
529 {
530     uint64_t deinit_timestart = 0;
531     core_http_handle_t *http_handle = NULL;
532 
533     if (p_handle == NULL || *p_handle == NULL) {
534         return STATE_USER_INPUT_NULL_POINTER;
535     }
536 
537     http_handle = *(core_http_handle_t **)p_handle;
538 
539     if (http_handle->exec_enabled == 0) {
540         return STATE_USER_INPUT_EXEC_DISABLED;
541     }
542 
543     http_handle->exec_enabled = 0;
544     deinit_timestart = http_handle->sysdep->core_sysdep_time();
545     do {
546         if (http_handle->exec_count == 0) {
547             break;
548         }
549         http_handle->sysdep->core_sysdep_sleep(CORE_HTTP_DEINIT_INTERVAL_MS);
550     } while ((http_handle->sysdep->core_sysdep_time() - deinit_timestart) < http_handle->deinit_timeout_ms);
551 
552     if (http_handle->exec_count != 0) {
553         return STATE_HTTP_DEINIT_TIMEOUT;
554     }
555 
556     if (http_handle->product_key != NULL) {
557         http_handle->sysdep->core_sysdep_free(http_handle->product_key);
558     }
559     if (http_handle->device_name != NULL) {
560         http_handle->sysdep->core_sysdep_free(http_handle->device_name);
561     }
562     if (http_handle->device_secret != NULL) {
563         http_handle->sysdep->core_sysdep_free(http_handle->device_secret);
564     }
565     if (http_handle->extend_devinfo != NULL) {
566         http_handle->sysdep->core_sysdep_free(http_handle->extend_devinfo);
567     }
568     if (http_handle->token != NULL) {
569         http_handle->sysdep->core_sysdep_free(http_handle->token);
570     }
571 
572     core_http_deinit(p_handle);
573 
574     return STATE_SUCCESS;
575 }
576 
577