blob: b4e58ee4858a57eb1db8f085ff0e449021ed0074 [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;
1140 session->version = version;
1141 session->option = option;
1142 session->req.content_len = 0;
1143 session->req.content_len_send = 0;
1144 session->rsp.is_chunked = FALSE;
1145 session->rsp.content_length = 0;
1146 session->rsp.header_cnt = 0;
1147 http_handles[handle_index].session[session_index] = session;
1148 http_handles[handle_index].session_cnt++;
1149
1150 return session->id;
1151}
1152
1153int mbtk_http_session_option_reset(int handle_id, int session_id, mbtk_http_option_enum option)
1154{
1155 if(!http_session_check(handle_id,session_id))
1156 {
1157 LOGE("Session error.");
1158 return -1;
1159 }
1160
1161 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1162 if(session->state != HTTP_SESSION_STATE_NON)
1163 {
1164 LOGE("Session state error.[%d]",session->state);
1165 return -1;
1166 }
1167
1168 session->option = option;
1169 return 0;
1170}
1171
LUOJian99f31df2023-09-28 17:03:24 +08001172int mbtk_http_session_type_set(int handle_id, int session_id, mbtk_http_type_enum type)
1173{
1174 if(!http_session_check(handle_id,session_id))
1175 {
1176 LOGE("Session error.");
1177 return -1;
1178 }
1179
1180 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1181 if(session->state != HTTP_SESSION_STATE_NON)
1182 {
1183 LOGE("Session state error.[%d]",session->state);
1184 return -1;
1185 }
1186
1187 session->type = type;
1188 LOGE("session->type:%d, type:%d\n", session->type, type);
1189 return 0;
1190}
1191
liubin281ac462023-07-19 14:22:54 +08001192int mbtk_http_session_free(int handle_id,int session_id)
1193{
1194 if(!http_session_check(handle_id,session_id))
1195 {
1196 LOGE("Session error.");
1197 return -1;
1198 }
1199
1200 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1201 if(session->state != HTTP_SESSION_STATE_NON)
1202 {
1203 if(http_session_close(session))
1204 {
1205 return -1;
1206 }
1207 }
1208
1209 http_session_free(session);
1210 http_handles[handle_id].session[session_id] = NULL;
1211 http_handles[handle_id].session_cnt--;
1212 return 0;
1213}
1214
1215int mbtk_http_session_url_set(int handle_id,int session_id,void *url)
1216{
1217 if(!http_session_check(handle_id,session_id))
1218 {
1219 LOGE("Session error.");
1220 return -1;
1221 }
1222
1223 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1224 if(session->state == HTTP_SESSION_STATE_NON)
1225 return http_url_parse(url, session->host,session->uri,&(session->port),&(session->is_ssl));
1226 else
1227 {
1228 LOGE("Currenr session is process[state - %d].",session->state);
1229 return -1;
1230 }
1231}
1232
1233int mbtk_http_session_head_add(int handle_id,int session_id,
1234 char *name, char *value)
1235{
1236 if(!http_session_check(handle_id,session_id))
1237 {
1238 LOGE("Session error.");
1239 return -1;
1240 }
1241
1242 if(http_str_empty(name) || http_str_empty(value))
1243 {
1244 LOGE("Param error.");
1245 return -1;
1246 }
1247
1248 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1249 if(session->state == HTTP_SESSION_STATE_NON)
1250 {
1251 int result = http_session_req_head_add(session,TRUE,name,value);
1252 if(!result && !strncasecmp(name,"Content-Length",14))
1253 {
1254 session->req.content_len = atoi(value);
1255 }
1256 return result;
1257 }
1258 else
1259 {
1260 LOGE("Currenr session is process[state - %d].",session->state);
1261 return -1;
1262 }
1263}
1264
1265int mbtk_http_session_content_set(int handle_id,int session_id,
1266 char *content,uint32 content_len)
1267{
1268 if(!http_session_check(handle_id,session_id))
1269 {
1270 LOGE("Session error.");
1271 return -1;
1272 }
1273
1274 if(content_len <= 0 || content_len > HTTP_CONTENT_LEN_MAX)
1275 {
1276 LOGE("Content lenght error[%d].",content_len);
1277 return -1;
1278 }
1279
1280 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1281 if(session->state == HTTP_SESSION_STATE_NON)
1282 {
1283 if(session->option != HTTP_OPTION_POST)
1284 {
1285 LOGE("Content only for post.");
1286 return -1;
1287 }
1288
1289 if(session->req.content)
1290 {
1291 free(session->req.content);
1292 session->req.content_len = 0;
1293 }
1294
1295 session->req.content = (char*)malloc(content_len);
1296 if(session->req.content == NULL)
1297 {
1298 LOGE("malloc() fail.");
1299 return -1;
1300 }
1301
1302 char *content_type = NULL;
1303 if(strlen(content) == content_len) //
1304 {
1305 content_type = "text/plain";
1306 }
1307 else
1308 {
1309 content_type = "application/octet-stream";
1310 }
1311
1312 if(http_session_req_head_add(session, FALSE, "Content-Type", content_type))
1313 {
1314 LOGE("Set 'Content-Type' fail.");
1315 return -1;
1316 }
1317
1318 memcpy(session->req.content,content,content_len);
1319 session->req.content_len = content_len;
1320
1321 char len_str[20] = {0};
1322 snprintf(len_str,20,"%d",content_len);
1323 if(http_session_req_head_add(session,FALSE,"Content-Length",len_str))
1324 {
1325 LOGE("Set 'Content-Length' fail.");
1326 return -1;
1327 }
1328
1329
1330 return 0;
1331 }
1332 else
1333 {
1334 LOGE("Currenr session is process[state - %d].",session->state);
1335 return -1;
1336 }
1337}
1338
1339int mbtk_http_session_start(int handle_id,int session_id)
1340{
1341 if(!http_session_check(handle_id,session_id))
1342 {
1343 LOGE("Session error.");
1344 return -1;
1345 }
1346
1347 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1348 if(session->state == HTTP_SESSION_STATE_NON)
1349 {
1350 if(!http_session_req_check(session))
1351 {
1352 LOGE("http_session_req_check() fail.");
1353 return -1;
1354 }
1355
1356 // Must set "Connection" for post.
1357 if(session->option == HTTP_OPTION_POST)
1358 {
1359 if(http_session_req_head_add(session,FALSE,"Connection","KeepAlive"))
1360 {
1361 LOGE("Set 'Content-Length' fail.");
1362 return -1;
1363 }
1364 }
1365
1366 LOGI("HTTP request start.");
1367 LOGI("host:%s, port:%d, uri:%s",session->host,session->port,session->uri);
1368 LOGI("is_ssl:%d, version:%d, option:%d, content_len:%d",session->is_ssl,
1369 session->version,session->option,session->req.content_len);
1370
1371 int sock_fd = mbtk_http_open(session->is_ssl,TRUE,session->host,session->port);
1372 if(sock_fd < 0)
1373 {
1374 return -1;
1375 }
1376 session->sock_fd = sock_fd;
1377// int fd = mbtk_sock_fd_get(sock_fd);
1378// if(fd < 0) {
1379// LOGE("mbtk_sock_fd_get() fail.");
1380// return -1;
1381// }
1382 // session->sock_file = fdopen(sock_fd,"r");
1383 session->state = HTTP_SESSION_STATE_CONN;
1384
1385// if(!session->sock_file) {
1386// LOGE("fdopen() fail.");
1387// return -1;
1388// }
1389
1390 LOGI("HTTP connected.");
1391
1392 if(http_session_start_write(session))
1393 {
1394 return -1;
1395 }
1396
1397 if(session->state == HTTP_SESSION_STATE_WRITE_END)
1398 {
1399 if(http_session_start_read(session))
1400 {
1401 return -1;
1402 }
1403 }
1404 else
1405 {
1406 LOGI("Waitting post content data...");
1407 }
1408
1409 return 0;
1410 }
1411 else
1412 {
1413 LOGE("Currenr session is process[state - %d].",session->state);
1414 return -1;
1415 }
1416}
1417
1418int mbtk_http_session_content_send(int handle_id,int session_id,
1419 char *data,int data_len)
1420{
1421 if(!http_session_check(handle_id,session_id))
1422 {
1423 LOGE("Session error.");
1424 return -1;
1425 }
1426
1427 if(data_len <= 0 || data_len > HTTP_CONTENT_LEN_MAX)
1428 {
1429 LOGE("Content lenght error[%d].",data_len);
1430 return -1;
1431 }
1432
1433 LOGV("Post send:%d - %s",data_len,data);
1434
1435 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1436 if(session->state == HTTP_SESSION_STATE_WRITE_CONTENT)
1437 {
1438 if(session->option != HTTP_OPTION_POST)
1439 {
1440 LOGE("Content only for post.");
1441 return -1;
1442 }
1443
1444 if(session->req.content || session->req.content_len <= 0)
1445 {
1446 LOGE("This post not spit package.");
1447 return -1;
1448 }
1449
1450 // Discard excess data.
1451 if(session->req.content_len_send + data_len > session->req.content_len)
1452 data_len = session->req.content_len - session->req.content_len_send;
1453
1454 if(data_len != mbtk_http_write(session->sock_fd,data,data_len))
1455 {
1456 return -1;
1457 }
1458
1459 session->req.content_len_send += data_len;
1460
1461 LOGI("HTTP post data send: %d / %d",session->req.content_len_send,
1462 session->req.content_len);
1463
1464 // Post data send complete.
1465 if(session->req.content_len_send >= session->req.content_len)
1466 {
1467 session->state = HTTP_SESSION_STATE_WRITE_END;
1468
1469 LOGI("HTTP write complete.");
1470 if(http_session_start_read(session))
1471 {
1472 return -1;
1473 }
1474 }
1475
1476 return 0;
1477 }
1478 else
1479 {
1480 LOGE("Currenr session state error[%d].",session->state);
1481 return -1;
1482 }
1483}
1484
1485const mbtk_http_session_t* mbtk_http_session_get(int handle_id,int session_id)
1486{
1487 if(!http_session_check(handle_id,session_id))
1488 {
1489 LOGE("Session error.");
1490 return NULL;
1491 }
1492
1493 return http_handles[handle_id].session[session_id];
1494}
LUOJian99f31df2023-09-28 17:03:24 +08001495
1496int mbtk_http_get_file_size(char *file_name)
1497{
1498 int ret;
1499 int fd = -1;
1500 struct stat file_stat;
1501
1502 LOGE("mbtk_http_get_file_size() start\n");
1503
1504 fd = open(file_name, O_RDONLY); // ??¡§¡ã?a???t
1505 if (fd == -1) {
1506 printf("Open file %s failed\n", file_name);
1507 return -1;
1508 }
1509 ret = fstat(fd, &file_stat); // ??¡§¡§????t?¨¢??¡§??
1510 if (ret == -1) {
1511 printf("Get file %s stat failed\n", file_name);
1512 close(fd);
1513 return -1;
1514 }
1515 close(fd);
1516 LOGE("mbtk_http_get_file_size() end\n");
1517 return file_stat.st_size;
1518}
1519
1520
1521int mbtk_http_read_file_data(int handle_id, int session_id,
1522 mbtk_http_data_file_type_enum type,int offset, mbtk_http_data_file_callback_func data_file_cb)
1523{
1524
1525 if(!http_session_check(handle_id,session_id))
1526 {
1527 LOGE("Session error.");
1528 return -1;
1529 }
1530
1531 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1532 if(session != NULL)
1533 {
1534 http_handles[session->handle_id].data_file_cb = data_file_cb;
1535
1536 if(type) //1 read file size
1537 {
1538 int size = mbtk_http_get_file_size("/http_test.txt");
1539 http_handles[session->handle_id].data_file_cb(type, NULL, size);
1540 }else //read file data
1541 {
1542 char buf[1024+1] = {0};
1543 int ret = 0;
1544
1545 int fd = open("/http_test.txt", O_RDONLY);
1546 if (fd == -1) {
1547 printf("Open file %s failed\n", "/http_test.txt");
1548 return -1;
1549 }
1550
1551 if(offset)
1552 {
1553 lseek(fd, offset, SEEK_SET);
1554 }
1555// usleep(500000);
1556 int index = 0;
1557 while(1)
1558 {
1559 memset(buf,0, sizeof(buf));
1560 ret = read(fd, buf, 1024);
1561 printf("ret = %d , ", ret);
1562 usleep(100000);
1563 LOGE("mbtk, read file:%s\n", buf);
1564 if(ret <= 0)
1565 break;
1566
1567 http_handles[session->handle_id].data_file_cb(type, buf, ret);
1568 index++;
1569 }
1570 close(fd);
1571 printf("%d\n", index);
1572
1573 LOGE("read()end index;:%d, ret:%d",index,ret);
1574 }
1575 }
1576
1577
1578 return 0;
1579}
1580
1581
1582
1583