Commit 4cce117d authored by Stewart Brodie's avatar Stewart Brodie
Browse files

AcornHTTP version 0.81

On the fly decompression now works.  Both deflated and gzipped files
are handled and will, if the server asks us to, be decompressed on the
fly during download.  (Chunked compressed downloads are untested)
parent 720811b0
......@@ -52,11 +52,18 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
if (ses->zstream.avail_in) {
/* Something left over from last time */
int ret = inflate(&ses->zstream, Z_NO_FLUSH);
int ret;
#ifdef TRACE
protocol_debug("inflate: Next byte in stream is %02x\n", *ses->zstream.next_in);
#endif
ret = inflate(&ses->zstream, Z_NO_FLUSH);
if (ret == Z_STREAM_END) {
inflateEnd(&ses->zstream);
ses->compression = compression_NONE;
ses->compstate = compress_FINISHED;
/*ses->compression = compression_NONE;*/
ses->compstate = compress_READ_GZIP_TRAILER;
ses->zstream.next_in = ses->compbuf;
}
else if (ret != Z_OK) {
#ifdef TRACE
......@@ -68,7 +75,23 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
}
while (ses->zstream.avail_in == 0 && ses->zstream.avail_out > 0 && toread > 0 && ses->compstate == compress_INFLATE) {
int ret;
dataread = ses->op->s_recv(ses->sd, ses->compbuf, toread > ses->compbufsize ? ses->compbufsize : toread, 0);
int s;
s = toread > ses->compbufsize ? ses->compbufsize : toread;
if (s == 0) {
#ifdef TRACE
protocol_debug("No buffer space left!\n");
#endif
errno = EWOULDBLOCK;
dataread = -1;
if (toread < orig_toread) {
*rawread = orig_toread - toread;
return (char *) ses->zstream.next_out - buffer;
}
}
else {
dataread = ses->op->s_recv(ses->sd, ses->compbuf, s, 0);
}
if (dataread > 0) {
toread -= dataread;
ses->zstream.next_in = ses->compbuf;
......@@ -76,8 +99,9 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
ret = inflate(&ses->zstream, Z_NO_FLUSH);
if (ret == Z_STREAM_END) {
inflateEnd(&ses->zstream);
ses->compression = compression_NONE;
ses->compstate = compress_FINISHED;
/*ses->compression = compression_NONE;*/
ses->compstate = compress_READ_GZIP_TRAILER;
ses->zstream.next_in = ses->compbuf;
}
else if (ret != Z_OK) {
#ifdef TRACE
......@@ -100,6 +124,28 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
}
}
*rawread = orig_toread - toread;
#ifdef TRACE
protocol_debug("decompress: %d bytes read; return value %d\n", *rawread, (char *) ses->zstream.next_out - buffer);
#endif
if ((char *)ses->zstream.next_out == buffer && *rawread) {
if (ses->compstate == compress_INFLATE) {
#ifdef TRACE
protocol_debug("decompress: still inflating, therefore returning EWOULDBLOCK\n");
#endif
errno = EWOULDBLOCK;
return -1;
}
if (ses->compstate == compress_READ_GZIP_TRAILER) {
#ifdef TRACE
protocol_debug("decompress: still waiting for 8 bytes trailer = therefore returning EWOULDBLOCK\n");
#endif
errno = EWOULDBLOCK;
return -1;
}
#ifdef TRACE
protocol_debug("decompress: inflation has completed - therefore returning zero\n");
#endif
}
return (char *) ses->zstream.next_out - buffer;
case compress_READ_GZIP_HEADER:
......@@ -120,6 +166,7 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
toread -= dataread;
ses->zstream.avail_in += dataread;
ses->zstream.next_in += dataread;
if (ses->zstream.avail_in < 10) {
*rawread = orig_toread - toread;
errno = EWOULDBLOCK;
......@@ -127,8 +174,11 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
}
if (ses->compbuf[0] != 0x1F || ses->compbuf[1] != 0x8B ||
ses->compbuf[2] != 8) {
ses->compbuf[2] != 8 || (ses->compbuf[3] & 0xE0) != 0) {
*rawread = orig_toread - toread;
#ifdef TRACE
protocol_debug("decompress: compbuf wrong (%02x,%02x,%02x,%02x)\n", ses->compbuf[0], ses->compbuf[1], ses->compbuf[2],ses->compbuf[3]);
#endif
return 0;
}
......@@ -136,6 +186,11 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
ses->compstate = compress_READ_GZIP_EXTRA;
ses->zstream.next_in = ses->compbuf;
ses->zstream.avail_in = 0;
if (toread == 0) {
*rawread = orig_toread - toread;
errno = EWOULDBLOCK;
return -1;
}
/* Fall through */
case compress_READ_GZIP_EXTRA:
......@@ -144,36 +199,61 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
#endif
if (ses->compflags & 0x04) {
int s;
if (ses->zstream.avail_in < 2) {
dataread = ses->op->s_recv(ses->sd, ses->zstream.next_in, toread > 2 - ses->zstream.avail_in ? 2 - ses->zstream.avail_in : toread, 0);
if (toread == 0) {
dataread = -1;
errno = EWOULDBLOCK;
}
else {
dataread = ses->op->s_recv(ses->sd, ses->zstream.next_in, toread > 2 - ses->zstream.avail_in ? 2 - ses->zstream.avail_in : toread, 0);
}
if (dataread <= 0) {
*rawread = orig_toread - toread;
return dataread;
}
toread -= dataread;
ses->zstream.avail_in += dataread;
ses->zstream.next_in += dataread;
if (ses->zstream.avail_in < 2) {
*rawread = orig_toread - toread;
errno = EWOULDBLOCK;
return -1;
}
ses->zstream.avail_out = ses->compbuf[0] + 256 * ses->compbuf[1];
ses->zstream.avail_in = ses->compbuf[0] + 256 * ses->compbuf[1];
#ifdef TRACE
protocol_debug("%d bytes of gzip extra data to discard\n", ses->zstream.avail_in);
#endif
}
}
ses->compstate = compress_READING_GZIP_EXTRA;
/* Fall through */
case compress_READING_GZIP_EXTRA:
#ifdef TRACE
protocol_debug("decompress: READING_GZIP_EXTRA\n");
#endif
if (ses->compflags & 0x04) {
int s;
suck_more:
s = ses->compbufsize > ses->zstream.avail_out ? ses->compbufsize : ses->zstream.avail_out;
s = ses->compbufsize > ses->zstream.avail_in ? ses->zstream.avail_in : ses->compbufsize;
s = toread > s ? s : toread;
dataread = ses->op->s_recv(ses->sd, ses->compbuf, s, 0);
toread -= dataread;
if (s == 0) {
errno = EWOULDBLOCK;
dataread = -1;
}
else {
dataread = ses->op->s_recv(ses->sd, ses->compbuf, s, 0);
}
if (dataread <= 0) {
*rawread = orig_toread - toread;
return dataread;
}
ses->zstream.avail_out -= dataread;
if (ses->zstream.avail_out > 0)
toread -= dataread;
ses->zstream.avail_in -= dataread;
if (ses->zstream.avail_in > 0)
goto suck_more;
}
}
ses->compstate = compress_READ_GZIP_NAME;
ses->zstream.next_in = ses->compbuf;
......@@ -186,8 +266,17 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
#endif
if (ses->compflags & 0x08) {
int s;
suck_more_fname:
dataread = ses->op->s_recv(ses->sd, ses->compbuf, toread > ses->compbufsize ? ses->compbufsize : toread, 0);
s = toread > ses->compbufsize ? ses->compbufsize : toread;
if (s == 0) {
errno = EWOULDBLOCK;
dataread = -1;
}
else {
dataread = ses->op->s_recv(ses->sd, ses->compbuf, s, 0);
}
if (dataread <= 0) {
*rawread = orig_toread - toread;
return dataread;
......@@ -203,8 +292,11 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
goto suck_more_fname;
finished_fname:
/* Don't forget to skip over the '\0' */
ses->zstream.next_in++;
ses->zstream.avail_in--;
}
finished_fname:
ses->compstate = compress_READ_GZIP_COMMENT;
/* Fall through */
......@@ -214,13 +306,21 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
#endif
if (ses->compflags & 0x10) {
int s;
suck_more_comment:
for ( ; ses->zstream.avail_in;
ses->zstream.next_in++,
ses->zstream.avail_in--) {
if (*ses->zstream.next_in == 0) goto finished_comment;
}
dataread = ses->op->s_recv(ses->sd, ses->compbuf, toread > ses->compbufsize - 2 ? ses->compbufsize - 2 : toread, 0); /* Leave room for CRC... */
s = toread > ses->compbufsize - 2 ? ses->compbufsize - 2 : toread;
if (s == 0) {
errno = EWOULDBLOCK;
dataread = -1;
}
else {
dataread = ses->op->s_recv(ses->sd, ses->compbuf, s, 0); /* Leave room for CRC... */
}
if (dataread <= 0) {
*rawread = orig_toread - toread;
return dataread;
......@@ -230,8 +330,11 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
ses->zstream.avail_in = dataread;
goto suck_more_comment;
finished_comment:
/* Don't forget to skip over the '\0' */
ses->zstream.next_in++;
ses->zstream.avail_in--;
}
finished_comment:
ses->compstate = compress_READ_GZIP_HCRC;
/* Fall through */
......@@ -242,7 +345,15 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
if (ses->compflags & 0x02) {
if (ses->zstream.avail_in < 2) {
dataread = ses->op->s_recv(ses->sd, ses->zstream.next_in, toread > 2 - ses->zstream.avail_in ? 2 - ses->zstream.avail_in : toread, 0);
int s;
s = toread > 2 - ses->zstream.avail_in ? 2 - ses->zstream.avail_in : toread;
if (s == 0) {
errno = EWOULDBLOCK;
dataread = -1;
}
else {
dataread = ses->op->s_recv(ses->sd, ses->zstream.next_in, s, 0);
}
if (dataread <= 0) {
*rawread = orig_toread - toread;
return dataread;
......@@ -257,14 +368,57 @@ int decompress(Session *ses, char *buffer, int bufsize, int toread, int *rawread
return -1;
}
}
else {
ses->zstream.next_in += 2;
}
ses->zstream.avail_in -= 2;
}
ses->compstate = compress_INFLATE;
break;
case compress_READ_GZIP_TRAILER:
#ifdef TRACE
protocol_debug("decompress: READ_GZIP_TRAILER (avail_in = %d, orig_toread = %d)\n", ses->zstream.avail_in, orig_toread);
#endif
if (ses->compression != compression_GZIP) {
*rawread = orig_toread - toread;
ses->compstate = compress_FINISHED;
return 0;
}
else if (ses->zstream.avail_in < 8) {
int s;
s = toread > 8 - ses->zstream.avail_in ? 8 - ses->zstream.avail_in : toread;
if (s == 0) {
errno = EWOULDBLOCK;
dataread = -1;
}
else {
dataread = ses->op->s_recv(ses->sd, ses->compbuf, s, 0);
}
if (dataread <= 0) {
*rawread = orig_toread - toread;
return dataread;
}
toread -= dataread;
ses->zstream.avail_in += dataread;
if (ses->zstream.avail_in < 8) {
*rawread = orig_toread - toread;
errno = EWOULDBLOCK;
return -1;
}
}
ses->zstream.avail_in -= 8;
ses->compstate = compress_FINISHED;
ses->compression = compression_NONE;
case compress_FINISHED:
dataread=0;
ses->compression = compression_NONE;
*rawread = orig_toread - toread;
return 0;
}
}
......
......@@ -290,7 +290,45 @@ static void http_reading_response(_kernel_swi_regs *r, Session *ses)
#ifdef COMPRESSION
if (ses->compression) {
#ifdef TEST_COMPRESSION_CODE
int i, result, readthistime;
dataread=0;
rawread=0;
for (i=0; i<toread; i++)
{
result= decompress(ses, buffer+dataread, bufsize-dataread, (toread-i)>4?4:(toread-i), &readthistime);
if (result<0 && errno == EWOULDBLOCK && readthistime > 0)
{
rawread+=readthistime;
continue;
}
else if (result < 0)
{
#ifdef TRACE
protocol_debug("Error!!! %d\n", errno);
#endif
dataread=-1; /*??*/
rawread+=readthistime;
break;
}
else if (result == 0) {
#ifdef TRACE
protocol_debug("result was zero\n");
#endif
rawread+=readthistime;
ses->compression=compression_NONE;
#ifdef TRACE
protocol_debug("rawread ends as %d, dataread ends as %d\n", rawread, dataread);
#endif
break;
}
dataread+=result;
rawread+=readthistime;
}
#else
dataread = decompress(ses, buffer, bufsize, toread, &rawread);
#endif
} else
#endif
dataread = rawread = ses->op->s_recv(ses->sd, buffer, toread, 0);
......
......@@ -21,7 +21,7 @@
title-string: AcornHTTP
; Version information
help-string: Acorn_HTTP 0.80
help-string: Acorn_HTTP 0.81
; Initialisation routine.
initialisation-code: module_init
......@@ -55,4 +55,4 @@ service-call-handler: service_handler &83E00 &83E02
vector-handlers: callevery_entry/callevery_handler,
callback_entry/callback_handler
date-string: 21 Apr 1998
date-string: 23 Apr 1998
......@@ -53,9 +53,11 @@ typedef enum {
compress_INFLATE,
compress_READ_GZIP_HEADER,
compress_READ_GZIP_EXTRA,
compress_READING_GZIP_EXTRA,
compress_READ_GZIP_NAME,
compress_READ_GZIP_COMMENT,
compress_READ_GZIP_HCRC,
compress_READ_GZIP_TRAILER,
compress_FINISHED
} compress_state;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment