blob: b7ab671f7dadcaa0e289dc02c37b480088b38479 [file] [log] [blame]
liubin281ac462023-07-19 14:22:54 +08001/*************************************************************
2Description:
3 MBTK HTTP c file.
4Author:
5 LiuBin
6Date:
7 2020/4/30 13:51:42
8*************************************************************/
9#include <stdio.h>
10#include <stdlib.h>
11#include <ctype.h>
12#include <string.h>
LUOJian99f31df2023-09-28 17:03:24 +080013#include <fcntl.h>
14#include <unistd.h>
15#include <sys/stat.h>
liubin281ac462023-07-19 14:22:54 +080016
17#include "mbtk_http_base.h"
18#include "mbtk_http.h"
19#include "mbtk_http_chunks.h"
20
21/*************************************************************
22 Constants and Macros
23*************************************************************/
LUOJian99f31df2023-09-28 17:03:24 +080024#define BUFFER_SIZE 1024
25
26
liubin281ac462023-07-19 14:22:54 +080027
28/*************************************************************
29 Variables:local
30*************************************************************/
31static mbtk_http_handle_t http_handles[HTTP_HANDLE_MAX] =
32{
33 {
34 .id = -1,
35 .data_cb = NULL,
36 .session_cnt = 0,
37 .session = {NULL}
38 }
39};
40
41/*************************************************************
42 Variables:public
43*************************************************************/
44
45
46/*************************************************************
47 Local Function Declaration
48*************************************************************/
49
50
51/*************************************************************
52 Local Function Definitions
53*************************************************************/
54static void http_session_free(mbtk_http_session_t *session)
55{
56 if(session)
57 {
58 if(session->req.header_cnt > 0)
59 {
60 int index;
61 for(index = 0; index < HTTP_REQUEST_HEADER_MAX; index++)
62 {
63 if(session->req.req_h[index] != NULL)
64 {
65 if(session->req.req_h[index]->value)
66 free(session->req.req_h[index]->value);
67 free(session->req.req_h[index]);
68 session->req.req_h[index] = NULL;
69 }
70 }
71 session->req.header_cnt = 0;
72 }
73
74 if(session->req.content)
75 {
76 free(session->req.content);
77 session->req.content = NULL;
78 }
79
80 if(session->rsp.header_cnt > 0)
81 {
82 int index;
83 for(index = 0; index < HTTP_REQUEST_HEADER_MAX; index++)
84 {
85 if(session->rsp.rsp_h[index] != NULL)
86 {
87 if(session->rsp.rsp_h[index]->value)
88 free(session->rsp.rsp_h[index]->value);
89 free(session->rsp.rsp_h[index]);
90 session->rsp.rsp_h[index] = NULL;
91 }
92 }
93 session->rsp.header_cnt = 0;
94 }
95
96 free(session);
97 }
98}
99
100static int http_session_close(mbtk_http_session_t *session)
101{
102 if(session)
103 {
104 if(session->sock_fd > 0)
105 {
106 if(mbtk_http_close(session->sock_fd))
107 {
108 LOGE("mbtk_http_close() fail.");
109 return -1;
110 }
111 session->sock_fd = -1;
112 }
113
114 session->state = HTTP_SESSION_STATE_NON;
115
116 return 0;
117 }
118
119 return -1;
120}
121
122
123static bool http_handle_check(int handle_id)
124{
125 if(handle_id < 0 || handle_id >= HTTP_HANDLE_MAX
126 || http_handles[handle_id].id < 0)
127 {
128 return FALSE;
129 }
130
131 return TRUE;
132}
133
134static bool http_session_check(int handle_id, int session_id)
135{
136 if(handle_id < 0 || handle_id >= HTTP_HANDLE_MAX
137 || http_handles[handle_id].id < 0
138 || http_handles[handle_id].id != handle_id)
139 {
140 return FALSE;
141 }
142
143 if(session_id < 0 || session_id >= HTTP_SESSION_MAX
144 || http_handles[handle_id].session[session_id] == NULL
145 || http_handles[handle_id].session[session_id]->id != session_id)
146 {
147 return FALSE;
148 }
149
150 return TRUE;
151}
152
153static bool http_is_space_char(char ch)
154{
155 if(ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n')
156 return TRUE;
157
158 return FALSE;
159}
160
161static bool http_str_empty(char *str)
162{
163 if(str == NULL || strlen(str) == 0)
164 return TRUE;
165
166 return FALSE;
167}
168
169
170static int http_url_parse
171(
172 void* url,
173 void *host,
174 void *uri,
175 int *port,
176 bool *is_ssl
177)
178{
179 if(strlen(url) == 0)
180 {
181 return -1;
182 }
183 char *url_ptr = (char*)url;
184 char *host_ptr = (char*)host;
185
186 LOGI("URL[%d]:%s",strlen(url_ptr),url_ptr);
187
188 if(!memcmp(url_ptr,"https://",8))
189 {
190 *is_ssl = TRUE;
191 url_ptr += 8;
192 }
193 else if(!memcmp(url_ptr,"http://",7))
194 {
195 *is_ssl = FALSE;
196 url_ptr += 7;
197 }
198 else
199 {
200 *is_ssl = FALSE;
201 }
202
203 // ptr point to host.
204 while(*url_ptr)
205 {
206 if(*url_ptr == ':' || *url_ptr == '/') // Host end
207 break;
208 if(http_is_space_char(*url_ptr))
209 {
210 url_ptr++;
211 continue;
212 }
213 *host_ptr++ = *url_ptr++;
214 }
215
216 // "www.baidu.com"
217 if(*url_ptr == '\0') // No port and uri
218 {
219 if(*is_ssl)
220 {
221 *port = MBTK_HTTPS_PORT_DEF;
222 }
223 else
224 {
225 *port = MBTK_HTTP_PORT_DEF;
226 }
227 memcpy(uri,"/",1);
228
229 LOGI("HTTP parse success:'%s','%s', %d, %d",(char*)host,(char*)uri,*port,*is_ssl);
230 return 0;
231 }
232 else
233 {
234 //LOGI("Host end with:%x",*url_ptr);
235 if(*url_ptr == ':') // Port exist.
236 {
237 *port = atoi(url_ptr + 1);
238
239 // Point to '/' or NULL
240 while(*url_ptr && *url_ptr != '/')
241 {
242 url_ptr++;
243 }
244
245 // "www.baidu.com:80"
246 if(*url_ptr == '\0') // No uri
247 {
248 if(*port == 0)
249 {
250 if(*is_ssl)
251 {
252 *port = MBTK_HTTPS_PORT_DEF;
253 }
254 else
255 {
256 *port = MBTK_HTTP_PORT_DEF;
257 }
258 }
259 memcpy(uri,"/",1);
260
261 LOGI("HTTP parse success:'%s','%s', %d, %d",(char*)host,(char*)uri,*port,*is_ssl);
262 return 0;
263 }
264 }
265
266 // "www.baidu.com/xxx" or "www.baidu.com:80/xxx"
267 // Now,url_ptr point to '/'
268 if(*url_ptr != '/')
269 {
270 LOGE("URI must start with '/'.");
271 return -1;
272 }
273
274 //LOGI("URL3[%d]:%s",strlen(url_ptr),url_ptr);
275
276 memcpy(uri,url_ptr,strlen(url_ptr));
277
278 if(*port == 0)
279 {
280 if(*is_ssl)
281 {
282 *port = MBTK_HTTPS_PORT_DEF;
283 }
284 else
285 {
286 *port = MBTK_HTTP_PORT_DEF;
287 }
288 }
289
290 LOGI("HTTP parse success:'%s','%s', %d, %d",(char*)host,(char*)uri,*port,*is_ssl);
291 return 0;
292 }
293}
294
295static int http_session_req_head_add(mbtk_http_session_t *session,bool replace,
296 char *name, char *value)
297{
298 if(session == NULL || value == NULL)
299 return -1;
300
301 LOGI("Add request header - %s:%s",name,value);
302
303 int i = 0;
304 while(i < HTTP_REQUEST_HEADER_MAX)
305 {
306 if(session->req.req_h[i]
307 && !strncasecmp(session->req.req_h[i]->name,name,strlen(name))) // Is change value
308 {
309 break;
310 }
311 i++;
312 }
313
314 if(i == HTTP_REQUEST_HEADER_MAX) // Should add new header.
315 {
316 i = 0;
317 while(i < HTTP_REQUEST_HEADER_MAX)
318 {
319 if(session->req.req_h[i] == NULL) // Find NULL request.
320 {
321 session->req.req_h[i] = (mbtk_http_header_t*)malloc(sizeof(mbtk_http_header_t));
322 if(session->req.req_h[i] == NULL)
323 {
324 LOGE("malloc() fail.");
325 return -1;
326 }
327
328 memset(session->req.req_h[i],0x0,sizeof(mbtk_http_header_t));
329 memcpy(session->req.req_h[i]->name, name, strlen(name));
330 session->req.req_h[i]->value = NULL;
331 session->req.header_cnt++;
332 break;
333 }
334 i++;
335 }
336 }
337 else // Is change value
338 {
339 if(!replace)
340 {
341 LOGW("Found this header[%s],no replace.",name);
342 return 0;
343 }
344 }
345
346 if(i == HTTP_REQUEST_HEADER_MAX)
347 {
348 LOGE("Request header is full.");
349 return -1;
350 }
351
352 if(session->req.req_h[i]->value)
353 {
354 free(session->req.req_h[i]->value);
355 }
356 session->req.req_h[i]->value = (char*)malloc(strlen(value) + 1);
357 if(session->req.req_h[i]->value == NULL)
358 {
359 LOGE("malloc() fail.");
360 return -1;
361 }
362 memset(session->req.req_h[i]->value,0x0,strlen(value) + 1);
363 memcpy(session->req.req_h[i]->value,value,strlen(value));
364
365 return 0;
366}
367
368#if 0
369static int http_session_rsp_head_add(mbtk_http_session_t *session,
370 char *name, char *value)
371{
372 if(session == NULL || value == NULL)
373 return -1;
374
375 int i = 0;
376 while(i < HTTP_REQUEST_HEADER_MAX)
377 {
378 if(session->rsp.rsp_h[i] == NULL) // Find NULL request.
379 {
380 session->rsp.rsp_h[i] = (mbtk_http_header_t*)malloc(sizeof(mbtk_http_header_t));
381 if(session->rsp.rsp_h[i] == NULL)
382 {
383 LOGE("malloc() fail.");
384 return -1;
385 }
386
387 memcpy(session->rsp.rsp_h[i]->name,name,strlen(name));
388 session->rsp.rsp_h[i]->value = (char*)malloc(strlen(value) + 1);
389 if(session->rsp.rsp_h[i]->value == NULL)
390 {
391 LOGE("malloc() fail.");
392 return -1;
393 }
394 memset(session->rsp.rsp_h[i]->value,0x0,strlen(value) + 1);
395 memcpy(session->rsp.rsp_h[i]->value,value,strlen(value));
396
397 session->rsp.header_cnt++;
398 return 0;
399 }
400 i++;
401 }
402
403 return -1;
404}
405#endif
406
407static char* http_option_str_get(mbtk_http_option_enum option)
408{
409 switch(option)
410 {
411 case HTTP_OPTION_HEAD:
412 return "HEAD";
413 case HTTP_OPTION_GET:
414 return "GET";
415 case HTTP_OPTION_POST:
416 return "POST";
417 case HTTP_OPTION_PUT:
418 return "PUT";
419 case HTTP_OPTION_DELETE:
420 return "DELETE";
421 case HTTP_OPTION_OPTIONS:
422 return "OPTIONS";
423 case HTTP_OPTION_TRACE:
424 return "TRACE";
425 case HTTP_OPTION_CONNECT:
426 return "CONNECT";
427 case HTTP_OPTION_LINK:
428 return "LINK";
429 case HTTP_OPTION_UNLINK:
430 return "UNLINK";
431 default:
432 return "";
433 }
434}
435
436static char* http_version_str_get(mbtk_http_version_enum version)
437{
438 switch(version)
439 {
440 case HTTP_VERSION_1_0:
441 return "1.0";
442 case HTTP_VERSION_1_1:
443 return "1.1";
444 case HTTP_VERSION_2:
445 return "2";
446 case HTTP_VERSION_3:
447 return "3";
448 default:
449 return "";
450 }
451}
452
453static char* http_header_find(mbtk_http_session_t *session,char* name)
454{
455 int i = 0;
456 while(i < HTTP_REQUEST_HEADER_MAX)
457 {
458 if(session->req.req_h[i] &&
459 !strncasecmp(session->req.req_h[i]->name,name,strlen(name)))
460 {
461 return session->req.req_h[i]->value;
462 }
463
464 i++;
465 }
466 return NULL;
467}
468
469static int http_header_str_get(mbtk_http_header_t *header,char *header_str,int header_str_len)
470{
471 if(header == NULL || header->value == NULL
472 || header_str == NULL)
473 return 0;
474
475 int len = 0;
476 len = snprintf(header_str,header_str_len,"%s: %s\r\n",
477 header->name, header->value);
478
479 return len;
480}
481
482static mbtk_http_version_enum http_version_get_by_str(char *version_str)
483{
484 if(!memcmp(version_str,"1.0",3))
485 return HTTP_VERSION_1_0;
486 else if(!memcmp(version_str,"1.1",3))
487 return HTTP_VERSION_1_1;
488 else if(!memcmp(version_str,"2",1))
489 return HTTP_VERSION_2;
490 else if(!memcmp(version_str,"3",1))
491 return HTTP_VERSION_3;
492 else
493 return HTTP_VERSION_1_1;
494}
495
496static int http_header_read(mbtk_http_session_t *session)
497{
498#define BUFFER_SIZE 2048
499 char line[BUFFER_SIZE];
500 char *ptr = NULL;
501 int len = 0;
LUOJian99f31df2023-09-28 17:03:24 +0800502 int write_len = 0;
liubin281ac462023-07-19 14:22:54 +0800503 while((len = mbtk_http_read_line(session->sock_fd,line,BUFFER_SIZE)) > 0)
504 {
505 if(!memcmp(line,"\r\n",2))
506 {
507 LOGD("Read empty line.");
508 break;
509 }
LUOJian99f31df2023-09-28 17:03:24 +0800510
liubin281ac462023-07-19 14:22:54 +0800511 // Delete "\r\n"
512 ptr = line + len - 1; // Point to last char.
513 while(http_is_space_char(*ptr))
514 {
515 *ptr = '\0';
516 len--;
517 ptr--;
518 }
519
520 LOGV("LINE:%s",line);
LUOJian99f31df2023-09-28 17:03:24 +0800521 if(session->type)
liubin281ac462023-07-19 14:22:54 +0800522 {
LUOJian99f31df2023-09-28 17:03:24 +0800523 /*
524 if(session->file_fd >= 0)
525 {
526 write_len = write(session->file_fd, line, len);
527 if(write_len < len) {
528 LOGE("write() fail.");
529 return -1;
530 }
531 }
532 */
liubin281ac462023-07-19 14:22:54 +0800533 }
LUOJian99f31df2023-09-28 17:03:24 +0800534 else
535 {
536 if(http_handles[session->handle_id].show_rsp_header &&
537 http_handles[session->handle_id].data_cb)
538 {
539 http_handles[session->handle_id].data_cb(session->id,
540 MBTK_HTTP_DATA_HEADER,line,len);
541 }
542
543 }
liubin281ac462023-07-19 14:22:54 +0800544
545 if(!memcmp(line,"HTTP/",5)) // "HTTP/1.1 200 OK"
546 {
547 session->rsp.state_code = atoi(line + 9);
548 session->rsp.version = http_version_get_by_str(line + 5);
549 }
550 else // Is response header item.
551 {
552 if(!strncasecmp(line,"Content-Length",14))
553 {
554 ptr = line + 14;
555 while(ptr && !isdigit(*ptr))
556 {
557 ptr++;
558 }
559
560 if(ptr)
561 {
562 session->rsp.content_length = atol(ptr);
563 }
564 }
565 else if(!strncasecmp(line,"Transfer-Encoding",17))
566 {
567 ptr = line + 17;
568 while(ptr && !isalpha(*ptr))
569 {
570 ptr++;
571 }
572
573 if(ptr && !memcmp(ptr,"chunked",7))
574 {
575 session->rsp.is_chunked = TRUE;
576 }
577 }
578 }
579 }
580#undef BUFFER_SIZE
581
582 LOGD("RSP:HTTP/%s %d, is_chunked:%d,Content-Length:%d",http_version_str_get(session->rsp.version),
583 session->rsp.state_code,session->rsp.is_chunked,session->rsp.content_length);
584
585 return 0;
586}
587
588static int http_session_start_write(mbtk_http_session_t *session)
589{
590 LOGI("Start HTTP write.");
591
592#define BUFFER_SIZE 1024
593 session->state = HTTP_SESSION_STATE_WRITE_HEADER;
594 char buff[BUFFER_SIZE];
595 int len = 0;
596 int index = 0;
597 len += snprintf(buff + len,BUFFER_SIZE - len,"%s %s HTTP/%s\r\n",
598 http_option_str_get(session->option),
599 session->uri,
600 http_version_str_get(session->version));
601
602 // if no set "Host",should set default host.
603 char *host = http_header_find(session,"Host");
604 if(!host)
605 {
606 len += snprintf(buff + len,BUFFER_SIZE - len,"Host: %s\r\n", session->host);
607 }
608
609 if(mbtk_http_write(session->sock_fd,buff,len) != len)
610 {
611 LOGE("mbtk_http_write() fail.");
612 return -1;
613 }
614
615 char header_str[BUFFER_SIZE];
616 int header_str_len = 0;
617 while(index < HTTP_REQUEST_HEADER_MAX)
618 {
619 if(session->req.req_h[index] &&
620 (header_str_len = http_header_str_get(session->req.req_h[index], header_str, BUFFER_SIZE)) > 0)
621 {
622 if(mbtk_http_write(session->sock_fd,header_str,header_str_len) != header_str_len)
623 {
624 LOGE("mbtk_http_write() fail.");
625 return -1;
626 }
627 }
628 index++;
629 }
630
631 // Write request header success.
632 LOGI("HTTP write header complete.");
633
634#undef BUFFER_SIZE
635
636 // Write "\r\n"
637 if(mbtk_http_write(session->sock_fd,"\r\n",2) != 2)
638 {
639 LOGE("mbtk_http_write() fail.");
640 return -1;
641 }
642
643 LOGI("Start write HTTPsession->option. %d", session->option);
644 if(session->option == HTTP_OPTION_POST)
645 {
646 session->state = HTTP_SESSION_STATE_WRITE_CONTENT;
647 LOGI("Start write HTTP content data.");
648
649 if(session->req.content && session->req.content_len > 0)
650 {
651 if(mbtk_http_write(session->sock_fd,session->req.content,session->req.content_len) != session->req.content_len)
652 {
653 LOGE("mbtk_http_write() fail.");
654 return -1;
655 }
656
657 session->state = HTTP_SESSION_STATE_WRITE_END;
658 }
659 }
660 else
661 {
662 session->state = HTTP_SESSION_STATE_WRITE_END;
663
664 LOGI("HTTP write complete.");
665 }
666 return 0;
667}
668
669static int http_session_read_by_chunk(mbtk_http_session_t *session)
670{
671#undef BUFFER_SIZE
672#define BUFFER_SIZE 2048
673 http_chunk_code chunk_code;
674 http_chunker_t chunker;
675 char read_buf[BUFFER_SIZE + 1];
676 int read_len = 0;
677 char chunk_buf[BUFFER_SIZE + 1];
LUOJian99f31df2023-09-28 17:03:24 +0800678 int chunk_len = 0, write_len=0;
liubin281ac462023-07-19 14:22:54 +0800679 http_chunk_init(&chunker);
680 while(TRUE)
681 {
682 read_len = mbtk_http_read(session->sock_fd,read_buf,BUFFER_SIZE,3000);
683 //read_len = mbtk_http_read_line(session->sock_file,read_buf,BUFFER_SIZE);
684 if(read_len <= 0)
685 {
686 LOGE("Read fail.");
687 return -1;
688 }
689
690 chunk_code = http_chunk_parse(&chunker, read_buf, read_len, chunk_buf, &chunk_len);
691 if(chunk_code > CHUNKE_OK) // Fail.
692 {
693 LOGE("http_chunk_parse() fail[err - %d].",chunk_code);
694 return -1;
695 }
696
697 LOGD("Read chunk_len:%d",chunk_len);
698 chunk_buf[chunk_len] = '\0';
699
LUOJian99f31df2023-09-28 17:03:24 +0800700 if(session->type)
701 {
702 if(session->file_fd >= 0)
703 {
704 write_len = write(session->file_fd, chunk_buf, chunk_len);
705 if(write_len < chunk_len) {
706 LOGE("write() fail.");
707 return -1;
708 }
709 }
710 }
711 else
712 {
713 if(http_handles[session->handle_id].data_cb)
714 http_handles[session->handle_id].data_cb(session->id,
715 MBTK_HTTP_DATA_CONTENT,chunk_buf,chunk_len);
716 usleep(100000);
717 }
liubin281ac462023-07-19 14:22:54 +0800718
719 if(CHUNKE_STOP == chunk_code)
720 {
721 if(http_handles[session->handle_id].data_cb)
722 http_handles[session->handle_id].data_cb(session->id,
723 MBTK_HTTP_DATA_COMPLETE,NULL,0);
724
725 break;
726 }
727 }
728
729 LOGV("Chunk read success.");
730
731 return 0;
732}
733
734static int http_session_read_by_length(mbtk_http_session_t *session)
735{
736#undef BUFFER_SIZE
737#define BUFFER_SIZE 2048
738 char read_buf[BUFFER_SIZE + 1];
739 int read_len = 0;
LUOJian99f31df2023-09-28 17:03:24 +0800740 int write_len = 0;
liubin281ac462023-07-19 14:22:54 +0800741 int64 read_count = 0;
742 while(TRUE)
743 {
744 memset(read_buf,0x0,BUFFER_SIZE + 1);
745 read_len = mbtk_http_read(session->sock_fd,read_buf,BUFFER_SIZE,3000);
746 if(read_len <= 0)
747 {
748 LOGE("Read fail.");
749 return -1;
750 }
751
LUOJian99f31df2023-09-28 17:03:24 +0800752
liubin281ac462023-07-19 14:22:54 +0800753 if(read_count + read_len >= session->rsp.content_length) // Read data complete.
754 {
LUOJian99f31df2023-09-28 17:03:24 +0800755 if(session->file_fd >= 0)
756 {
757 write_len = write(session->file_fd, read_buf, read_len);
758 if(write_len < read_len) {
759 LOGE("write() fail.");
760 return -1;
761 }
762 }
763
liubin281ac462023-07-19 14:22:54 +0800764 if(http_handles[session->handle_id].data_cb)
765 {
766 http_handles[session->handle_id].data_cb(session->id,
767 MBTK_HTTP_DATA_CONTENT,read_buf,session->rsp.content_length - read_count);
LUOJian99f31df2023-09-28 17:03:24 +0800768
liubin281ac462023-07-19 14:22:54 +0800769 http_handles[session->handle_id].data_cb(session->id,
770 MBTK_HTTP_DATA_COMPLETE,NULL,0);
771 }
772 break;
773 }
774
LUOJian99f31df2023-09-28 17:03:24 +0800775 LOGE("read_len :%d, session->type:%d\n", read_len, session->type);
776 if(session->type)
777 {
778 if(session->file_fd >= 0)
779 {
780 write_len = write(session->file_fd, read_buf, read_len);
781 if(write_len < read_len) {
782 LOGE("write() fail.");
783 return -1;
784 }
785 }
786 }
787 else
788 {
789 if(http_handles[session->handle_id].data_cb)
790 http_handles[session->handle_id].data_cb(session->id,
791 MBTK_HTTP_DATA_CONTENT,read_buf,read_len);
792 usleep(100000);
793 }
liubin281ac462023-07-19 14:22:54 +0800794
795 read_count += read_len;
LUOJian99f31df2023-09-28 17:03:24 +0800796 LOGE("mbtk1111111111111111111111113by read_count:%d, read_len:%d\n.", read_count, read_len);
797
liubin281ac462023-07-19 14:22:54 +0800798 }
799
800 return 0;
801}
802
803static int http_session_read_by_general(mbtk_http_session_t *session)
804{
805#undef BUFFER_SIZE
806#define BUFFER_SIZE 2048
807 char read_buf[BUFFER_SIZE + 1];
808 int read_len = 0;
LUOJian99f31df2023-09-28 17:03:24 +0800809 int write_len = 0;
liubin281ac462023-07-19 14:22:54 +0800810 while(TRUE)
811 {
812 read_len = mbtk_http_read(session->sock_fd,read_buf,BUFFER_SIZE,1000);
813 if(read_len <= 0)
814 {
815 if(read_len == -2 || read_len == 0) // Timeout or end
816 break;
817
818 LOGW("Read end[read_len - %d].",read_len);
819 //return -1;
820 break;
821 }
LUOJian99f31df2023-09-28 17:03:24 +0800822
liubin281ac462023-07-19 14:22:54 +0800823 read_buf[read_len] = '\0';
824
LUOJian99f31df2023-09-28 17:03:24 +0800825 if(session->type)
826 {
827 if(session->file_fd >= 0)
828 {
829 write_len = write(session->file_fd, read_buf, read_len);
830 if(write_len < read_len) {
831 LOGE("write() fail.");
832 return -1;
833 }
834 }
835 }
836 else
837 {
838 if(http_handles[session->handle_id].data_cb)
839 http_handles[session->handle_id].data_cb(session->id,
840 MBTK_HTTP_DATA_CONTENT,read_buf,read_len);
841
842 usleep(100000);
843 }
844 LOGE("mbtk1111111111111111111111111by general\n.");
845
liubin281ac462023-07-19 14:22:54 +0800846 }
847
848 if(http_handles[session->handle_id].data_cb)
849 http_handles[session->handle_id].data_cb(session->id,
850 MBTK_HTTP_DATA_COMPLETE,NULL,0);
851
LUOJian99f31df2023-09-28 17:03:24 +0800852
liubin281ac462023-07-19 14:22:54 +0800853 return 0;
854}
855
856static int http_session_start_read(mbtk_http_session_t *session)
857{
858 LOGI("Start HTTP read.");
859 int result = 0;
LUOJian99f31df2023-09-28 17:03:24 +0800860
liubin281ac462023-07-19 14:22:54 +0800861// usleep(500000);
LUOJian99f31df2023-09-28 17:03:24 +0800862 if(session->type)
863 {
864 session->file_fd = open("/http_test.txt", O_WRONLY|O_TRUNC|O_CREAT|O_APPEND, 0666);
865
866 if(session->file_fd < 0) {
867 LOGE("open() fail.");
868 return -1;
869 }
870 }
871
liubin281ac462023-07-19 14:22:54 +0800872 session->state = HTTP_SESSION_STATE_READ_HEADER;
873 if(http_header_read(session))
874 {
875 result = -1;
876 goto read_end;
877 }
878
879 if(session->option != HTTP_OPTION_HEAD)
880 {
881 session->state = HTTP_SESSION_STATE_READ_CONTENT;
882 if(session->rsp.is_chunked)
883 {
884 if(http_session_read_by_chunk(session))
885 {
LUOJian99f31df2023-09-28 17:03:24 +0800886 LOGE("http_session_read_by_chunk fail.");
liubin281ac462023-07-19 14:22:54 +0800887 result = -1;
888 goto read_end;
889 }
890 }
891 else if(session->rsp.content_length > 0)
892 {
893 if(http_session_read_by_length(session))
894 {
LUOJian99f31df2023-09-28 17:03:24 +0800895 LOGE("http_session_read_by_length fail.");
liubin281ac462023-07-19 14:22:54 +0800896 result = -1;
897 goto read_end;
898 }
899 }
900 else
901 {
902 if(http_session_read_by_general(session))
903 {
LUOJian99f31df2023-09-28 17:03:24 +0800904 LOGE("http_session_read_by_general fail.");
liubin281ac462023-07-19 14:22:54 +0800905 result = -1;
906 goto read_end;
907 }
908 }
909 }
910 else
911 {
912 if(http_handles[session->handle_id].data_cb)
913 http_handles[session->handle_id].data_cb(session->id,
914 MBTK_HTTP_DATA_COMPLETE,NULL,0);
915 }
916
917read_end:
918 session->state = HTTP_SESSION_STATE_READ_END;
919
LUOJian99f31df2023-09-28 17:03:24 +0800920 if(session->file_fd >= 0)
921 {
922 if(close(session->file_fd))
923 {
924 LOGI("close() fail file_fd:%d",session->file_fd);
925 session->file_fd = -1;
926 return -1;
927 }
928 session->file_fd = -1;
929 }
930
931
liubin281ac462023-07-19 14:22:54 +0800932 LOGI("HTTP request complete[result - %d].",result);
933 if(http_session_close(session))
934 {
935 return -1;
936 }
937
938#if 0
939 // Free session after HTTP request complete.
940 http_session_free(session);
941 http_handles[handle_id].session[session_id] = NULL;
942 http_handles[handle_id].session_cnt--;
943#endif
944
945 return result;
946}
947
948static bool http_session_req_check(mbtk_http_session_t *session)
949{
950 if(session == NULL || session->port == 0 ||
951 strlen(session->host) == 0)
952 {
953 LOGE("Session not set host or port.");
954 return FALSE;
955 }
956
957 if(session->option != HTTP_OPTION_HEAD &&
958 session->option != HTTP_OPTION_POST &&
959 session->option != HTTP_OPTION_GET)
960 {
961 LOGE("Only support HEAD/GET/POST");
962 return FALSE;
963 }
964
965#if 0
966 if(session->version != HTTP_VERSION_1_0 &&
967 session->version != HTTP_VERSION_1_1)
968 {
969 LOGE("Only support HTTP 1.0/1.1");
970 return FALSE;
971 }
972#endif
973
974 if(session->option == HTTP_OPTION_POST)
975 {
976 char *value = NULL;
977 value = http_header_find(session, "Content-Length");
978 if(!value)
979 {
980 LOGE("POST must set 'Content-Length'");
981 return FALSE;
982 }
983 if(session->req.content_len != atoi(value))
984 {
985 LOGE("POST 'Content-Length' error.");
986 return FALSE;
987 }
988
989 value = http_header_find(session, "Content-Type");
990 if(!value)
991 {
992 LOGE("POST must set 'Content-Type'");
993 return FALSE;
994 }
995 }
996
997 return TRUE;
998}
999
1000/*************************************************************
1001 Public Function Definitions
1002*************************************************************/
1003int mbtk_http_handle_get(bool show_rsp_header,mbtk_http_data_callback_func data_cb)
1004{
1005 int index = 0;
1006 int i = 0;
1007 for(; index < HTTP_HANDLE_MAX; index++)
1008 {
1009 if(http_handles[index].id < 0) // Find free handle
1010 {
1011 break;
1012 }
1013 }
1014
1015 if(index == HTTP_HANDLE_MAX)
1016 {
1017 LOGE("HTTP Handle is full.");
1018 return -1;
1019 }
1020
1021 memset(&(http_handles[index]),0x0,sizeof(mbtk_http_handle_t));
1022 http_handles[index].id = index;
1023 http_handles[index].show_rsp_header = show_rsp_header;
1024 http_handles[index].data_cb = data_cb;
1025 http_handles[index].session_cnt = 0;
1026 for(i = 0; i < HTTP_SESSION_MAX; i++)
1027 {
1028 http_handles[index].session[i] = NULL;
1029 }
1030
1031 if(mbtk_http_init())
1032 {
1033 LOGE("mbtk_http_init() fail.");
1034 return -1;
1035 }
1036
1037 return http_handles[index].id;
1038}
1039
1040int mbtk_http_handle_free(int handle_id)
1041{
1042 int i = 0;
1043 if(!http_handle_check(handle_id))
1044 {
1045 LOGE("Handle error.");
1046 return -1;
1047 }
1048
1049 http_handles[handle_id].id = -1;
1050 http_handles[handle_id].data_cb = NULL;
1051 if(http_handles[handle_id].session_cnt > 0)
1052 {
1053 for(i = 0; i < HTTP_SESSION_MAX; i++)
1054 {
1055 if(http_handles[handle_id].session[i] != NULL)
1056 {
1057 if(http_handles[handle_id].session[i]->state != HTTP_SESSION_STATE_NON)
1058 {
1059 if(http_session_close(http_handles[handle_id].session[i]))
1060 {
1061 return -1;
1062 }
1063 }
1064
1065 http_session_free(http_handles[handle_id].session[i]);
1066 http_handles[handle_id].session[i] = NULL;
1067 }
1068 }
1069
1070 http_handles[handle_id].session_cnt = 0;
1071 }
1072
1073 if(mbtk_http_deinit())
1074 {
1075 LOGE("mbtk_http_deinit() fail.");
1076 return -1;
1077 }
1078
1079 return 0;
1080}
1081
1082int mbtk_http_session_create(int handle_id, mbtk_http_option_enum option,
1083 mbtk_http_version_enum version)
1084{
1085 int handle_index = 0;
1086 int session_index = 0;
1087 if(!http_handle_check(handle_id))
1088 {
1089 LOGE("Handle error.");
1090 return -1;
1091 }
1092
1093 for(; handle_index < HTTP_HANDLE_MAX; handle_index++)
1094 {
1095 if(http_handles[handle_index].id == handle_id) // Find handle
1096 {
1097 break;
1098 }
1099 }
1100
1101 if(handle_index == HTTP_HANDLE_MAX)
1102 {
1103 LOGE("No found handle[handle - %d].",handle_id);
1104 return -1;
1105 }
1106
1107 if(http_handles[handle_index].session_cnt >= HTTP_SESSION_MAX)
1108 {
1109 LOGE("Session is full.");
1110 return -1;
1111 }
1112
1113 for(; session_index < HTTP_SESSION_MAX; session_index++)
1114 {
1115 if(http_handles[handle_index].session[session_index] == NULL) // Find first NULL session
1116 {
1117 break;
1118 }
1119 }
1120
1121 if(session_index == HTTP_SESSION_MAX)
1122 {
1123 LOGE("Session is full.");
1124 return -1;
1125 }
1126
1127 mbtk_http_session_t* session = (mbtk_http_session_t*)malloc(sizeof(mbtk_http_session_t));
1128 if(session == NULL)
1129 {
1130 LOGE("malloc() fail.");
1131 return -1;
1132 }
1133 memset(session,0x0,sizeof(mbtk_http_session_t));
1134 session->sock_fd = -1;
LUOJian99f31df2023-09-28 17:03:24 +08001135 session->file_fd = -1;
liubin281ac462023-07-19 14:22:54 +08001136 session->handle_id = handle_id;
1137 session->id = session_index;
1138 session->state = HTTP_SESSION_STATE_NON;
1139 session->is_ssl = FALSE;
LUOJian5f18afe2023-10-09 10:23:34 +08001140 session->ingnore_cert = TRUE;
liubin281ac462023-07-19 14:22:54 +08001141 session->version = version;
1142 session->option = option;
1143 session->req.content_len = 0;
1144 session->req.content_len_send = 0;
1145 session->rsp.is_chunked = FALSE;
1146 session->rsp.content_length = 0;
1147 session->rsp.header_cnt = 0;
1148 http_handles[handle_index].session[session_index] = session;
1149 http_handles[handle_index].session_cnt++;
1150
1151 return session->id;
1152}
1153
1154int mbtk_http_session_option_reset(int handle_id, int session_id, mbtk_http_option_enum option)
1155{
1156 if(!http_session_check(handle_id,session_id))
1157 {
1158 LOGE("Session error.");
1159 return -1;
1160 }
1161
1162 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1163 if(session->state != HTTP_SESSION_STATE_NON)
1164 {
1165 LOGE("Session state error.[%d]",session->state);
1166 return -1;
1167 }
1168
1169 session->option = option;
1170 return 0;
1171}
1172
LUOJian99f31df2023-09-28 17:03:24 +08001173int mbtk_http_session_type_set(int handle_id, int session_id, mbtk_http_type_enum type)
1174{
1175 if(!http_session_check(handle_id,session_id))
1176 {
1177 LOGE("Session error.");
1178 return -1;
1179 }
1180
1181 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1182 if(session->state != HTTP_SESSION_STATE_NON)
1183 {
1184 LOGE("Session state error.[%d]",session->state);
1185 return -1;
1186 }
1187
1188 session->type = type;
1189 LOGE("session->type:%d, type:%d\n", session->type, type);
1190 return 0;
1191}
1192
LUOJian5f18afe2023-10-09 10:23:34 +08001193int mbtk_http_session_ingnore_cert_set(int handle_id, int session_id, bool ingnore_cert)
1194{
1195 if(!http_session_check(handle_id,session_id))
1196 {
1197 LOGE("Session error.");
1198 return -1;
1199 }
1200
1201 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1202
1203 session->ingnore_cert = ingnore_cert;
1204
1205 LOGE("session->ingnore_cert:%d, ingnore_cert:%d\n", session->ingnore_cert, ingnore_cert);
1206 return 0;
1207}
1208
1209
liubin281ac462023-07-19 14:22:54 +08001210int mbtk_http_session_free(int handle_id,int session_id)
1211{
1212 if(!http_session_check(handle_id,session_id))
1213 {
1214 LOGE("Session error.");
1215 return -1;
1216 }
1217
1218 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1219 if(session->state != HTTP_SESSION_STATE_NON)
1220 {
1221 if(http_session_close(session))
1222 {
1223 return -1;
1224 }
1225 }
1226
1227 http_session_free(session);
1228 http_handles[handle_id].session[session_id] = NULL;
1229 http_handles[handle_id].session_cnt--;
1230 return 0;
1231}
1232
1233int mbtk_http_session_url_set(int handle_id,int session_id,void *url)
1234{
1235 if(!http_session_check(handle_id,session_id))
1236 {
1237 LOGE("Session error.");
1238 return -1;
1239 }
1240
1241 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1242 if(session->state == HTTP_SESSION_STATE_NON)
1243 return http_url_parse(url, session->host,session->uri,&(session->port),&(session->is_ssl));
1244 else
1245 {
1246 LOGE("Currenr session is process[state - %d].",session->state);
1247 return -1;
1248 }
1249}
1250
1251int mbtk_http_session_head_add(int handle_id,int session_id,
1252 char *name, char *value)
1253{
1254 if(!http_session_check(handle_id,session_id))
1255 {
1256 LOGE("Session error.");
1257 return -1;
1258 }
1259
1260 if(http_str_empty(name) || http_str_empty(value))
1261 {
1262 LOGE("Param error.");
1263 return -1;
1264 }
1265
1266 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1267 if(session->state == HTTP_SESSION_STATE_NON)
1268 {
1269 int result = http_session_req_head_add(session,TRUE,name,value);
1270 if(!result && !strncasecmp(name,"Content-Length",14))
1271 {
1272 session->req.content_len = atoi(value);
1273 }
1274 return result;
1275 }
1276 else
1277 {
1278 LOGE("Currenr session is process[state - %d].",session->state);
1279 return -1;
1280 }
1281}
1282
1283int mbtk_http_session_content_set(int handle_id,int session_id,
1284 char *content,uint32 content_len)
1285{
1286 if(!http_session_check(handle_id,session_id))
1287 {
1288 LOGE("Session error.");
1289 return -1;
1290 }
1291
1292 if(content_len <= 0 || content_len > HTTP_CONTENT_LEN_MAX)
1293 {
1294 LOGE("Content lenght error[%d].",content_len);
1295 return -1;
1296 }
1297
1298 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1299 if(session->state == HTTP_SESSION_STATE_NON)
1300 {
1301 if(session->option != HTTP_OPTION_POST)
1302 {
1303 LOGE("Content only for post.");
1304 return -1;
1305 }
1306
1307 if(session->req.content)
1308 {
1309 free(session->req.content);
1310 session->req.content_len = 0;
1311 }
1312
1313 session->req.content = (char*)malloc(content_len);
1314 if(session->req.content == NULL)
1315 {
1316 LOGE("malloc() fail.");
1317 return -1;
1318 }
1319
1320 char *content_type = NULL;
1321 if(strlen(content) == content_len) //
1322 {
1323 content_type = "text/plain";
1324 }
1325 else
1326 {
1327 content_type = "application/octet-stream";
1328 }
1329
1330 if(http_session_req_head_add(session, FALSE, "Content-Type", content_type))
1331 {
1332 LOGE("Set 'Content-Type' fail.");
1333 return -1;
1334 }
1335
1336 memcpy(session->req.content,content,content_len);
1337 session->req.content_len = content_len;
1338
1339 char len_str[20] = {0};
1340 snprintf(len_str,20,"%d",content_len);
1341 if(http_session_req_head_add(session,FALSE,"Content-Length",len_str))
1342 {
1343 LOGE("Set 'Content-Length' fail.");
1344 return -1;
1345 }
1346
1347
1348 return 0;
1349 }
1350 else
1351 {
1352 LOGE("Currenr session is process[state - %d].",session->state);
1353 return -1;
1354 }
1355}
1356
1357int mbtk_http_session_start(int handle_id,int session_id)
1358{
1359 if(!http_session_check(handle_id,session_id))
1360 {
1361 LOGE("Session error.");
1362 return -1;
1363 }
1364
1365 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1366 if(session->state == HTTP_SESSION_STATE_NON)
1367 {
1368 if(!http_session_req_check(session))
1369 {
1370 LOGE("http_session_req_check() fail.");
1371 return -1;
1372 }
1373
1374 // Must set "Connection" for post.
1375 if(session->option == HTTP_OPTION_POST)
1376 {
1377 if(http_session_req_head_add(session,FALSE,"Connection","KeepAlive"))
1378 {
1379 LOGE("Set 'Content-Length' fail.");
1380 return -1;
1381 }
1382 }
1383
1384 LOGI("HTTP request start.");
1385 LOGI("host:%s, port:%d, uri:%s",session->host,session->port,session->uri);
LUOJian5f18afe2023-10-09 10:23:34 +08001386 LOGI("is_ssl:%d,ingnore_cert:%d, version:%d, option:%d, content_len:%d",session->is_ssl,
1387 session->ingnore_cert, session->version,session->option,session->req.content_len);
liubin281ac462023-07-19 14:22:54 +08001388
LUOJian5f18afe2023-10-09 10:23:34 +08001389 int sock_fd = mbtk_http_open(session->is_ssl,session->ingnore_cert,session->host,session->port);
1390
liubin281ac462023-07-19 14:22:54 +08001391 if(sock_fd < 0)
1392 {
LUOJian5f18afe2023-10-09 10:23:34 +08001393 LOGE("mbtk_http_open() fail.");
liubin281ac462023-07-19 14:22:54 +08001394 return -1;
1395 }
1396 session->sock_fd = sock_fd;
1397// int fd = mbtk_sock_fd_get(sock_fd);
1398// if(fd < 0) {
1399// LOGE("mbtk_sock_fd_get() fail.");
1400// return -1;
1401// }
1402 // session->sock_file = fdopen(sock_fd,"r");
1403 session->state = HTTP_SESSION_STATE_CONN;
1404
1405// if(!session->sock_file) {
1406// LOGE("fdopen() fail.");
1407// return -1;
1408// }
1409
1410 LOGI("HTTP connected.");
1411
1412 if(http_session_start_write(session))
1413 {
1414 return -1;
1415 }
1416
1417 if(session->state == HTTP_SESSION_STATE_WRITE_END)
1418 {
1419 if(http_session_start_read(session))
1420 {
1421 return -1;
1422 }
1423 }
1424 else
1425 {
1426 LOGI("Waitting post content data...");
1427 }
1428
1429 return 0;
1430 }
1431 else
1432 {
1433 LOGE("Currenr session is process[state - %d].",session->state);
1434 return -1;
1435 }
1436}
1437
1438int mbtk_http_session_content_send(int handle_id,int session_id,
1439 char *data,int data_len)
1440{
1441 if(!http_session_check(handle_id,session_id))
1442 {
1443 LOGE("Session error.");
1444 return -1;
1445 }
1446
1447 if(data_len <= 0 || data_len > HTTP_CONTENT_LEN_MAX)
1448 {
1449 LOGE("Content lenght error[%d].",data_len);
1450 return -1;
1451 }
1452
1453 LOGV("Post send:%d - %s",data_len,data);
1454
1455 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1456 if(session->state == HTTP_SESSION_STATE_WRITE_CONTENT)
1457 {
1458 if(session->option != HTTP_OPTION_POST)
1459 {
1460 LOGE("Content only for post.");
1461 return -1;
1462 }
1463
1464 if(session->req.content || session->req.content_len <= 0)
1465 {
1466 LOGE("This post not spit package.");
1467 return -1;
1468 }
1469
1470 // Discard excess data.
1471 if(session->req.content_len_send + data_len > session->req.content_len)
1472 data_len = session->req.content_len - session->req.content_len_send;
1473
1474 if(data_len != mbtk_http_write(session->sock_fd,data,data_len))
1475 {
1476 return -1;
1477 }
1478
1479 session->req.content_len_send += data_len;
1480
1481 LOGI("HTTP post data send: %d / %d",session->req.content_len_send,
1482 session->req.content_len);
1483
1484 // Post data send complete.
1485 if(session->req.content_len_send >= session->req.content_len)
1486 {
1487 session->state = HTTP_SESSION_STATE_WRITE_END;
1488
1489 LOGI("HTTP write complete.");
1490 if(http_session_start_read(session))
1491 {
1492 return -1;
1493 }
1494 }
1495
1496 return 0;
1497 }
1498 else
1499 {
1500 LOGE("Currenr session state error[%d].",session->state);
1501 return -1;
1502 }
1503}
1504
1505const mbtk_http_session_t* mbtk_http_session_get(int handle_id,int session_id)
1506{
1507 if(!http_session_check(handle_id,session_id))
1508 {
1509 LOGE("Session error.");
1510 return NULL;
1511 }
1512
1513 return http_handles[handle_id].session[session_id];
1514}
LUOJian99f31df2023-09-28 17:03:24 +08001515
1516int mbtk_http_get_file_size(char *file_name)
1517{
1518 int ret;
1519 int fd = -1;
1520 struct stat file_stat;
1521
1522 LOGE("mbtk_http_get_file_size() start\n");
1523
1524 fd = open(file_name, O_RDONLY); // ??¡§¡ã?a???t
1525 if (fd == -1) {
1526 printf("Open file %s failed\n", file_name);
1527 return -1;
1528 }
1529 ret = fstat(fd, &file_stat); // ??¡§¡§????t?¨¢??¡§??
1530 if (ret == -1) {
1531 printf("Get file %s stat failed\n", file_name);
1532 close(fd);
1533 return -1;
1534 }
1535 close(fd);
1536 LOGE("mbtk_http_get_file_size() end\n");
1537 return file_stat.st_size;
1538}
1539
1540
1541int mbtk_http_read_file_data(int handle_id, int session_id,
1542 mbtk_http_data_file_type_enum type,int offset, mbtk_http_data_file_callback_func data_file_cb)
1543{
1544
1545 if(!http_session_check(handle_id,session_id))
1546 {
1547 LOGE("Session error.");
1548 return -1;
1549 }
1550
1551 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1552 if(session != NULL)
1553 {
1554 http_handles[session->handle_id].data_file_cb = data_file_cb;
1555
1556 if(type) //1 read file size
1557 {
1558 int size = mbtk_http_get_file_size("/http_test.txt");
1559 http_handles[session->handle_id].data_file_cb(type, NULL, size);
1560 }else //read file data
1561 {
1562 char buf[1024+1] = {0};
1563 int ret = 0;
1564
1565 int fd = open("/http_test.txt", O_RDONLY);
1566 if (fd == -1) {
1567 printf("Open file %s failed\n", "/http_test.txt");
1568 return -1;
1569 }
1570
1571 if(offset)
1572 {
1573 lseek(fd, offset, SEEK_SET);
1574 }
1575// usleep(500000);
1576 int index = 0;
1577 while(1)
1578 {
1579 memset(buf,0, sizeof(buf));
1580 ret = read(fd, buf, 1024);
1581 printf("ret = %d , ", ret);
1582 usleep(100000);
1583 LOGE("mbtk, read file:%s\n", buf);
1584 if(ret <= 0)
1585 break;
1586
1587 http_handles[session->handle_id].data_file_cb(type, buf, ret);
1588 index++;
1589 }
1590 close(fd);
1591 printf("%d\n", index);
1592
1593 LOGE("read()end index;:%d, ret:%d",index,ret);
1594 }
1595 }
1596
1597
1598 return 0;
1599}
1600
1601
1602
1603