blob: 899e0c755e382224dcd4c032979d3e7e9aacc2d1 [file] [log] [blame]
liubin281ac462023-07-19 14:22:54 +08001#include <string.h>
2
3#include "mbtk_http_chunks.h"
4#include "mbtk_http_base.h"
5
6static bool http_isxdigit(char digit)
7{
8 return (digit >= 0x30 && digit <= 0x39) /* 0-9 */
9 || (digit >= 0x41 && digit <= 0x46) /* A-F */
10 || (digit >= 0x61 && digit <= 0x66); /* a-f */
11}
12
13void http_chunk_init(http_chunker_t *chunker)
14{
15 chunker->hexindex = 0; /* start at 0 */
16 chunker->dataleft = 0; /* no data left yet! */
17 chunker->state = CHUNK_HEX; /* we get hex first! */
18}
19
20http_chunk_code http_chunk_parse(http_chunker_t *chunker, char *src, int src_len,
21 char *dest,int *dest_len)
22{
23 int piece;
24 char *datap = src;
25 int length = src_len;
26
27 *dest_len = 0;
28
29 while(length > 0)
30 {
31 switch(chunker->state)
32 {
33 case CHUNK_HEX:
34 if(http_isxdigit(*datap))
35 {
36 if(chunker->hexindex < MAXNUM_SIZE)
37 {
38 chunker->hexbuffer[chunker->hexindex] = *datap;
39 datap++;
40 length--;
41 chunker->hexindex++;
42 }
43 else
44 {
45 return CHUNKE_TOO_LONG_HEX; /* longer hex than we support */
46 }
47 }
48 else // Not hex char. ('\r')
49 {
50 if(0 == chunker->hexindex)
51 return CHUNKE_ILLEGAL_HEX;
52
53 chunker->hexbuffer[chunker->hexindex] = '\0';
54 sscanf(chunker->hexbuffer,"%x",&chunker->datasize);
55
56 LOGD("Chunk len:%s -> %d",chunker->hexbuffer,chunker->datasize);
57
58 chunker->state = CHUNK_LF; /* now wait for the CRLF */
59 }
60 break;
61 case CHUNK_LF:
62 if(*datap == 0x0a) // '\n'
63 {
64 if(0 == chunker->datasize) { // Chunk lenght is '0' (Is last chunk)
65 chunker->state = CHUNK_TRAILER;
66 } else {
67 chunker->state = CHUNK_DATA;
68 }
69 }
70
71 datap++;
72 length--;
73 break;
74 case CHUNK_DATA:
75 /* We expect 'datasize' of data. We have 'length' right now, it can be
76 more or less than 'datasize'. Get the smallest piece.
77 */
78 piece = (chunker->datasize >= length)?length:chunker->datasize;
79
80 memcpy(dest + *dest_len,datap,piece);
81 *dest_len += piece;
82
83 chunker->datasize -= piece; /* decrease amount left to expect */
84 datap += piece; /* move read pointer forward */
85 length -= piece; /* decrease space left in this round */
86
87 if(0 == chunker->datasize) // Next chunk
88 chunker->state = CHUNK_POSTLF;
89 break;
90 case CHUNK_POSTLF:
91 if(*datap == 0x0a)
92 {
93 http_chunk_init(chunker);
94 }
95 else if(*datap != 0x0d)
96 return CHUNKE_BAD_CHUNK;
97 datap++;
98 length--;
99 break;
100 case CHUNK_TRAILER:
101 if((*datap != 0x0d) && (*datap != 0x0a))
102 {
103 return CHUNKE_BAD_CHUNK;
104 }
105 if(*datap == 0x0d)
106 {
107 /* skip if CR */
108 datap++;
109 length--;
110 }
111 chunker->state = CHUNK_STOP;
112 break;
113 case CHUNK_STOP: // Complete
114 if(*datap == 0x0a)
115 {
116 length--;
117
118 /* Record the length of any data left in the end of the buffer
119 even if there's no more chunks to read */
120 chunker->dataleft = length;
121
122 return CHUNKE_STOP; /* return stop */
123 }
124 else
125 return CHUNKE_BAD_CHUNK;
126 }
127 }
128 return CHUNKE_OK;
129}
130
131