blob: e63064eff9477fa007d326c77dcaf727ce126cd6 [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>
13
14#include "mbtk_http_base.h"
15#include "mbtk_http.h"
16#include "mbtk_http_chunks.h"
17
18/*************************************************************
19 Constants and Macros
20*************************************************************/
21
22/*************************************************************
23 Variables:local
24*************************************************************/
25static mbtk_http_handle_t http_handles[HTTP_HANDLE_MAX] =
26{
27 {
28 .id = -1,
29 .data_cb = NULL,
30 .session_cnt = 0,
31 .session = {NULL}
32 }
33};
34
35/*************************************************************
36 Variables:public
37*************************************************************/
38
39
40/*************************************************************
41 Local Function Declaration
42*************************************************************/
43
44
45/*************************************************************
46 Local Function Definitions
47*************************************************************/
48static void http_session_free(mbtk_http_session_t *session)
49{
50 if(session)
51 {
52 if(session->req.header_cnt > 0)
53 {
54 int index;
55 for(index = 0; index < HTTP_REQUEST_HEADER_MAX; index++)
56 {
57 if(session->req.req_h[index] != NULL)
58 {
59 if(session->req.req_h[index]->value)
60 free(session->req.req_h[index]->value);
61 free(session->req.req_h[index]);
62 session->req.req_h[index] = NULL;
63 }
64 }
65 session->req.header_cnt = 0;
66 }
67
68 if(session->req.content)
69 {
70 free(session->req.content);
71 session->req.content = NULL;
72 }
73
74 if(session->rsp.header_cnt > 0)
75 {
76 int index;
77 for(index = 0; index < HTTP_REQUEST_HEADER_MAX; index++)
78 {
79 if(session->rsp.rsp_h[index] != NULL)
80 {
81 if(session->rsp.rsp_h[index]->value)
82 free(session->rsp.rsp_h[index]->value);
83 free(session->rsp.rsp_h[index]);
84 session->rsp.rsp_h[index] = NULL;
85 }
86 }
87 session->rsp.header_cnt = 0;
88 }
89
90 free(session);
91 }
92}
93
94static int http_session_close(mbtk_http_session_t *session)
95{
96 if(session)
97 {
98 if(session->sock_fd > 0)
99 {
100 if(mbtk_http_close(session->sock_fd))
101 {
102 LOGE("mbtk_http_close() fail.");
103 return -1;
104 }
105 session->sock_fd = -1;
106 }
107
108 session->state = HTTP_SESSION_STATE_NON;
109
110 return 0;
111 }
112
113 return -1;
114}
115
116
117static bool http_handle_check(int handle_id)
118{
119 if(handle_id < 0 || handle_id >= HTTP_HANDLE_MAX
120 || http_handles[handle_id].id < 0)
121 {
122 return FALSE;
123 }
124
125 return TRUE;
126}
127
128static bool http_session_check(int handle_id, int session_id)
129{
130 if(handle_id < 0 || handle_id >= HTTP_HANDLE_MAX
131 || http_handles[handle_id].id < 0
132 || http_handles[handle_id].id != handle_id)
133 {
134 return FALSE;
135 }
136
137 if(session_id < 0 || session_id >= HTTP_SESSION_MAX
138 || http_handles[handle_id].session[session_id] == NULL
139 || http_handles[handle_id].session[session_id]->id != session_id)
140 {
141 return FALSE;
142 }
143
144 return TRUE;
145}
146
147static bool http_is_space_char(char ch)
148{
149 if(ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n')
150 return TRUE;
151
152 return FALSE;
153}
154
155static bool http_str_empty(char *str)
156{
157 if(str == NULL || strlen(str) == 0)
158 return TRUE;
159
160 return FALSE;
161}
162
163
164static int http_url_parse
165(
166 void* url,
167 void *host,
168 void *uri,
169 int *port,
170 bool *is_ssl
171)
172{
173 if(strlen(url) == 0)
174 {
175 return -1;
176 }
177 char *url_ptr = (char*)url;
178 char *host_ptr = (char*)host;
179
180 LOGI("URL[%d]:%s",strlen(url_ptr),url_ptr);
181
182 if(!memcmp(url_ptr,"https://",8))
183 {
184 *is_ssl = TRUE;
185 url_ptr += 8;
186 }
187 else if(!memcmp(url_ptr,"http://",7))
188 {
189 *is_ssl = FALSE;
190 url_ptr += 7;
191 }
192 else
193 {
194 *is_ssl = FALSE;
195 }
196
197 // ptr point to host.
198 while(*url_ptr)
199 {
200 if(*url_ptr == ':' || *url_ptr == '/') // Host end
201 break;
202 if(http_is_space_char(*url_ptr))
203 {
204 url_ptr++;
205 continue;
206 }
207 *host_ptr++ = *url_ptr++;
208 }
209
210 // "www.baidu.com"
211 if(*url_ptr == '\0') // No port and uri
212 {
213 if(*is_ssl)
214 {
215 *port = MBTK_HTTPS_PORT_DEF;
216 }
217 else
218 {
219 *port = MBTK_HTTP_PORT_DEF;
220 }
221 memcpy(uri,"/",1);
222
223 LOGI("HTTP parse success:'%s','%s', %d, %d",(char*)host,(char*)uri,*port,*is_ssl);
224 return 0;
225 }
226 else
227 {
228 //LOGI("Host end with:%x",*url_ptr);
229 if(*url_ptr == ':') // Port exist.
230 {
231 *port = atoi(url_ptr + 1);
232
233 // Point to '/' or NULL
234 while(*url_ptr && *url_ptr != '/')
235 {
236 url_ptr++;
237 }
238
239 // "www.baidu.com:80"
240 if(*url_ptr == '\0') // No uri
241 {
242 if(*port == 0)
243 {
244 if(*is_ssl)
245 {
246 *port = MBTK_HTTPS_PORT_DEF;
247 }
248 else
249 {
250 *port = MBTK_HTTP_PORT_DEF;
251 }
252 }
253 memcpy(uri,"/",1);
254
255 LOGI("HTTP parse success:'%s','%s', %d, %d",(char*)host,(char*)uri,*port,*is_ssl);
256 return 0;
257 }
258 }
259
260 // "www.baidu.com/xxx" or "www.baidu.com:80/xxx"
261 // Now,url_ptr point to '/'
262 if(*url_ptr != '/')
263 {
264 LOGE("URI must start with '/'.");
265 return -1;
266 }
267
268 //LOGI("URL3[%d]:%s",strlen(url_ptr),url_ptr);
269
270 memcpy(uri,url_ptr,strlen(url_ptr));
271
272 if(*port == 0)
273 {
274 if(*is_ssl)
275 {
276 *port = MBTK_HTTPS_PORT_DEF;
277 }
278 else
279 {
280 *port = MBTK_HTTP_PORT_DEF;
281 }
282 }
283
284 LOGI("HTTP parse success:'%s','%s', %d, %d",(char*)host,(char*)uri,*port,*is_ssl);
285 return 0;
286 }
287}
288
289static int http_session_req_head_add(mbtk_http_session_t *session,bool replace,
290 char *name, char *value)
291{
292 if(session == NULL || value == NULL)
293 return -1;
294
295 LOGI("Add request header - %s:%s",name,value);
296
297 int i = 0;
298 while(i < HTTP_REQUEST_HEADER_MAX)
299 {
300 if(session->req.req_h[i]
301 && !strncasecmp(session->req.req_h[i]->name,name,strlen(name))) // Is change value
302 {
303 break;
304 }
305 i++;
306 }
307
308 if(i == HTTP_REQUEST_HEADER_MAX) // Should add new header.
309 {
310 i = 0;
311 while(i < HTTP_REQUEST_HEADER_MAX)
312 {
313 if(session->req.req_h[i] == NULL) // Find NULL request.
314 {
315 session->req.req_h[i] = (mbtk_http_header_t*)malloc(sizeof(mbtk_http_header_t));
316 if(session->req.req_h[i] == NULL)
317 {
318 LOGE("malloc() fail.");
319 return -1;
320 }
321
322 memset(session->req.req_h[i],0x0,sizeof(mbtk_http_header_t));
323 memcpy(session->req.req_h[i]->name, name, strlen(name));
324 session->req.req_h[i]->value = NULL;
325 session->req.header_cnt++;
326 break;
327 }
328 i++;
329 }
330 }
331 else // Is change value
332 {
333 if(!replace)
334 {
335 LOGW("Found this header[%s],no replace.",name);
336 return 0;
337 }
338 }
339
340 if(i == HTTP_REQUEST_HEADER_MAX)
341 {
342 LOGE("Request header is full.");
343 return -1;
344 }
345
346 if(session->req.req_h[i]->value)
347 {
348 free(session->req.req_h[i]->value);
349 }
350 session->req.req_h[i]->value = (char*)malloc(strlen(value) + 1);
351 if(session->req.req_h[i]->value == NULL)
352 {
353 LOGE("malloc() fail.");
354 return -1;
355 }
356 memset(session->req.req_h[i]->value,0x0,strlen(value) + 1);
357 memcpy(session->req.req_h[i]->value,value,strlen(value));
358
359 return 0;
360}
361
362#if 0
363static int http_session_rsp_head_add(mbtk_http_session_t *session,
364 char *name, char *value)
365{
366 if(session == NULL || value == NULL)
367 return -1;
368
369 int i = 0;
370 while(i < HTTP_REQUEST_HEADER_MAX)
371 {
372 if(session->rsp.rsp_h[i] == NULL) // Find NULL request.
373 {
374 session->rsp.rsp_h[i] = (mbtk_http_header_t*)malloc(sizeof(mbtk_http_header_t));
375 if(session->rsp.rsp_h[i] == NULL)
376 {
377 LOGE("malloc() fail.");
378 return -1;
379 }
380
381 memcpy(session->rsp.rsp_h[i]->name,name,strlen(name));
382 session->rsp.rsp_h[i]->value = (char*)malloc(strlen(value) + 1);
383 if(session->rsp.rsp_h[i]->value == NULL)
384 {
385 LOGE("malloc() fail.");
386 return -1;
387 }
388 memset(session->rsp.rsp_h[i]->value,0x0,strlen(value) + 1);
389 memcpy(session->rsp.rsp_h[i]->value,value,strlen(value));
390
391 session->rsp.header_cnt++;
392 return 0;
393 }
394 i++;
395 }
396
397 return -1;
398}
399#endif
400
401static char* http_option_str_get(mbtk_http_option_enum option)
402{
403 switch(option)
404 {
405 case HTTP_OPTION_HEAD:
406 return "HEAD";
407 case HTTP_OPTION_GET:
408 return "GET";
409 case HTTP_OPTION_POST:
410 return "POST";
411 case HTTP_OPTION_PUT:
412 return "PUT";
413 case HTTP_OPTION_DELETE:
414 return "DELETE";
415 case HTTP_OPTION_OPTIONS:
416 return "OPTIONS";
417 case HTTP_OPTION_TRACE:
418 return "TRACE";
419 case HTTP_OPTION_CONNECT:
420 return "CONNECT";
421 case HTTP_OPTION_LINK:
422 return "LINK";
423 case HTTP_OPTION_UNLINK:
424 return "UNLINK";
425 default:
426 return "";
427 }
428}
429
430static char* http_version_str_get(mbtk_http_version_enum version)
431{
432 switch(version)
433 {
434 case HTTP_VERSION_1_0:
435 return "1.0";
436 case HTTP_VERSION_1_1:
437 return "1.1";
438 case HTTP_VERSION_2:
439 return "2";
440 case HTTP_VERSION_3:
441 return "3";
442 default:
443 return "";
444 }
445}
446
447static char* http_header_find(mbtk_http_session_t *session,char* name)
448{
449 int i = 0;
450 while(i < HTTP_REQUEST_HEADER_MAX)
451 {
452 if(session->req.req_h[i] &&
453 !strncasecmp(session->req.req_h[i]->name,name,strlen(name)))
454 {
455 return session->req.req_h[i]->value;
456 }
457
458 i++;
459 }
460 return NULL;
461}
462
463static int http_header_str_get(mbtk_http_header_t *header,char *header_str,int header_str_len)
464{
465 if(header == NULL || header->value == NULL
466 || header_str == NULL)
467 return 0;
468
469 int len = 0;
470 len = snprintf(header_str,header_str_len,"%s: %s\r\n",
471 header->name, header->value);
472
473 return len;
474}
475
476static mbtk_http_version_enum http_version_get_by_str(char *version_str)
477{
478 if(!memcmp(version_str,"1.0",3))
479 return HTTP_VERSION_1_0;
480 else if(!memcmp(version_str,"1.1",3))
481 return HTTP_VERSION_1_1;
482 else if(!memcmp(version_str,"2",1))
483 return HTTP_VERSION_2;
484 else if(!memcmp(version_str,"3",1))
485 return HTTP_VERSION_3;
486 else
487 return HTTP_VERSION_1_1;
488}
489
490static int http_header_read(mbtk_http_session_t *session)
491{
492#define BUFFER_SIZE 2048
493 char line[BUFFER_SIZE];
494 char *ptr = NULL;
495 int len = 0;
496 while((len = mbtk_http_read_line(session->sock_fd,line,BUFFER_SIZE)) > 0)
497 {
498 if(!memcmp(line,"\r\n",2))
499 {
500 LOGD("Read empty line.");
501 break;
502 }
503
504 // Delete "\r\n"
505 ptr = line + len - 1; // Point to last char.
506 while(http_is_space_char(*ptr))
507 {
508 *ptr = '\0';
509 len--;
510 ptr--;
511 }
512
513 LOGV("LINE:%s",line);
514
515 if(http_handles[session->handle_id].show_rsp_header &&
516 http_handles[session->handle_id].data_cb)
517 {
518 http_handles[session->handle_id].data_cb(session->id,
519 MBTK_HTTP_DATA_HEADER,line,len);
520 }
521
522 if(!memcmp(line,"HTTP/",5)) // "HTTP/1.1 200 OK"
523 {
524 session->rsp.state_code = atoi(line + 9);
525 session->rsp.version = http_version_get_by_str(line + 5);
526 }
527 else // Is response header item.
528 {
529 if(!strncasecmp(line,"Content-Length",14))
530 {
531 ptr = line + 14;
532 while(ptr && !isdigit(*ptr))
533 {
534 ptr++;
535 }
536
537 if(ptr)
538 {
539 session->rsp.content_length = atol(ptr);
540 }
541 }
542 else if(!strncasecmp(line,"Transfer-Encoding",17))
543 {
544 ptr = line + 17;
545 while(ptr && !isalpha(*ptr))
546 {
547 ptr++;
548 }
549
550 if(ptr && !memcmp(ptr,"chunked",7))
551 {
552 session->rsp.is_chunked = TRUE;
553 }
554 }
555 }
556 }
557#undef BUFFER_SIZE
558
559 LOGD("RSP:HTTP/%s %d, is_chunked:%d,Content-Length:%d",http_version_str_get(session->rsp.version),
560 session->rsp.state_code,session->rsp.is_chunked,session->rsp.content_length);
561
562 return 0;
563}
564
565static int http_session_start_write(mbtk_http_session_t *session)
566{
567 LOGI("Start HTTP write.");
568
569#define BUFFER_SIZE 1024
570 session->state = HTTP_SESSION_STATE_WRITE_HEADER;
571 char buff[BUFFER_SIZE];
572 int len = 0;
573 int index = 0;
574 len += snprintf(buff + len,BUFFER_SIZE - len,"%s %s HTTP/%s\r\n",
575 http_option_str_get(session->option),
576 session->uri,
577 http_version_str_get(session->version));
578
579 // if no set "Host",should set default host.
580 char *host = http_header_find(session,"Host");
581 if(!host)
582 {
583 len += snprintf(buff + len,BUFFER_SIZE - len,"Host: %s\r\n", session->host);
584 }
585
586 if(mbtk_http_write(session->sock_fd,buff,len) != len)
587 {
588 LOGE("mbtk_http_write() fail.");
589 return -1;
590 }
591
592 char header_str[BUFFER_SIZE];
593 int header_str_len = 0;
594 while(index < HTTP_REQUEST_HEADER_MAX)
595 {
596 if(session->req.req_h[index] &&
597 (header_str_len = http_header_str_get(session->req.req_h[index], header_str, BUFFER_SIZE)) > 0)
598 {
599 if(mbtk_http_write(session->sock_fd,header_str,header_str_len) != header_str_len)
600 {
601 LOGE("mbtk_http_write() fail.");
602 return -1;
603 }
604 }
605 index++;
606 }
607
608 // Write request header success.
609 LOGI("HTTP write header complete.");
610
611#undef BUFFER_SIZE
612
613 // Write "\r\n"
614 if(mbtk_http_write(session->sock_fd,"\r\n",2) != 2)
615 {
616 LOGE("mbtk_http_write() fail.");
617 return -1;
618 }
619
620 LOGI("Start write HTTPsession->option. %d", session->option);
621 if(session->option == HTTP_OPTION_POST)
622 {
623 session->state = HTTP_SESSION_STATE_WRITE_CONTENT;
624 LOGI("Start write HTTP content data.");
625
626 if(session->req.content && session->req.content_len > 0)
627 {
628 if(mbtk_http_write(session->sock_fd,session->req.content,session->req.content_len) != session->req.content_len)
629 {
630 LOGE("mbtk_http_write() fail.");
631 return -1;
632 }
633
634 session->state = HTTP_SESSION_STATE_WRITE_END;
635 }
636 }
637 else
638 {
639 session->state = HTTP_SESSION_STATE_WRITE_END;
640
641 LOGI("HTTP write complete.");
642 }
643 return 0;
644}
645
646static int http_session_read_by_chunk(mbtk_http_session_t *session)
647{
648#undef BUFFER_SIZE
649#define BUFFER_SIZE 2048
650 http_chunk_code chunk_code;
651 http_chunker_t chunker;
652 char read_buf[BUFFER_SIZE + 1];
653 int read_len = 0;
654 char chunk_buf[BUFFER_SIZE + 1];
655 int chunk_len;
656 http_chunk_init(&chunker);
657 while(TRUE)
658 {
659 read_len = mbtk_http_read(session->sock_fd,read_buf,BUFFER_SIZE,3000);
660 //read_len = mbtk_http_read_line(session->sock_file,read_buf,BUFFER_SIZE);
661 if(read_len <= 0)
662 {
663 LOGE("Read fail.");
664 return -1;
665 }
666
667 chunk_code = http_chunk_parse(&chunker, read_buf, read_len, chunk_buf, &chunk_len);
668 if(chunk_code > CHUNKE_OK) // Fail.
669 {
670 LOGE("http_chunk_parse() fail[err - %d].",chunk_code);
671 return -1;
672 }
673
674 LOGD("Read chunk_len:%d",chunk_len);
675 chunk_buf[chunk_len] = '\0';
676
677 if(http_handles[session->handle_id].data_cb)
678 http_handles[session->handle_id].data_cb(session->id,
679 MBTK_HTTP_DATA_CONTENT,chunk_buf,chunk_len);
680
681 if(CHUNKE_STOP == chunk_code)
682 {
683 if(http_handles[session->handle_id].data_cb)
684 http_handles[session->handle_id].data_cb(session->id,
685 MBTK_HTTP_DATA_COMPLETE,NULL,0);
686
687 break;
688 }
689 }
690
691 LOGV("Chunk read success.");
692
693 return 0;
694}
695
696static int http_session_read_by_length(mbtk_http_session_t *session)
697{
698#undef BUFFER_SIZE
699#define BUFFER_SIZE 2048
700 char read_buf[BUFFER_SIZE + 1];
701 int read_len = 0;
702 int64 read_count = 0;
703 while(TRUE)
704 {
705 memset(read_buf,0x0,BUFFER_SIZE + 1);
706 read_len = mbtk_http_read(session->sock_fd,read_buf,BUFFER_SIZE,3000);
707 if(read_len <= 0)
708 {
709 LOGE("Read fail.");
710 return -1;
711 }
712
713 if(read_count + read_len >= session->rsp.content_length) // Read data complete.
714 {
715 if(http_handles[session->handle_id].data_cb)
716 {
717 http_handles[session->handle_id].data_cb(session->id,
718 MBTK_HTTP_DATA_CONTENT,read_buf,session->rsp.content_length - read_count);
719
720 http_handles[session->handle_id].data_cb(session->id,
721 MBTK_HTTP_DATA_COMPLETE,NULL,0);
722 }
723 break;
724 }
725
726 if(http_handles[session->handle_id].data_cb)
727 http_handles[session->handle_id].data_cb(session->id,
728 MBTK_HTTP_DATA_CONTENT,read_buf,read_len);
729
730 read_count += read_len;
731 }
732
733 return 0;
734}
735
736static int http_session_read_by_general(mbtk_http_session_t *session)
737{
738#undef BUFFER_SIZE
739#define BUFFER_SIZE 2048
740 char read_buf[BUFFER_SIZE + 1];
741 int read_len = 0;
742 while(TRUE)
743 {
744 read_len = mbtk_http_read(session->sock_fd,read_buf,BUFFER_SIZE,1000);
745 if(read_len <= 0)
746 {
747 if(read_len == -2 || read_len == 0) // Timeout or end
748 break;
749
750 LOGW("Read end[read_len - %d].",read_len);
751 //return -1;
752 break;
753 }
754
755 read_buf[read_len] = '\0';
756
757 if(http_handles[session->handle_id].data_cb)
758 http_handles[session->handle_id].data_cb(session->id,
759 MBTK_HTTP_DATA_CONTENT,read_buf,read_len);
760 }
761
762 if(http_handles[session->handle_id].data_cb)
763 http_handles[session->handle_id].data_cb(session->id,
764 MBTK_HTTP_DATA_COMPLETE,NULL,0);
765
766 return 0;
767}
768
769static int http_session_start_read(mbtk_http_session_t *session)
770{
771 LOGI("Start HTTP read.");
772 int result = 0;
773// usleep(500000);
774 session->state = HTTP_SESSION_STATE_READ_HEADER;
775 if(http_header_read(session))
776 {
777 result = -1;
778 goto read_end;
779 }
780
781 if(session->option != HTTP_OPTION_HEAD)
782 {
783 session->state = HTTP_SESSION_STATE_READ_CONTENT;
784 if(session->rsp.is_chunked)
785 {
786 if(http_session_read_by_chunk(session))
787 {
788 result = -1;
789 goto read_end;
790 }
791 }
792 else if(session->rsp.content_length > 0)
793 {
794 if(http_session_read_by_length(session))
795 {
796 result = -1;
797 goto read_end;
798 }
799 }
800 else
801 {
802 if(http_session_read_by_general(session))
803 {
804 result = -1;
805 goto read_end;
806 }
807 }
808 }
809 else
810 {
811 if(http_handles[session->handle_id].data_cb)
812 http_handles[session->handle_id].data_cb(session->id,
813 MBTK_HTTP_DATA_COMPLETE,NULL,0);
814 }
815
816read_end:
817 session->state = HTTP_SESSION_STATE_READ_END;
818
819 LOGI("HTTP request complete[result - %d].",result);
820 if(http_session_close(session))
821 {
822 return -1;
823 }
824
825#if 0
826 // Free session after HTTP request complete.
827 http_session_free(session);
828 http_handles[handle_id].session[session_id] = NULL;
829 http_handles[handle_id].session_cnt--;
830#endif
831
832 return result;
833}
834
835static bool http_session_req_check(mbtk_http_session_t *session)
836{
837 if(session == NULL || session->port == 0 ||
838 strlen(session->host) == 0)
839 {
840 LOGE("Session not set host or port.");
841 return FALSE;
842 }
843
844 if(session->option != HTTP_OPTION_HEAD &&
845 session->option != HTTP_OPTION_POST &&
846 session->option != HTTP_OPTION_GET)
847 {
848 LOGE("Only support HEAD/GET/POST");
849 return FALSE;
850 }
851
852#if 0
853 if(session->version != HTTP_VERSION_1_0 &&
854 session->version != HTTP_VERSION_1_1)
855 {
856 LOGE("Only support HTTP 1.0/1.1");
857 return FALSE;
858 }
859#endif
860
861 if(session->option == HTTP_OPTION_POST)
862 {
863 char *value = NULL;
864 value = http_header_find(session, "Content-Length");
865 if(!value)
866 {
867 LOGE("POST must set 'Content-Length'");
868 return FALSE;
869 }
870 if(session->req.content_len != atoi(value))
871 {
872 LOGE("POST 'Content-Length' error.");
873 return FALSE;
874 }
875
876 value = http_header_find(session, "Content-Type");
877 if(!value)
878 {
879 LOGE("POST must set 'Content-Type'");
880 return FALSE;
881 }
882 }
883
884 return TRUE;
885}
886
887/*************************************************************
888 Public Function Definitions
889*************************************************************/
890int mbtk_http_handle_get(bool show_rsp_header,mbtk_http_data_callback_func data_cb)
891{
892 int index = 0;
893 int i = 0;
894 for(; index < HTTP_HANDLE_MAX; index++)
895 {
896 if(http_handles[index].id < 0) // Find free handle
897 {
898 break;
899 }
900 }
901
902 if(index == HTTP_HANDLE_MAX)
903 {
904 LOGE("HTTP Handle is full.");
905 return -1;
906 }
907
908 memset(&(http_handles[index]),0x0,sizeof(mbtk_http_handle_t));
909 http_handles[index].id = index;
910 http_handles[index].show_rsp_header = show_rsp_header;
911 http_handles[index].data_cb = data_cb;
912 http_handles[index].session_cnt = 0;
913 for(i = 0; i < HTTP_SESSION_MAX; i++)
914 {
915 http_handles[index].session[i] = NULL;
916 }
917
918 if(mbtk_http_init())
919 {
920 LOGE("mbtk_http_init() fail.");
921 return -1;
922 }
923
924 return http_handles[index].id;
925}
926
927int mbtk_http_handle_free(int handle_id)
928{
929 int i = 0;
930 if(!http_handle_check(handle_id))
931 {
932 LOGE("Handle error.");
933 return -1;
934 }
935
936 http_handles[handle_id].id = -1;
937 http_handles[handle_id].data_cb = NULL;
938 if(http_handles[handle_id].session_cnt > 0)
939 {
940 for(i = 0; i < HTTP_SESSION_MAX; i++)
941 {
942 if(http_handles[handle_id].session[i] != NULL)
943 {
944 if(http_handles[handle_id].session[i]->state != HTTP_SESSION_STATE_NON)
945 {
946 if(http_session_close(http_handles[handle_id].session[i]))
947 {
948 return -1;
949 }
950 }
951
952 http_session_free(http_handles[handle_id].session[i]);
953 http_handles[handle_id].session[i] = NULL;
954 }
955 }
956
957 http_handles[handle_id].session_cnt = 0;
958 }
959
960 if(mbtk_http_deinit())
961 {
962 LOGE("mbtk_http_deinit() fail.");
963 return -1;
964 }
965
966 return 0;
967}
968
969int mbtk_http_session_create(int handle_id, mbtk_http_option_enum option,
970 mbtk_http_version_enum version)
971{
972 int handle_index = 0;
973 int session_index = 0;
974 if(!http_handle_check(handle_id))
975 {
976 LOGE("Handle error.");
977 return -1;
978 }
979
980 for(; handle_index < HTTP_HANDLE_MAX; handle_index++)
981 {
982 if(http_handles[handle_index].id == handle_id) // Find handle
983 {
984 break;
985 }
986 }
987
988 if(handle_index == HTTP_HANDLE_MAX)
989 {
990 LOGE("No found handle[handle - %d].",handle_id);
991 return -1;
992 }
993
994 if(http_handles[handle_index].session_cnt >= HTTP_SESSION_MAX)
995 {
996 LOGE("Session is full.");
997 return -1;
998 }
999
1000 for(; session_index < HTTP_SESSION_MAX; session_index++)
1001 {
1002 if(http_handles[handle_index].session[session_index] == NULL) // Find first NULL session
1003 {
1004 break;
1005 }
1006 }
1007
1008 if(session_index == HTTP_SESSION_MAX)
1009 {
1010 LOGE("Session is full.");
1011 return -1;
1012 }
1013
1014 mbtk_http_session_t* session = (mbtk_http_session_t*)malloc(sizeof(mbtk_http_session_t));
1015 if(session == NULL)
1016 {
1017 LOGE("malloc() fail.");
1018 return -1;
1019 }
1020 memset(session,0x0,sizeof(mbtk_http_session_t));
1021 session->sock_fd = -1;
1022 session->sock_file = NULL;
1023 session->handle_id = handle_id;
1024 session->id = session_index;
1025 session->state = HTTP_SESSION_STATE_NON;
1026 session->is_ssl = FALSE;
1027 session->version = version;
1028 session->option = option;
1029 session->req.content_len = 0;
1030 session->req.content_len_send = 0;
1031 session->rsp.is_chunked = FALSE;
1032 session->rsp.content_length = 0;
1033 session->rsp.header_cnt = 0;
1034 http_handles[handle_index].session[session_index] = session;
1035 http_handles[handle_index].session_cnt++;
1036
1037 return session->id;
1038}
1039
1040int mbtk_http_session_option_reset(int handle_id, int session_id, mbtk_http_option_enum option)
1041{
1042 if(!http_session_check(handle_id,session_id))
1043 {
1044 LOGE("Session error.");
1045 return -1;
1046 }
1047
1048 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1049 if(session->state != HTTP_SESSION_STATE_NON)
1050 {
1051 LOGE("Session state error.[%d]",session->state);
1052 return -1;
1053 }
1054
1055 session->option = option;
1056 return 0;
1057}
1058
1059int mbtk_http_session_free(int handle_id,int session_id)
1060{
1061 if(!http_session_check(handle_id,session_id))
1062 {
1063 LOGE("Session error.");
1064 return -1;
1065 }
1066
1067 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1068 if(session->state != HTTP_SESSION_STATE_NON)
1069 {
1070 if(http_session_close(session))
1071 {
1072 return -1;
1073 }
1074 }
1075
1076 http_session_free(session);
1077 http_handles[handle_id].session[session_id] = NULL;
1078 http_handles[handle_id].session_cnt--;
1079 return 0;
1080}
1081
1082int mbtk_http_session_url_set(int handle_id,int session_id,void *url)
1083{
1084 if(!http_session_check(handle_id,session_id))
1085 {
1086 LOGE("Session error.");
1087 return -1;
1088 }
1089
1090 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1091 if(session->state == HTTP_SESSION_STATE_NON)
1092 return http_url_parse(url, session->host,session->uri,&(session->port),&(session->is_ssl));
1093 else
1094 {
1095 LOGE("Currenr session is process[state - %d].",session->state);
1096 return -1;
1097 }
1098}
1099
1100int mbtk_http_session_head_add(int handle_id,int session_id,
1101 char *name, char *value)
1102{
1103 if(!http_session_check(handle_id,session_id))
1104 {
1105 LOGE("Session error.");
1106 return -1;
1107 }
1108
1109 if(http_str_empty(name) || http_str_empty(value))
1110 {
1111 LOGE("Param error.");
1112 return -1;
1113 }
1114
1115 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1116 if(session->state == HTTP_SESSION_STATE_NON)
1117 {
1118 int result = http_session_req_head_add(session,TRUE,name,value);
1119 if(!result && !strncasecmp(name,"Content-Length",14))
1120 {
1121 session->req.content_len = atoi(value);
1122 }
1123 return result;
1124 }
1125 else
1126 {
1127 LOGE("Currenr session is process[state - %d].",session->state);
1128 return -1;
1129 }
1130}
1131
1132int mbtk_http_session_content_set(int handle_id,int session_id,
1133 char *content,uint32 content_len)
1134{
1135 if(!http_session_check(handle_id,session_id))
1136 {
1137 LOGE("Session error.");
1138 return -1;
1139 }
1140
1141 if(content_len <= 0 || content_len > HTTP_CONTENT_LEN_MAX)
1142 {
1143 LOGE("Content lenght error[%d].",content_len);
1144 return -1;
1145 }
1146
1147 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1148 if(session->state == HTTP_SESSION_STATE_NON)
1149 {
1150 if(session->option != HTTP_OPTION_POST)
1151 {
1152 LOGE("Content only for post.");
1153 return -1;
1154 }
1155
1156 if(session->req.content)
1157 {
1158 free(session->req.content);
1159 session->req.content_len = 0;
1160 }
1161
1162 session->req.content = (char*)malloc(content_len);
1163 if(session->req.content == NULL)
1164 {
1165 LOGE("malloc() fail.");
1166 return -1;
1167 }
1168
1169 char *content_type = NULL;
1170 if(strlen(content) == content_len) //
1171 {
1172 content_type = "text/plain";
1173 }
1174 else
1175 {
1176 content_type = "application/octet-stream";
1177 }
1178
1179 if(http_session_req_head_add(session, FALSE, "Content-Type", content_type))
1180 {
1181 LOGE("Set 'Content-Type' fail.");
1182 return -1;
1183 }
1184
1185 memcpy(session->req.content,content,content_len);
1186 session->req.content_len = content_len;
1187
1188 char len_str[20] = {0};
1189 snprintf(len_str,20,"%d",content_len);
1190 if(http_session_req_head_add(session,FALSE,"Content-Length",len_str))
1191 {
1192 LOGE("Set 'Content-Length' fail.");
1193 return -1;
1194 }
1195
1196
1197 return 0;
1198 }
1199 else
1200 {
1201 LOGE("Currenr session is process[state - %d].",session->state);
1202 return -1;
1203 }
1204}
1205
1206int mbtk_http_session_start(int handle_id,int session_id)
1207{
1208 if(!http_session_check(handle_id,session_id))
1209 {
1210 LOGE("Session error.");
1211 return -1;
1212 }
1213
1214 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1215 if(session->state == HTTP_SESSION_STATE_NON)
1216 {
1217 if(!http_session_req_check(session))
1218 {
1219 LOGE("http_session_req_check() fail.");
1220 return -1;
1221 }
1222
1223 // Must set "Connection" for post.
1224 if(session->option == HTTP_OPTION_POST)
1225 {
1226 if(http_session_req_head_add(session,FALSE,"Connection","KeepAlive"))
1227 {
1228 LOGE("Set 'Content-Length' fail.");
1229 return -1;
1230 }
1231 }
1232
1233 LOGI("HTTP request start.");
1234 LOGI("host:%s, port:%d, uri:%s",session->host,session->port,session->uri);
1235 LOGI("is_ssl:%d, version:%d, option:%d, content_len:%d",session->is_ssl,
1236 session->version,session->option,session->req.content_len);
1237
1238 int sock_fd = mbtk_http_open(session->is_ssl,TRUE,session->host,session->port);
1239 if(sock_fd < 0)
1240 {
1241 return -1;
1242 }
1243 session->sock_fd = sock_fd;
1244// int fd = mbtk_sock_fd_get(sock_fd);
1245// if(fd < 0) {
1246// LOGE("mbtk_sock_fd_get() fail.");
1247// return -1;
1248// }
1249 // session->sock_file = fdopen(sock_fd,"r");
1250 session->state = HTTP_SESSION_STATE_CONN;
1251
1252// if(!session->sock_file) {
1253// LOGE("fdopen() fail.");
1254// return -1;
1255// }
1256
1257 LOGI("HTTP connected.");
1258
1259 if(http_session_start_write(session))
1260 {
1261 return -1;
1262 }
1263
1264 if(session->state == HTTP_SESSION_STATE_WRITE_END)
1265 {
1266 if(http_session_start_read(session))
1267 {
1268 return -1;
1269 }
1270 }
1271 else
1272 {
1273 LOGI("Waitting post content data...");
1274 }
1275
1276 return 0;
1277 }
1278 else
1279 {
1280 LOGE("Currenr session is process[state - %d].",session->state);
1281 return -1;
1282 }
1283}
1284
1285int mbtk_http_session_content_send(int handle_id,int session_id,
1286 char *data,int data_len)
1287{
1288 if(!http_session_check(handle_id,session_id))
1289 {
1290 LOGE("Session error.");
1291 return -1;
1292 }
1293
1294 if(data_len <= 0 || data_len > HTTP_CONTENT_LEN_MAX)
1295 {
1296 LOGE("Content lenght error[%d].",data_len);
1297 return -1;
1298 }
1299
1300 LOGV("Post send:%d - %s",data_len,data);
1301
1302 mbtk_http_session_t *session = http_handles[handle_id].session[session_id];
1303 if(session->state == HTTP_SESSION_STATE_WRITE_CONTENT)
1304 {
1305 if(session->option != HTTP_OPTION_POST)
1306 {
1307 LOGE("Content only for post.");
1308 return -1;
1309 }
1310
1311 if(session->req.content || session->req.content_len <= 0)
1312 {
1313 LOGE("This post not spit package.");
1314 return -1;
1315 }
1316
1317 // Discard excess data.
1318 if(session->req.content_len_send + data_len > session->req.content_len)
1319 data_len = session->req.content_len - session->req.content_len_send;
1320
1321 if(data_len != mbtk_http_write(session->sock_fd,data,data_len))
1322 {
1323 return -1;
1324 }
1325
1326 session->req.content_len_send += data_len;
1327
1328 LOGI("HTTP post data send: %d / %d",session->req.content_len_send,
1329 session->req.content_len);
1330
1331 // Post data send complete.
1332 if(session->req.content_len_send >= session->req.content_len)
1333 {
1334 session->state = HTTP_SESSION_STATE_WRITE_END;
1335
1336 LOGI("HTTP write complete.");
1337 if(http_session_start_read(session))
1338 {
1339 return -1;
1340 }
1341 }
1342
1343 return 0;
1344 }
1345 else
1346 {
1347 LOGE("Currenr session state error[%d].",session->state);
1348 return -1;
1349 }
1350}
1351
1352const mbtk_http_session_t* mbtk_http_session_get(int handle_id,int session_id)
1353{
1354 if(!http_session_check(handle_id,session_id))
1355 {
1356 LOGE("Session error.");
1357 return NULL;
1358 }
1359
1360 return http_handles[handle_id].session[session_id];
1361}