1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4
5 #include <stdint.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <stdlib.h>
9
10 #include "linkkit/infra/infra_defs.h"
11 #include "linkkit/infra/infra_types.h"
12 #include "linkkit/infra/infra_httpc.h"
13 #include "linkkit/infra/infra_sha1.h"
14 #include "linkkit/infra/infra_timer.h"
15 #include "linkkit/infra/infra_list.h"
16 #include "linkkit/infra/infra_log.h"
17
18 #include "http2_internal.h"
19 #include "linkkit/http2_api.h"
20 #include "http2_config.h"
21
22 #define URL_MAX_LEN (100)
23
24 typedef enum {
25 NUM_STRING_ENUM = 0,
26 PATH_CREATE_STR_ENUM = 1,
27 PATH_UPLOAD_STR_ENUM = 2,
28 CID_STRING_ENUM = 3,
29 ORI_SIGN_STR_ENUM = 4,
30 FS_STRING_ENUM = 5,
31 REAL_SIGN_STR_ENUM = 6,
32 } HEADER_TYPE_ENUM;
33
34 typedef struct _device_info_struct_ {
35 char product_key[IOTX_PRODUCT_KEY_LEN + 1];
36 char device_name[IOTX_DEVICE_NAME_LEN + 1];
37 char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
38 char url[URL_MAX_LEN + 1];
39 int port;
40 } device_info;
41
42 typedef struct {
43 unsigned int stream_id; /* http2 protocol stream id */
44 char *channel_id; /* string return by server to identify a specific stream
45 channel, different from stream identifier which is a
46 field in http2 frame */
47 stream_type_t stream_type; /* check @stream_type_t */
48 void *semaphore; /* semaphore for http2 response sync */
49 char status_code[5]; /* http2 response status code */
50 uint8_t rcv_hd_cnt; /* the number of concerned heads received*/
51 void *user_data; /* data passed to the stream callback function */
52 http2_list_t list; /* list_head */
53 } http2_stream_node_t;
54
55 static device_info g_device_info;
56
57 static stream_handle_t *g_stream_handle = NULL;
58 static httpclient_t g_client;
59
_set_device_info(device_conn_info_t * device_info)60 static int _set_device_info(device_conn_info_t *device_info)
61 {
62 memset(g_device_info.product_key, 0, IOTX_PRODUCT_KEY_LEN + 1);
63 memset(g_device_info.device_name, 0, IOTX_DEVICE_NAME_LEN + 1);
64 memset(g_device_info.device_secret, 0, IOTX_DEVICE_SECRET_LEN + 1);
65 memset(g_device_info.url, 0, URL_MAX_LEN + 1);
66
67 strncpy(g_device_info.product_key, device_info->product_key,
68 IOTX_PRODUCT_KEY_LEN);
69 strncpy(g_device_info.device_name, device_info->device_name,
70 IOTX_DEVICE_NAME_LEN);
71 strncpy(g_device_info.device_secret, device_info->device_secret,
72 IOTX_DEVICE_SECRET_LEN);
73 if (device_info->url != NULL) {
74 strncpy(g_device_info.url, device_info->url, URL_MAX_LEN);
75 }
76 g_device_info.port = device_info->port;
77
78 return 0;
79 }
80
http2_nv_copy(http2_header * nva,int start,http2_header * nva_copy,int num)81 static int http2_nv_copy(http2_header *nva, int start, http2_header *nva_copy,
82 int num)
83 {
84 int i, j;
85 for (i = start, j = 0; j < num; i++, j++) {
86 nva[i].name = nva_copy[j].name;
87 nva[i].value = nva_copy[j].value;
88 nva[i].namelen = nva_copy[j].namelen;
89 nva[i].valuelen = nva_copy[j].valuelen;
90 }
91 return i;
92 }
93
iotx_http2_get_url(char * buf,char * productkey)94 static int iotx_http2_get_url(char *buf, char *productkey)
95 {
96 if (strlen(g_device_info.url) != 0) {
97 strncpy(buf, g_device_info.url, URL_MAX_LEN);
98 return g_device_info.port;
99 }
100 #if defined(ON_DAILY)
101 sprintf(buf, "%s", "10.101.12.205");
102 return 9999;
103 #elif defined(ON_PRE)
104 sprintf(buf, "%s", "100.67.141.158");
105 return 8443;
106 #else
107 sprintf(buf, "%s", productkey);
108 strcat(buf, ".iot-as-http2.cn-shanghai.aliyuncs.com");
109 return 443;
110 #endif
111 }
112
file_upload_gen_string(char * str,int type,char * para1,int para2)113 static void file_upload_gen_string(char *str, int type, char *para1, int para2)
114 {
115 switch (type) {
116 case NUM_STRING_ENUM:
117 {
118 sprintf(str, "%d", para2);
119 break;
120 }
121 case PATH_CREATE_STR_ENUM:
122 case PATH_UPLOAD_STR_ENUM:
123 case ORI_SIGN_STR_ENUM:
124 case CID_STRING_ENUM:
125 {
126 if (type == PATH_CREATE_STR_ENUM) {
127 sprintf(str, "/message/pub_with_resp/sys/%s/%s/thing/%s/create",
128 g_device_info.product_key, g_device_info.device_name,
129 para1);
130 } else if (type == PATH_UPLOAD_STR_ENUM) {
131 sprintf(str, "/message/pub_with_resp/sys/%s/%s/thing/%s/upload",
132 g_device_info.product_key, g_device_info.device_name,
133 para1);
134 } else if (type == ORI_SIGN_STR_ENUM) {
135 sprintf(str, "clientId%sdeviceName%sproductKey%s", para1,
136 g_device_info.device_name, g_device_info.product_key);
137 } else {
138 sprintf(str, "%s.%s", g_device_info.product_key,
139 g_device_info.device_name);
140 }
141 break;
142 }
143 case REAL_SIGN_STR_ENUM:
144 {
145 utils_hmac_sha1(para1, strlen(para1), str,
146 g_device_info.device_secret,
147 strlen(g_device_info.device_secret));
148 break;
149 }
150 default:
151 {
152 h2_err("ASSERT\n");
153 break;
154 }
155 }
156 }
157
http2_stream_node_search(stream_handle_t * handle,unsigned int stream_id,http2_stream_node_t ** p_node)158 static int http2_stream_node_search(stream_handle_t *handle,
159 unsigned int stream_id,
160 http2_stream_node_t **p_node)
161 {
162 http2_stream_node_t *search_node = NULL;
163 *p_node = NULL;
164
165 POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
166 POINTER_SANITY_CHECK(p_node, NULL_VALUE_ERROR);
167
168 list_for_each_entry(search_node, &handle->stream_list, list,
169 http2_stream_node_t)
170 {
171 if (search_node->stream_id == stream_id) {
172 *p_node = search_node;
173 return SUCCESS_RETURN;
174 }
175 }
176
177 h2_debug("stream node not exist, stream_id = %d", stream_id);
178 return FAIL_RETURN;
179 }
180
on_stream_header(int32_t stream_id,int cat,const uint8_t * name,uint32_t namelen,const uint8_t * value,uint32_t valuelen,uint8_t flags)181 static void on_stream_header(int32_t stream_id, int cat, const uint8_t *name,
182 uint32_t namelen, const uint8_t *value,
183 uint32_t valuelen, uint8_t flags)
184 {
185 http2_stream_node_t *node = NULL;
186 char *channel_id = NULL;
187 char *user_data = NULL;
188
189 if (g_stream_handle == NULL) {
190 return;
191 }
192 http2_stream_node_search(g_stream_handle, stream_id, &node);
193 if (node != NULL) {
194 channel_id = node->channel_id;
195 user_data = node->user_data;
196
197 switch (cat) {
198 case 0x01:
199 if (strncmp((char *)name, "x-data-stream-id", (int)namelen) == 0) {
200 node->channel_id = HTTP2_STREAM_MALLOC(valuelen + 1);
201 if (node->channel_id == NULL) {
202 return;
203 }
204 memset(node->channel_id, 0, (int)valuelen + 1);
205 memcpy(node->channel_id, (char *)value, (int)valuelen);
206 if (++node->rcv_hd_cnt == 2) {
207 HAL_SemaphorePost(node->semaphore);
208 }
209 }
210 #ifdef FS_ENABLED
211 else if (strncmp((char *)name, "x-file-upload-id", (int)namelen) ==
212 0) {
213 fs_rsp_header_val_t *rsp_data =
214 (fs_rsp_header_val_t *)user_data;
215 memcpy(rsp_data->fs_upload_id, value, valuelen);
216 } else if (strncmp((char *)name, "x-next-append-position",
217 (int)namelen) == 0) {
218 fs_rsp_header_val_t *rsp_data =
219 (fs_rsp_header_val_t *)user_data;
220 rsp_data->fs_offset = atoi((char *)value);
221 } else if (strncmp((char *)name, "x-response-status",
222 (int)namelen) == 0) {
223 strncpy(node->status_code, (char *)value,
224 sizeof(node->status_code) - 1);
225 if (++node->rcv_hd_cnt == 2) {
226 HAL_SemaphorePost(node->semaphore);
227 }
228 }
229 #else
230 else if (strncmp((char *)name, ":status", (int)namelen) == 0) {
231 strncpy(node->status_code, (char *)value,
232 sizeof(node->status_code) - 1);
233 if (++node->rcv_hd_cnt == 2) {
234 HAL_SemaphorePost(node->semaphore);
235 }
236 }
237 #endif
238 }
239 }
240
241 if (g_stream_handle->cbs && g_stream_handle->cbs->on_stream_header_cb) {
242 g_stream_handle->cbs->on_stream_header_cb(stream_id, channel_id, cat,
243 name, namelen, value,
244 valuelen, flags, user_data);
245 }
246 }
247
on_stream_chunk_recv(int32_t stream_id,const uint8_t * data,uint32_t len,uint8_t flags)248 static void on_stream_chunk_recv(int32_t stream_id, const uint8_t *data,
249 uint32_t len, uint8_t flags)
250 {
251 http2_stream_node_t *node;
252 char *channel_id = NULL;
253 char *user_data = NULL;
254
255 if (g_stream_handle == NULL) {
256 return;
257 }
258 http2_stream_node_search(g_stream_handle, stream_id, &node);
259 if (node != NULL) {
260 channel_id = node->channel_id;
261 user_data = node->user_data;
262 }
263
264 if (g_stream_handle->cbs && g_stream_handle->cbs->on_stream_chunk_recv_cb) {
265 g_stream_handle->cbs->on_stream_chunk_recv_cb(
266 stream_id, channel_id, data, len, flags, user_data);
267 }
268 }
269
on_stream_close(int32_t stream_id,uint32_t error_code)270 static void on_stream_close(int32_t stream_id, uint32_t error_code)
271 {
272 http2_stream_node_t *node;
273 char *channel_id = NULL;
274 char *user_data = NULL;
275
276 if (g_stream_handle == NULL) {
277 return;
278 }
279 http2_stream_node_search(g_stream_handle, stream_id, &node);
280 if (node != NULL) {
281 channel_id = node->channel_id;
282 user_data = node->user_data;
283 }
284 if (g_stream_handle->cbs && g_stream_handle->cbs->on_stream_close_cb) {
285 g_stream_handle->cbs->on_stream_close_cb(stream_id, channel_id,
286 error_code, user_data);
287 }
288 }
289
on_stream_frame_send(int32_t stream_id,int type,uint8_t flags)290 static void on_stream_frame_send(int32_t stream_id, int type, uint8_t flags)
291 {
292 http2_stream_node_t *node;
293 char *channel_id = NULL;
294 char *user_data = NULL;
295
296 if (g_stream_handle == NULL) {
297 return;
298 }
299 http2_stream_node_search(g_stream_handle, stream_id, &node);
300 if (node != NULL) {
301 channel_id = node->channel_id;
302 user_data = node->user_data;
303 }
304 if (g_stream_handle->cbs && g_stream_handle->cbs->on_stream_frame_send_cb) {
305 g_stream_handle->cbs->on_stream_frame_send_cb(stream_id, channel_id,
306 type, flags, user_data);
307 }
308 }
309
on_stream_frame_recv(int32_t stream_id,int type,uint8_t flags)310 static void on_stream_frame_recv(int32_t stream_id, int type, uint8_t flags)
311 {
312 http2_stream_node_t *node;
313 char *channel_id = NULL;
314 char *user_data = NULL;
315 if (g_stream_handle == NULL) {
316 return;
317 }
318 http2_stream_node_search(g_stream_handle, stream_id, &node);
319 if (node != NULL) {
320 channel_id = node->channel_id;
321 user_data = node->user_data;
322 }
323
324 if (g_stream_handle->cbs && g_stream_handle->cbs->on_stream_frame_recv_cb) {
325 g_stream_handle->cbs->on_stream_frame_recv_cb(stream_id, channel_id,
326 type, flags, user_data);
327 }
328 }
329
330 static http2_user_cb_t my_cb = {
331 .on_user_header_cb = on_stream_header,
332 .on_user_chunk_recv_cb = on_stream_chunk_recv,
333 .on_user_stream_close_cb = on_stream_close,
334 .on_user_frame_send_cb = on_stream_frame_send,
335 .on_user_frame_recv_cb = on_stream_frame_recv,
336 };
337
reconnect(stream_handle_t * handle)338 static int reconnect(stream_handle_t *handle)
339 {
340 char buf[100] = { 0 };
341 http2_connection_t *conn = NULL;
342 int port = 0;
343
344 iotx_http2_client_disconnect(handle->http2_connect);
345 handle->http2_connect = NULL;
346 port = iotx_http2_get_url(buf, g_device_info.product_key);
347 conn =
348 iotx_http2_client_connect_with_cb((void *)&g_client, buf, port, &my_cb);
349 if (conn == NULL) {
350 return -1;
351 }
352 handle->http2_connect = conn;
353 return 0;
354 }
355
http2_io(void * user_data)356 static void *http2_io(void *user_data)
357 {
358 stream_handle_t *handle = (stream_handle_t *)user_data;
359 int rv = 0;
360 iotx_time_t timer, timer_rsp;
361 static uint8_t timer_valid = 0;
362 POINTER_SANITY_CHECK(handle, NULL);
363 iotx_time_init(&timer);
364 iotx_time_init(&timer_rsp);
365 while (handle->init_state) {
366 if (handle->connect_state) {
367 HAL_MutexLock(handle->mutex);
368 rv = iotx_http2_exec_io(handle->http2_connect);
369 HAL_MutexUnlock(handle->mutex);
370 }
371 if (utils_time_is_expired(&timer)) {
372 HAL_MutexLock(handle->mutex);
373 rv = iotx_http2_client_send_ping(handle->http2_connect);
374 HAL_MutexUnlock(handle->mutex);
375 utils_time_countdown_ms(&timer, IOT_HTTP2_KEEP_ALIVE_TIME);
376 if (rv >= 0) {
377 utils_time_countdown_ms(&timer_rsp, 3000);
378 timer_valid = 1;
379 }
380 }
381
382 if (timer_valid && utils_time_is_expired(&timer_rsp)) {
383 timer_valid = 0;
384 rv = iotx_http2_client_recv_ping();
385 }
386
387 if (rv < 0) {
388 if (handle->retry_cnt == IOT_HTTP2_KEEP_ALIVE_CNT - 1) {
389 h2_info("rv =%d, try reconnect\n", rv);
390 if (handle->connect_state != 0) {
391 handle->connect_state = 0;
392 if (handle->cbs && handle->cbs->on_disconnect_cb) {
393 handle->cbs->on_disconnect_cb();
394 }
395 }
396 rv = reconnect(handle);
397 continue;
398 } else {
399 handle->retry_cnt++;
400 }
401 } else {
402 if (handle->connect_state == 0) {
403 handle->connect_state = 1;
404 handle->retry_cnt = 0;
405 if (handle->cbs && handle->cbs->on_reconnect_cb) {
406 handle->cbs->on_reconnect_cb();
407 }
408 }
409 }
410 HAL_SleepMs(100);
411 }
412 HAL_SemaphorePost(handle->semaphore);
413
414 return NULL;
415 }
416
http2_stream_node_insert(stream_handle_t * handle,unsigned int id,void * user_data,http2_stream_node_t ** p_node)417 static int http2_stream_node_insert(stream_handle_t *handle, unsigned int id,
418 void *user_data,
419 http2_stream_node_t **p_node)
420 {
421 http2_stream_node_t *node = NULL;
422 void *semaphore = NULL;
423
424 POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
425
426 ARGUMENT_SANITY_CHECK(id != 0, FAIL_RETURN);
427
428 if (p_node != NULL) {
429 *p_node = NULL;
430 }
431
432 node =
433 (http2_stream_node_t *)HTTP2_STREAM_MALLOC(sizeof(http2_stream_node_t));
434 if (node == NULL) {
435 return FAIL_RETURN;
436 }
437
438 memset(node, 0, sizeof(http2_stream_node_t));
439 node->stream_id = id;
440 node->user_data = user_data;
441 semaphore = HAL_SemaphoreCreate();
442 if (semaphore == NULL) {
443 HTTP2_STREAM_FREE(node);
444 return FAIL_RETURN;
445 }
446 node->semaphore = semaphore;
447
448 INIT_LIST_HEAD((list_head_t *)&node->list);
449 list_add((list_head_t *)&node->list, (list_head_t *)&handle->stream_list);
450
451 if (p_node != NULL) {
452 *p_node = node;
453 }
454
455 return SUCCESS_RETURN;
456 }
457
http2_stream_node_remove(stream_handle_t * handle,unsigned int id)458 static int http2_stream_node_remove(stream_handle_t *handle, unsigned int id)
459 {
460 http2_stream_node_t *search_node;
461
462 POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
463 ARGUMENT_SANITY_CHECK(id != 0, FAIL_RETURN);
464
465 list_for_each_entry(search_node, &handle->stream_list, list,
466 http2_stream_node_t)
467 {
468 if (id == search_node->stream_id) {
469 h2_info("stream_node found, delete\n");
470
471 list_del((list_head_t *)&search_node->list);
472 HTTP2_STREAM_FREE(search_node->channel_id);
473 HAL_SemaphoreDestroy(search_node->semaphore);
474 HTTP2_STREAM_FREE(search_node);
475 return SUCCESS_RETURN;
476 }
477 }
478 return FAIL_RETURN;
479 }
480
get_version_int()481 static int get_version_int()
482 {
483 const char *p_version = IOTX_SDK_VERSION;
484 int v_int = 0;
485
486 while (*p_version != 0) {
487 if (*p_version <= '9' && *p_version >= '0') {
488 v_int = v_int * 10 + *p_version - '0';
489 }
490 p_version++;
491 }
492 return v_int;
493 }
494
IOT_HTTP2_Connect(device_conn_info_t * conn_info,http2_stream_cb_t * user_cb)495 void *IOT_HTTP2_Connect(device_conn_info_t *conn_info,
496 http2_stream_cb_t *user_cb)
497 {
498 stream_handle_t *stream_handle = NULL;
499 http2_connection_t *conn = NULL;
500 hal_os_thread_param_t thread_parms = { 0 };
501 char buf[URL_MAX_LEN + 1] = { 0 };
502 int port = 0;
503 int ret = 0;
504
505 POINTER_SANITY_CHECK(conn_info, NULL);
506 POINTER_SANITY_CHECK(conn_info->product_key, NULL);
507 POINTER_SANITY_CHECK(conn_info->device_name, NULL);
508 POINTER_SANITY_CHECK(conn_info->device_secret, NULL);
509
510 memset(&g_client, 0, sizeof(httpclient_t));
511
512 stream_handle = HTTP2_STREAM_MALLOC(sizeof(stream_handle_t));
513 if (stream_handle == NULL) {
514 return NULL;
515 }
516
517 memset(stream_handle, 0, sizeof(stream_handle_t));
518 stream_handle->mutex = HAL_MutexCreate();
519 if (stream_handle->mutex == NULL) {
520 HTTP2_STREAM_FREE(stream_handle);
521 h2_err("mutex create error\n");
522 return NULL;
523 }
524 stream_handle->semaphore = HAL_SemaphoreCreate();
525 if (stream_handle->semaphore == NULL) {
526 h2_err("semaphore create error\n");
527 HAL_MutexDestroy(stream_handle->mutex);
528 HTTP2_STREAM_FREE(stream_handle);
529 return NULL;
530 }
531
532 INIT_LIST_HEAD((list_head_t *)&(stream_handle->stream_list));
533
534 _set_device_info(conn_info);
535 g_stream_handle = stream_handle;
536 g_stream_handle->cbs = user_cb;
537
538 port = iotx_http2_get_url(buf, conn_info->product_key);
539 conn =
540 iotx_http2_client_connect_with_cb((void *)&g_client, buf, port, &my_cb);
541 if (conn == NULL) {
542 HAL_MutexDestroy(stream_handle->mutex);
543 HAL_SemaphoreDestroy(stream_handle->semaphore);
544 HTTP2_STREAM_FREE(stream_handle);
545 return NULL;
546 }
547 stream_handle->http2_connect = conn;
548 stream_handle->init_state = 1;
549
550 thread_parms.stack_size = 6144;
551 thread_parms.name = "http2_io";
552 ret = HAL_ThreadCreate(&stream_handle->rw_thread, http2_io, stream_handle,
553 &thread_parms, NULL);
554 if (ret != 0) {
555 h2_err("thread create error\n");
556 IOT_HTTP2_Disconnect(stream_handle);
557 return NULL;
558 }
559
560 return stream_handle;
561 }
562
IOT_HTTP2_Stream_Open(void * hd,stream_data_info_t * info,header_ext_info_t * header)563 int IOT_HTTP2_Stream_Open(void *hd, stream_data_info_t *info,
564 header_ext_info_t *header)
565 {
566 char client_id[64 + 1] = { 0 };
567 char sign_str[256 + 1] = { 0 };
568 char sign[41 + 1] = { 0 };
569 char path[128] = { 0 };
570 char version[33] = { 0 };
571 int header_count = 0;
572 int header_num;
573 int rv = 0;
574 http2_data h2_data;
575 http2_stream_node_t *node = NULL;
576 stream_handle_t *handle = (stream_handle_t *)hd;
577 http2_header *nva = NULL;
578
579 POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
580 POINTER_SANITY_CHECK(info, NULL_VALUE_ERROR);
581 POINTER_SANITY_CHECK(info->identify, NULL_VALUE_ERROR);
582
583 memset(&h2_data, 0, sizeof(http2_data));
584
585 HAL_Snprintf(path, sizeof(path), "/stream/open/%s", info->identify);
586
587 file_upload_gen_string(client_id, CID_STRING_ENUM, NULL, 0);
588 file_upload_gen_string(sign_str, ORI_SIGN_STR_ENUM, client_id, 0);
589 file_upload_gen_string(sign, REAL_SIGN_STR_ENUM, sign_str, 0);
590
591 HAL_Snprintf(version, sizeof(version), "%d", get_version_int());
592
593 {
594 const http2_header static_header[] = {
595 MAKE_HEADER(":method", "POST"),
596 MAKE_HEADER_CS(":path", path),
597 MAKE_HEADER(":scheme", "https"),
598 MAKE_HEADER("x-auth-name", "devicename"),
599 MAKE_HEADER_CS("x-auth-param-client-id", client_id),
600 MAKE_HEADER("x-auth-param-signmethod", "hmacsha1"),
601 MAKE_HEADER_CS("x-auth-param-product-key",
602 g_device_info.product_key),
603 MAKE_HEADER_CS("x-auth-param-device-name",
604 g_device_info.device_name),
605 MAKE_HEADER_CS("x-auth-param-sign", sign),
606 MAKE_HEADER_CS("x-sdk-version", version),
607 MAKE_HEADER_CS("x-sdk-version-name", IOTX_SDK_VERSION),
608 MAKE_HEADER("x-sdk-platform", "c"),
609 MAKE_HEADER("content-length", "0"),
610 };
611
612 header_num = sizeof(static_header) / sizeof(static_header[0]);
613 if (header != NULL) {
614 header_num += header->num;
615 }
616 nva = (http2_header *)HTTP2_STREAM_MALLOC(sizeof(http2_header) *
617 header_num);
618 if (nva == NULL) {
619 h2_err("nva malloc failed\n");
620 return FAIL_RETURN;
621 }
622
623 /* add external header if it's not NULL */
624 header_count =
625 http2_nv_copy(nva, 0, (http2_header *)static_header,
626 sizeof(static_header) / sizeof(static_header[0]));
627 if (header != NULL) {
628 header_count = http2_nv_copy(
629 nva, header_count, (http2_header *)header->nva, header->num);
630 }
631
632 h2_data.header = (http2_header *)nva;
633 h2_data.header_count = header_count;
634 h2_data.data = NULL;
635 h2_data.len = 0;
636 h2_data.flag = 1;
637 h2_data.stream_id = 0;
638
639 HAL_MutexLock(handle->mutex);
640 rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
641 http2_stream_node_insert(handle, h2_data.stream_id, info->user_data,
642 &node);
643 HTTP2_STREAM_FREE(nva);
644 }
645
646 if (rv < 0) {
647 h2_err("client send error\n");
648 HAL_MutexUnlock(handle->mutex);
649 return FAIL_RETURN;
650 }
651
652 if (node == NULL) {
653 h2_err("node insert failed!");
654 HAL_MutexUnlock(handle->mutex);
655 return FAIL_RETURN;
656 }
657
658 node->stream_type = STREAM_TYPE_AUXILIARY;
659 HAL_MutexUnlock(handle->mutex);
660
661 rv = HAL_SemaphoreWait(node->semaphore, IOT_HTTP2_RES_OVERTIME_MS);
662 if (rv < 0 || memcmp(node->status_code, "200", 3)) {
663 h2_err("semaphore wait overtime or status code error\n");
664 HAL_MutexLock(handle->mutex);
665 http2_stream_node_remove(handle, node->stream_id);
666 HAL_MutexUnlock(handle->mutex);
667 return FAIL_RETURN;
668 }
669 info->channel_id = HTTP2_STREAM_MALLOC(strlen(node->channel_id) + 1);
670 if (info->channel_id == NULL) {
671 h2_err("channel_id malloc failed\n");
672 HAL_MutexLock(handle->mutex);
673 http2_stream_node_remove(handle, node->stream_id);
674 HAL_MutexUnlock(handle->mutex);
675 return FAIL_RETURN;
676 }
677 memset(info->channel_id, 0, strlen(node->channel_id) + 1);
678 strcpy(info->channel_id, node->channel_id);
679
680 return SUCCESS_RETURN;
681 }
682
IOT_HTTP2_Stream_Send_Message(void * hd,const char * identify,char * channel_id,char * data,uint32_t data_len,header_ext_info_t * header)683 int IOT_HTTP2_Stream_Send_Message(void *hd, const char *identify,
684 char *channel_id, char *data,
685 uint32_t data_len, header_ext_info_t *header)
686 {
687 int rv = 0;
688 http2_data h2_data;
689 char path[128] = { 0 };
690 char data_len_str[33] = { 0 };
691 int windows_size;
692 int count = 0;
693 stream_handle_t *handle = (stream_handle_t *)hd;
694 http2_header *nva = NULL;
695 int header_count, header_num;
696 char version[33] = { 0 };
697 POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
698 POINTER_SANITY_CHECK(identify, NULL_VALUE_ERROR);
699 POINTER_SANITY_CHECK(channel_id, NULL_VALUE_ERROR);
700
701 windows_size = iotx_http2_get_available_window_size(handle->http2_connect);
702 while (windows_size < data_len) {
703 h2_warning("windows_size < info->packet_len ,wait ...\n");
704 HAL_SleepMs(100);
705 if (++count > 50) {
706 return FAIL_RETURN;
707 }
708 windows_size =
709 iotx_http2_get_available_window_size(handle->http2_connect);
710 }
711
712 HAL_Snprintf(data_len_str, sizeof(data_len_str), "%d", data_len);
713 HAL_Snprintf(path, sizeof(path), "/stream/send/%s", identify);
714 HAL_Snprintf(version, sizeof(version), "%d", get_version_int());
715
716 {
717 const http2_header static_header[] = {
718 MAKE_HEADER(":method", "POST"),
719 MAKE_HEADER_CS(":path", path),
720 MAKE_HEADER(":scheme", "https"),
721 MAKE_HEADER_CS("content-length", data_len_str),
722 MAKE_HEADER_CS("x-data-stream-id", channel_id),
723 MAKE_HEADER_CS("x-sdk-version", version),
724 MAKE_HEADER_CS("x-sdk-version-name", IOTX_SDK_VERSION),
725 MAKE_HEADER("x-sdk-platform", "c"),
726 };
727
728 header_num = sizeof(static_header) / sizeof(static_header[0]);
729 if (header != NULL) {
730 header_num += header->num;
731 }
732 nva = (http2_header *)HTTP2_STREAM_MALLOC(sizeof(http2_header) *
733 header_num);
734 if (nva == NULL) {
735 h2_err("nva malloc failed\n");
736 return FAIL_RETURN;
737 }
738
739 /* add external header if it's not NULL */
740 header_count =
741 http2_nv_copy(nva, 0, (http2_header *)static_header,
742 sizeof(static_header) / sizeof(static_header[0]));
743 if (header != NULL) {
744 header_count = http2_nv_copy(
745 nva, header_count, (http2_header *)header->nva, header->num);
746 }
747 memset(&h2_data, 0, sizeof(h2_data));
748 h2_data.header = (http2_header *)nva;
749 h2_data.header_count = header_count;
750 h2_data.data = data;
751 h2_data.len = data_len;
752 h2_data.flag = 1;
753
754 HAL_MutexLock(handle->mutex);
755 rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
756 HAL_MutexUnlock(handle->mutex);
757 HTTP2_STREAM_FREE(nva);
758 }
759
760 if (rv < 0) {
761 h2_err("send failed!");
762 return rv;
763 }
764
765 return h2_data.stream_id;
766 }
767
IOT_HTTP2_Stream_Send(void * hd,stream_data_info_t * info,header_ext_info_t * header)768 int IOT_HTTP2_Stream_Send(void *hd, stream_data_info_t *info,
769 header_ext_info_t *header)
770 {
771 int rv = 0;
772 http2_data h2_data;
773 char path[128] = { 0 };
774 char data_len_str[33] = { 0 };
775 int windows_size;
776 int count = 0;
777 http2_stream_node_t *node = NULL;
778 stream_handle_t *handle = (stream_handle_t *)hd;
779 http2_header *nva = NULL;
780
781 POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
782 POINTER_SANITY_CHECK(info, NULL_VALUE_ERROR);
783 POINTER_SANITY_CHECK(info->stream, NULL_VALUE_ERROR);
784 POINTER_SANITY_CHECK(info->channel_id, NULL_VALUE_ERROR);
785 ARGUMENT_SANITY_CHECK(info->stream_len != 0, FAIL_RETURN);
786 ARGUMENT_SANITY_CHECK(info->packet_len != 0, FAIL_RETURN);
787
788 windows_size = iotx_http2_get_available_window_size(handle->http2_connect);
789 while (windows_size < info->packet_len) {
790 h2_warning("windows_size < info->packet_len ,wait ...\n");
791 HAL_SleepMs(100);
792 if (++count > 50) {
793 return FAIL_RETURN;
794 }
795 windows_size =
796 iotx_http2_get_available_window_size(handle->http2_connect);
797 }
798
799 HAL_Snprintf(data_len_str, sizeof(data_len_str), "%d", info->stream_len);
800 HAL_Snprintf(path, sizeof(path), "/stream/send/%s", info->identify);
801 if (info->send_len == 0) { /* first send,need header */
802 int header_count, header_num;
803 char version[33] = { 0 };
804 HAL_Snprintf(version, sizeof(version), "%d", get_version_int());
805 {
806 const http2_header static_header[] = {
807 MAKE_HEADER(":method", "POST"),
808 MAKE_HEADER_CS(":path", path),
809 MAKE_HEADER(":scheme", "https"),
810 MAKE_HEADER_CS("content-length", data_len_str),
811 MAKE_HEADER_CS("x-data-stream-id", info->channel_id),
812 MAKE_HEADER_CS("x-sdk-version", version),
813 MAKE_HEADER_CS("x-sdk-version-name", IOTX_SDK_VERSION),
814 MAKE_HEADER("x-sdk-platform", "c"),
815 };
816
817 header_num = sizeof(static_header) / sizeof(static_header[0]);
818 if (header != NULL) {
819 header_num += header->num;
820 }
821 nva = (http2_header *)HTTP2_STREAM_MALLOC(sizeof(http2_header) *
822 header_num);
823 if (nva == NULL) {
824 h2_err("nva malloc failed\n");
825 return FAIL_RETURN;
826 }
827
828 /* add external header if it's not NULL */
829 header_count =
830 http2_nv_copy(nva, 0, (http2_header *)static_header,
831 sizeof(static_header) / sizeof(static_header[0]));
832 if (header != NULL) {
833 header_count =
834 http2_nv_copy(nva, header_count,
835 (http2_header *)header->nva, header->num);
836 }
837 memset(&h2_data, 0, sizeof(h2_data));
838 h2_data.header = (http2_header *)nva;
839 h2_data.header_count = header_count;
840 h2_data.data = info->stream;
841 h2_data.len = info->packet_len; /* TODO */
842
843 if (info->packet_len + info->send_len ==
844 info->stream_len) { /* last frame */
845 h2_data.flag = 1;
846 } else {
847 h2_data.flag = 0;
848 }
849
850 HAL_MutexLock(handle->mutex);
851 rv =
852 iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
853 http2_stream_node_insert(handle, h2_data.stream_id, info->user_data,
854 &node);
855 HTTP2_STREAM_FREE(nva);
856 }
857
858 if (rv < 0) {
859 h2_err("send failed!");
860 HAL_MutexUnlock(handle->mutex);
861 return FAIL_RETURN;
862 }
863
864 if (node == NULL) {
865 h2_err("node insert failed!");
866 HAL_MutexUnlock(handle->mutex);
867 return FAIL_RETURN;
868 }
869
870 node->stream_type = STREAM_TYPE_UPLOAD;
871 HAL_MutexUnlock(handle->mutex);
872
873 info->h2_stream_id = h2_data.stream_id;
874 info->send_len += info->packet_len;
875 } else {
876 h2_data.header = NULL;
877 h2_data.header_count = 0;
878 h2_data.data = info->stream;
879 h2_data.len = info->packet_len;
880
881 h2_data.stream_id = info->h2_stream_id;
882 if (info->packet_len + info->send_len ==
883 info->stream_len) { /* last frame */
884 h2_data.flag = 1;
885 } else {
886 h2_data.flag = 0;
887 }
888
889 HAL_MutexLock(handle->mutex);
890 rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
891 HAL_MutexUnlock(handle->mutex);
892 if (rv < 0) {
893 return FAIL_RETURN;
894 }
895 info->send_len += info->packet_len;
896 }
897
898 if (h2_data.flag == 1) {
899 http2_stream_node_t *node = NULL;
900 HAL_MutexLock(handle->mutex);
901 http2_stream_node_search(handle, h2_data.stream_id, &node);
902 HAL_MutexUnlock(handle->mutex);
903 if (node == NULL) {
904 h2_err("node search failed!");
905 return FAIL_RETURN;
906 }
907 rv = HAL_SemaphoreWait(node->semaphore, IOT_HTTP2_RES_OVERTIME_MS);
908 if (rv < 0 || memcmp(node->status_code, "200", 3)) {
909 h2_err(
910 "semaphore wait overtime or status code "
911 "error,h2_data.stream_id %d\n",
912 h2_data.stream_id);
913 HAL_MutexLock(handle->mutex);
914 http2_stream_node_remove(handle, node->stream_id);
915 HAL_MutexUnlock(handle->mutex);
916 return FAIL_RETURN;
917 }
918 }
919
920 return rv;
921 }
922
IOT_HTTP2_Stream_Query(void * hd,stream_data_info_t * info,header_ext_info_t * header)923 int IOT_HTTP2_Stream_Query(void *hd, stream_data_info_t *info,
924 header_ext_info_t *header)
925 {
926 int rv = 0;
927 http2_data h2_data;
928 http2_stream_node_t *node = NULL;
929 char path[128] = { 0 };
930 int header_count, header_num;
931 stream_handle_t *handle = (stream_handle_t *)hd;
932 http2_header *nva = NULL;
933 char version[33] = { 0 };
934
935 POINTER_SANITY_CHECK(info, NULL_VALUE_ERROR);
936 POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
937 POINTER_SANITY_CHECK(info->channel_id, NULL_VALUE_ERROR);
938 HAL_Snprintf(version, sizeof(version), "%d", get_version_int());
939 HAL_Snprintf(path, sizeof(path), "/stream/send/%s", info->identify);
940 {
941 const http2_header static_header[] = {
942 MAKE_HEADER(":method", "GET"),
943 MAKE_HEADER_CS(":path", path),
944 MAKE_HEADER(":scheme", "https"),
945 MAKE_HEADER_CS("x-data-stream-id", info->channel_id),
946 MAKE_HEADER("x-test-downstream", "1"),
947 MAKE_HEADER_CS("x-sdk-version", version),
948 MAKE_HEADER_CS("x-sdk-version-name", IOTX_SDK_VERSION),
949 MAKE_HEADER("x-sdk-platform", "c"),
950 };
951
952 header_num = sizeof(static_header) / sizeof(static_header[0]);
953 if (header != NULL) {
954 header_num += header->num;
955 }
956 nva = (http2_header *)HTTP2_STREAM_MALLOC(sizeof(http2_header) *
957 header_num);
958 if (nva == NULL) {
959 h2_err("nva malloc failed\n");
960 return FAIL_RETURN;
961 }
962
963 /* add external header if it's not NULL */
964 header_count =
965 http2_nv_copy(nva, 0, (http2_header *)static_header,
966 sizeof(static_header) / sizeof(static_header[0]));
967 if (header != NULL) {
968 header_count = http2_nv_copy(
969 nva, header_count, (http2_header *)header->nva, header->num);
970 }
971 h2_data.header = (http2_header *)nva;
972 h2_data.header_count = header_count;
973 h2_data.data = NULL;
974 h2_data.len = 0;
975 h2_data.flag = 1;
976 h2_data.stream_id = 0;
977
978 HAL_MutexLock(handle->mutex);
979 rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
980 http2_stream_node_insert(handle, h2_data.stream_id, info->user_data,
981 &node);
982 HTTP2_STREAM_FREE(nva);
983 }
984
985 if (rv < 0) {
986 h2_err("client send error\n");
987 HAL_MutexUnlock(handle->mutex);
988 return rv;
989 }
990
991 if (node == NULL) {
992 h2_err("node insert failed!");
993 HAL_MutexUnlock(handle->mutex);
994 return FAIL_RETURN;
995 }
996
997 node->stream_type = STREAM_TYPE_DOWNLOAD;
998 HAL_MutexUnlock(handle->mutex);
999
1000 rv = HAL_SemaphoreWait(node->semaphore, IOT_HTTP2_RES_OVERTIME_MS);
1001 if (rv < 0 || memcmp(node->status_code, "200", 3)) {
1002 h2_err("semaphore wait overtime or status code error\n");
1003 HAL_MutexLock(handle->mutex);
1004 http2_stream_node_remove(handle, node->stream_id);
1005 HAL_MutexUnlock(handle->mutex);
1006 return FAIL_RETURN;
1007 }
1008
1009 return rv;
1010 }
1011
1012 #ifdef FS_ENABLED
IOT_HTTP2_FS_Close(void * hd,stream_data_info_t * info,header_ext_info_t * header)1013 int IOT_HTTP2_FS_Close(void *hd, stream_data_info_t *info,
1014 header_ext_info_t *header)
1015 {
1016 int rv = 0;
1017 http2_data h2_data;
1018 char path[128] = { 0 };
1019 stream_handle_t *handle = (stream_handle_t *)hd;
1020 char version[33] = { 0 };
1021 char *stream_id = info->channel_id;
1022 int len = strlen(stream_id);
1023 http2_stream_node_t *node, *next;
1024 http2_header *nva = NULL;
1025 int header_count, header_num;
1026
1027 POINTER_SANITY_CHECK(info, NULL_VALUE_ERROR);
1028 POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
1029 POINTER_SANITY_CHECK(info->channel_id, NULL_VALUE_ERROR);
1030 HAL_Snprintf(version, sizeof(version), "%d", get_version_int());
1031 HAL_Snprintf(path, sizeof(path), "/stream/close/%s", info->identify);
1032 {
1033 const http2_header static_header[] = {
1034 MAKE_HEADER(":method", "POST"),
1035 MAKE_HEADER_CS(":path", path),
1036 MAKE_HEADER(":scheme", "https"),
1037 MAKE_HEADER_CS("x-data-stream-id", info->channel_id),
1038 MAKE_HEADER_CS("x-sdk-version", version),
1039 MAKE_HEADER_CS("x-sdk-version-name", IOTX_SDK_VERSION),
1040 MAKE_HEADER("x-sdk-platform", "c"),
1041 };
1042
1043 header_num = sizeof(static_header) / sizeof(static_header[0]);
1044 if (header != NULL) {
1045 header_num += header->num;
1046 }
1047 nva = (http2_header *)HTTP2_STREAM_MALLOC(sizeof(http2_header) *
1048 header_num);
1049 if (nva == NULL) {
1050 h2_err("nva malloc failed\n");
1051 HTTP2_STREAM_FREE(info->channel_id);
1052 return FAIL_RETURN;
1053 }
1054
1055 /* add external header if it's not NULL */
1056 header_count =
1057 http2_nv_copy(nva, 0, (http2_header *)static_header,
1058 sizeof(static_header) / sizeof(static_header[0]));
1059 if (header != NULL) {
1060 header_count = http2_nv_copy(
1061 nva, header_count, (http2_header *)header->nva, header->num);
1062 }
1063
1064 header_count = sizeof(static_header) / sizeof(static_header[0]);
1065 h2_data.header = (http2_header *)static_header;
1066 h2_data.header_count = header_count;
1067 h2_data.data = NULL;
1068 h2_data.len = 0;
1069 h2_data.flag = 1;
1070 h2_data.stream_id = 0;
1071
1072 HAL_MutexLock(handle->mutex);
1073 if (info->send_len < info->stream_len) {
1074 iotx_http2_reset_stream(handle->http2_connect, info->h2_stream_id);
1075 }
1076 rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
1077 http2_stream_node_insert(handle, h2_data.stream_id, info->user_data,
1078 &node);
1079 HTTP2_STREAM_FREE(nva);
1080 }
1081
1082 if (rv < 0) {
1083 h2_err("client send error\n");
1084 HAL_MutexUnlock(handle->mutex);
1085 HTTP2_STREAM_FREE(info->channel_id);
1086 return rv;
1087 }
1088
1089 if (node == NULL) {
1090 h2_err("node insert failed!");
1091 HAL_MutexUnlock(handle->mutex);
1092 HTTP2_STREAM_FREE(info->channel_id);
1093 return FAIL_RETURN;
1094 }
1095
1096 node->stream_type = STREAM_TYPE_AUXILIARY;
1097 HAL_MutexUnlock(handle->mutex);
1098
1099 rv = HAL_SemaphoreWait(node->semaphore, IOT_HTTP2_RES_OVERTIME_MS);
1100 if (rv < 0 || memcmp(node->status_code, "200", 3)) {
1101 h2_err("semaphore wait overtime or status code error\n");
1102 }
1103
1104 /* just delete stream node */
1105 HAL_MutexLock(handle->mutex);
1106 list_for_each_entry_safe(node, next, &handle->stream_list, list,
1107 http2_stream_node_t)
1108 {
1109 if (info->h2_stream_id == node->stream_id) {
1110 h2_info("stream_node found:stream_id= %d, Delete It",
1111 node->stream_id);
1112 list_del((list_head_t *)&node->list);
1113 HTTP2_STREAM_FREE(node->channel_id);
1114 HAL_SemaphoreDestroy(node->semaphore);
1115 HTTP2_STREAM_FREE(node);
1116 continue;
1117 }
1118 if ((node->channel_id != NULL) && (stream_id != NULL) &&
1119 (len == strlen(node->channel_id) &&
1120 !strncmp(node->channel_id, stream_id, len))) {
1121 list_del((list_head_t *)&node->list);
1122 HTTP2_STREAM_FREE(node->channel_id);
1123 HAL_SemaphoreDestroy(node->semaphore);
1124 HTTP2_STREAM_FREE(node);
1125 }
1126 }
1127 HTTP2_STREAM_FREE(info->channel_id);
1128 info->channel_id = NULL;
1129 HAL_MutexUnlock(handle->mutex);
1130
1131 return rv;
1132 }
1133 #endif /* #ifdef FS_ENABLED */
1134
IOT_HTTP2_Stream_Close(void * hd,stream_data_info_t * info)1135 int IOT_HTTP2_Stream_Close(void *hd, stream_data_info_t *info)
1136 {
1137 int rv = 0;
1138 http2_data h2_data;
1139 char path[128] = { 0 };
1140 stream_handle_t *handle = (stream_handle_t *)hd;
1141 char version[33] = { 0 };
1142 char *stream_id = info->channel_id;
1143 int len = strlen(stream_id);
1144 http2_stream_node_t *node, *next;
1145
1146 POINTER_SANITY_CHECK(info, NULL_VALUE_ERROR);
1147 POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
1148 POINTER_SANITY_CHECK(info->channel_id, NULL_VALUE_ERROR);
1149 HAL_Snprintf(version, sizeof(version), "%d", get_version_int());
1150 HAL_Snprintf(path, sizeof(path), "/stream/close/%s", info->identify);
1151 {
1152 const http2_header static_header[] = {
1153 MAKE_HEADER(":method", "POST"),
1154 MAKE_HEADER_CS(":path", path),
1155 MAKE_HEADER(":scheme", "https"),
1156 MAKE_HEADER_CS("x-data-stream-id", info->channel_id),
1157 MAKE_HEADER_CS("x-sdk-version", version),
1158 MAKE_HEADER_CS("x-sdk-version-name", IOTX_SDK_VERSION),
1159 MAKE_HEADER("x-sdk-platform", "c"),
1160 };
1161
1162 int header_count = sizeof(static_header) / sizeof(static_header[0]);
1163 h2_data.header = (http2_header *)static_header;
1164 h2_data.header_count = header_count;
1165 h2_data.data = NULL;
1166 h2_data.len = 0;
1167 h2_data.flag = 1;
1168 h2_data.stream_id = 0;
1169
1170 HAL_MutexLock(handle->mutex);
1171 if (info->send_len < info->stream_len) {
1172 iotx_http2_reset_stream(handle->http2_connect, info->h2_stream_id);
1173 }
1174 rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
1175 HAL_MutexUnlock(handle->mutex);
1176 }
1177
1178 if (rv < 0) {
1179 h2_warning("client send error\n");
1180 }
1181
1182 /* just delete stream node */
1183 HAL_MutexLock(handle->mutex);
1184 list_for_each_entry_safe(node, next, &handle->stream_list, list,
1185 http2_stream_node_t)
1186 {
1187 if (info->h2_stream_id == node->stream_id) {
1188 h2_info("stream_node found:stream_id= %d, Delete It",
1189 node->stream_id);
1190 list_del((list_head_t *)&node->list);
1191 HTTP2_STREAM_FREE(node->channel_id);
1192 HAL_SemaphoreDestroy(node->semaphore);
1193 HTTP2_STREAM_FREE(node);
1194 continue;
1195 }
1196 if ((node->channel_id != NULL) && (stream_id != NULL) &&
1197 (len == strlen(node->channel_id) &&
1198 !strncmp(node->channel_id, stream_id, len))) {
1199 list_del((list_head_t *)&node->list);
1200 HTTP2_STREAM_FREE(node->channel_id);
1201 HAL_SemaphoreDestroy(node->semaphore);
1202 HTTP2_STREAM_FREE(node);
1203 }
1204 }
1205 HTTP2_STREAM_FREE(info->channel_id);
1206 info->channel_id = NULL;
1207 HAL_MutexUnlock(handle->mutex);
1208 return rv;
1209 }
1210
IOT_HTTP2_Disconnect(void * hd)1211 int IOT_HTTP2_Disconnect(void *hd)
1212 {
1213 int ret;
1214 stream_handle_t *handle = (stream_handle_t *)hd;
1215 http2_stream_node_t *node, *next;
1216
1217 POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
1218 handle->init_state = 0;
1219
1220 ret = HAL_SemaphoreWait(handle->semaphore, PLATFORM_WAIT_INFINITE);
1221 if (ret < 0) {
1222 h2_err("semaphore wait err\n");
1223 return FAIL_RETURN;
1224 }
1225
1226 HAL_MutexLock(handle->mutex);
1227 list_for_each_entry_safe(node, next, &handle->stream_list, list,
1228 http2_stream_node_t)
1229 {
1230 list_del((list_head_t *)&node->list);
1231 HTTP2_STREAM_FREE(node->channel_id);
1232 HAL_SemaphoreDestroy(node->semaphore);
1233 HTTP2_STREAM_FREE(node);
1234 }
1235 HAL_MutexUnlock(handle->mutex);
1236 g_stream_handle = NULL;
1237
1238 HAL_MutexDestroy(handle->mutex);
1239 HAL_SemaphoreDestroy(handle->semaphore);
1240
1241 ret = iotx_http2_client_disconnect(handle->http2_connect);
1242 HTTP2_STREAM_FREE(handle);
1243 return ret;
1244 }
1245