Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 340 → Rev 341

/pkgnet/unchtest.c
78,6 → 78,7
size_t bytesprocessed = 0;
size_t file_decoded_len = 0;
int maxchunksz;
struct unchunk_state unchstate = {0};
 
/* segment file into chunks of random size */
maxchunksz = (rand() % 256) + 8;
96,7 → 97,7
memcpy(buffer, file_chunked + bytesprocessed, bytes);
 
/* decode the chunked version reading random amounts of data and build a decoded version */
decodedbytes = unchunk(buffer, bytes);
decodedbytes = unchunk(buffer, bytes, &unchstate);
printf(" -> decoded into %4d raw bytes\r\n", decodedbytes);
memcpy(file_decoded + file_decoded_len, buffer, decodedbytes);
file_decoded_len += decodedbytes;
/pkgnet/unchunk.c
10,22 → 10,22
 
#include "unchunk.h"
 
/* transforms a http CHUNKED stream into actual data, returns the amount of raw data to read */
int unchunk(unsigned char *buff, int bufflen) {
static long bytesleft; /* how many bytes are expected yet in the ongoing chunk */
static char partial_hdr[16]; /* a small buffer for storing partial chunk headers, if these are transmitted in separate parts */
 
/* transforms a http CHUNKED stream into actual data, returns the amount of
* raw data to read or -1 on error. st MUST be zeroed before first call. */
int unchunk(unsigned char *buff, int bufflen, struct unchunk_state *st) {
int hdrstart, hdrend;
 
/* if chunk header was being in progress, try to decode it now */
if (bytesleft == -1) {
int partial_hdr_len = strlen(partial_hdr);
if (st->bytesleft == -1) {
int partial_hdr_len = strlen(st->partial_hdr);
/* locate header terminator, if available */
for (hdrend = 0; (hdrend < bufflen) && (buff[hdrend] != '\n'); hdrend++);
if (partial_hdr_len + hdrend > 15) return(-1); /* error: chunk header too long */
 
/* copy header to buffer */
memcpy(partial_hdr + partial_hdr_len, buff, hdrend);
partial_hdr[partial_hdr_len + hdrend] = 0;
memcpy(st->partial_hdr + partial_hdr_len, buff, hdrend);
st->partial_hdr[partial_hdr_len + hdrend] = 0;
 
/* quit if header still no complete */
if (hdrend >= bufflen) return(0);
33,13 → 33,13
/* good, got whole header */
bufflen -= hdrend + 1;
memmove(buff, buff + hdrend + 1, bufflen);
bytesleft = strtol(partial_hdr, NULL, 16);
st->bytesleft = strtol(st->partial_hdr, NULL, 16);
}
 
AGAIN:
 
if (bufflen <= bytesleft) { /* bufflen <= bytesleft */
bytesleft -= bufflen;
if (bufflen <= st->bytesleft) {
st->bytesleft -= bufflen;
return(bufflen);
}
 
46,7 → 46,7
/* else bufflen > bytesleft */
 
/* skip trailing \r\n after chunk */
for (hdrstart = bytesleft; hdrstart < bufflen; hdrstart++) if ((buff[hdrstart] != '\r') && (buff[hdrstart] != '\n')) break;
for (hdrstart = st->bytesleft; hdrstart < bufflen; hdrstart++) if ((buff[hdrstart] != '\r') && (buff[hdrstart] != '\n')) break;
/* skip chunk size (look for its \n terminator) */
for (hdrend = hdrstart; (hdrend < bufflen) && (buff[hdrend] != '\n'); hdrend++);
 
55,18 → 55,18
/* read the header length */
newchunklen = strtol((char *)buff + hdrstart, NULL, 16);
/* move data over header to get a contiguous block of data */
memmove(buff + bytesleft, buff + hdrend + 1, bufflen - (hdrend + 1));
bufflen -= (hdrend + 1 - bytesleft);
memmove(buff + st->bytesleft, buff + hdrend + 1, bufflen - (hdrend + 1));
bufflen -= (hdrend + 1 - st->bytesleft);
/* update bytesleft */
bytesleft += newchunklen;
st->bytesleft += newchunklen;
/* loop again */
goto AGAIN;
} else { /* partial header */
if ((bufflen - bytesleft) > 15) return(-1); /* error: chunk header appears to be longer than 15 characters */
memset(partial_hdr, 0, sizeof(partial_hdr));
memcpy(partial_hdr, buff + bytesleft, bufflen - bytesleft);
bufflen -= (bufflen - bytesleft);
bytesleft = -1; /* "header in progress" */
if ((bufflen - st->bytesleft) > 15) return(-1); /* error: chunk header appears to be longer than 15 characters */
memset(st->partial_hdr, 0, sizeof(st->partial_hdr));
memcpy(st->partial_hdr, buff + st->bytesleft, bufflen - st->bytesleft);
bufflen -= (bufflen - st->bytesleft);
st->bytesleft = -1; /* "header in progress" */
return(bufflen);
}
}
/pkgnet/unchunk.h
8,7 → 8,13
#ifndef UNCHUNK_H
#define UNCHUNK_H
 
/* transforms a http CHUNKED stream into actual data, returns the amount of raw data to read */
int unchunk(unsigned char *buff, int bufflen);
struct unchunk_state {
char partial_hdr[16]; /* a small buffer for storing partial chunk headers, if these are transmitted in separate parts */
long bytesleft; /* how many bytes are expected yet in the ongoing chunk */
};
 
/* transforms a http CHUNKED stream into actual data, returns the amount of
* raw data to read or -1 on error. st MUST be zeroed before first call. */
int unchunk(unsigned char *buff, int bufflen, struct unchunk_state *st);
 
#endif