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