blob: 899e0c755e382224dcd4c032979d3e7e9aacc2d1 [file] [log] [blame]
#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;
}