| #include <string.h> | 
 |  | 
 | #include "mbtk_http_chunks.h" | 
 | #include "mbtk_http_base.h" | 
 |  | 
 | static bool http_isxdigit(char digit) | 
 | { | 
 |     return (digit >= 0x30 && digit <= 0x39) /* 0-9 */ | 
 |             || (digit >= 0x41 && digit <= 0x46) /* A-F */ | 
 |             || (digit >= 0x61 && digit <= 0x66); /* a-f */ | 
 | } | 
 |  | 
 | void http_chunk_init(http_chunker_t *chunker) | 
 | { | 
 |     chunker->hexindex = 0;      /* start at 0 */ | 
 |     chunker->dataleft = 0;      /* no data left yet! */ | 
 |     chunker->state = CHUNK_HEX; /* we get hex first! */ | 
 | } | 
 |  | 
 | http_chunk_code http_chunk_parse(http_chunker_t *chunker, char *src, int src_len, | 
 |             char *dest,int *dest_len) | 
 | { | 
 |     int piece; | 
 |     char *datap = src; | 
 |     int length = src_len; | 
 |  | 
 |     *dest_len = 0; | 
 |  | 
 |     while(length > 0) | 
 |     { | 
 |         switch(chunker->state) | 
 |         { | 
 |             case CHUNK_HEX: | 
 |                 if(http_isxdigit(*datap)) | 
 |                 { | 
 |                     if(chunker->hexindex < MAXNUM_SIZE) | 
 |                     { | 
 |                         chunker->hexbuffer[chunker->hexindex] = *datap; | 
 |                         datap++; | 
 |                         length--; | 
 |                         chunker->hexindex++; | 
 |                     } | 
 |                     else | 
 |                     { | 
 |                         return CHUNKE_TOO_LONG_HEX; /* longer hex than we support */ | 
 |                     } | 
 |                 } | 
 |                 else // Not hex char. ('\r') | 
 |                 { | 
 |                     if(0 == chunker->hexindex) | 
 |                         return CHUNKE_ILLEGAL_HEX; | 
 |  | 
 |                     chunker->hexbuffer[chunker->hexindex] = '\0'; | 
 |                     sscanf(chunker->hexbuffer,"%x",&chunker->datasize); | 
 |  | 
 |                     LOGD("Chunk len:%s -> %d",chunker->hexbuffer,chunker->datasize); | 
 |  | 
 |                     chunker->state = CHUNK_LF; /* now wait for the CRLF */ | 
 |                 } | 
 |                 break; | 
 |             case CHUNK_LF: | 
 |                 if(*datap == 0x0a) // '\n' | 
 |                 { | 
 |                     if(0 == chunker->datasize) { // Chunk lenght is '0' (Is last chunk) | 
 |                         chunker->state = CHUNK_TRAILER; | 
 |                     } else { | 
 |                         chunker->state = CHUNK_DATA; | 
 |                     } | 
 |                 } | 
 |  | 
 |                 datap++; | 
 |                 length--; | 
 |                 break; | 
 |             case CHUNK_DATA: | 
 |                 /* We expect 'datasize' of data. We have 'length' right now, it can be | 
 |                    more or less than 'datasize'. Get the smallest piece. | 
 |                 */ | 
 |                 piece = (chunker->datasize >= length)?length:chunker->datasize; | 
 |  | 
 |                 memcpy(dest + *dest_len,datap,piece); | 
 |                 *dest_len += piece; | 
 |  | 
 |                 chunker->datasize -= piece; /* decrease amount left to expect */ | 
 |                 datap += piece;    /* move read pointer forward */ | 
 |                 length -= piece;   /* decrease space left in this round */ | 
 |  | 
 |                 if(0 == chunker->datasize) // Next chunk | 
 |                     chunker->state = CHUNK_POSTLF; | 
 |                 break; | 
 |             case CHUNK_POSTLF: | 
 |                 if(*datap == 0x0a) | 
 |                 { | 
 |                     http_chunk_init(chunker); | 
 |                 } | 
 |                 else if(*datap != 0x0d) | 
 |                     return CHUNKE_BAD_CHUNK; | 
 |                 datap++; | 
 |                 length--; | 
 |                 break; | 
 |             case CHUNK_TRAILER: | 
 |                 if((*datap != 0x0d) && (*datap != 0x0a)) | 
 |                 { | 
 |                     return CHUNKE_BAD_CHUNK; | 
 |                 } | 
 |                 if(*datap == 0x0d) | 
 |                 { | 
 |                     /* skip if CR */ | 
 |                     datap++; | 
 |                     length--; | 
 |                 } | 
 |                 chunker->state = CHUNK_STOP; | 
 |                 break; | 
 |             case CHUNK_STOP: // Complete | 
 |                 if(*datap == 0x0a) | 
 |                 { | 
 |                     length--; | 
 |  | 
 |                     /* Record the length of any data left in the end of the buffer | 
 |                        even if there's no more chunks to read */ | 
 |                     chunker->dataleft = length; | 
 |  | 
 |                     return CHUNKE_STOP; /* return stop */ | 
 |                 } | 
 |                 else | 
 |                     return CHUNKE_BAD_CHUNK; | 
 |         } | 
 |     } | 
 |     return CHUNKE_OK; | 
 | } | 
 |  | 
 |  |