Add gzip content-encoding from patch by Ciamac Moallemi

This commit is contained in:
Ron Pedde 2004-12-29 05:44:32 +00:00
parent a82653e538
commit 1e17bf8c41
6 changed files with 190 additions and 28 deletions

View File

@ -58,3 +58,7 @@ Gavin Shelley
Stephen Rubner
* fixes for ulong ino_t
Ciamac Moallemi
* gzip content-encoding

View File

@ -112,6 +112,7 @@ CONFIGELEMENT config_elements[] = {
{ 1,0,0,CONFIG_TYPE_INT,"always_scan",(void*)&config.always_scan,config_emit_int },
{ 1,0,0,CONFIG_TYPE_INT,"process_m3u",(void*)&config.process_m3u,config_emit_int },
{ 1,0,0,CONFIG_TYPE_INT,"scan_type",(void*)&config.scan_type,config_emit_int },
{ 1,0,0,CONFIG_TYPE_INT,"compress",(void*)&config.compress,config_emit_int },
{ 1,0,0,CONFIG_TYPE_STRING,"playlist",(void*)&config.playlist,config_emit_string },
{ 1,0,0,CONFIG_TYPE_STRING,"extensions",(void*)&config.extensions,config_emit_string },
{ 1,0,0,CONFIG_TYPE_STRING,"password",(void*)&config.readpassword, config_emit_string },
@ -255,6 +256,7 @@ int config_read(char *file) {
config.rescan_interval=0;
config.process_m3u=0;
config.scan_type=0;
config.compress=0;
/* DWB: use alloced space so it can be freed without errors */
config.extensions=strdup(".mp3");

View File

@ -37,6 +37,103 @@
DAAP_BLOCK *daap_get_new(void);
DAAP_BLOCK *daap_add_formatted(DAAP_BLOCK *parent, char *tag,
int len, char *value);
GZIP_STREAM *gzip_alloc(void) {
GZIP_STREAM *gz = malloc(sizeof(GZIP_STREAM));
gz->in_size = GZIP_CHUNK;
gz->in = malloc(gz->in_size);
gz->bytes_in = 0;
gz->out = NULL;
gz->bytes_out = 0;
return gz;
}
ssize_t gzip_write(GZIP_STREAM *gz, void *buf, size_t size) {
int next_size;
char *in2;
int new_size;
if (gz->in == NULL)
return -1;
/* make sure input buffer is big enough */
while (gz->in_size <= gz->bytes_in + size) {
new_size = 2*gz->in_size;
in2 = malloc(new_size);
if (in2 == NULL) {
DPRINTF(E_LOG,L_WS|L_DAAP,"out of memory for input buffer\n");
free(gz->in);
gz->in = NULL;
gz->bytes_in = gz->in_size = 0;
return -1;
}
memcpy(in2, gz->in, gz->in_size);
free(gz->in);
gz->in = in2;
gz->in_size = new_size;
}
memcpy(gz->in + gz->bytes_in, buf, size);
gz->bytes_in += size;
return size;
}
int gzip_compress(GZIP_STREAM *gz) {
int out_size;
int status;
z_stream strm;
if (gz->in == NULL)
return -1;
out_size = (int)(1.05*gz->in_size) + 20;
gz->out = malloc(out_size);
if (gz->out == NULL) {
DPRINTF(E_INF,L_WS|L_DAAP,"out of memory for output buffer\n");
gz->bytes_out = 0;
return -1;
}
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.next_in = gz->in;
strm.avail_in = gz->bytes_in;
strm.next_out = gz->out;
strm.avail_out = out_size;
deflateInit2(&strm,GZIP_COMPRESSION_LEVEL,Z_DEFLATED,31,8,Z_DEFAULT_STRATEGY);
while ((status = deflate(&strm,Z_FINISH)) == Z_OK)
;
if (status != Z_STREAM_END) {
DPRINTF(E_LOG,L_WS|L_DAAP,"unable to compress data\n");
gz->bytes_out = 0;
return -1;
}
gz->bytes_out = strm.total_out;
deflateEnd(&strm);
return gz->bytes_out;
}
int gzip_close(GZIP_STREAM *gz, int fd) {
int bytes_written = gz->bytes_out;
if (r_write(fd,gz->out,gz->bytes_out) != gz->bytes_out) {
DPRINTF(E_LOG,L_WS|L_DAAP,"unable to write gzipped data\n");
return -1;
}
if (gz->in != NULL)
free(gz->in);
if (gz->out != NULL)
free(gz->out);
free(gz);
return bytes_written;
}
/*
* daap_get_new
*
@ -237,32 +334,50 @@ DAAP_BLOCK *daap_add_empty(DAAP_BLOCK *parent, char *tag) {
*
* Serialize a daap tree to a fd;
*/
int daap_serialize(DAAP_BLOCK *root, int fd, int gzip) {
int daap_serialize(DAAP_BLOCK *root, int fd, GZIP_STREAM *gz) {
char size[4];
while(root) {
if (gz == NULL)
r_write(fd,root->tag,4);
else
gzip_write(gz,root->tag,4);
size[0] = (root->reported_size >> 24) & 0xFF;
size[1] = (root->reported_size >> 16) & 0xFF;
size[2] = (root->reported_size >> 8 ) & 0xFF;
size[3] = (root->reported_size) & 0xFF;
size[0] = (root->reported_size >> 24) & 0xFF;
size[1] = (root->reported_size >> 16) & 0xFF;
size[2] = (root->reported_size >> 8 ) & 0xFF;
size[3] = (root->reported_size) & 0xFF;
if (gz == NULL)
r_write(fd,&size,4);
else
gzip_write(gz,&size,4);
if(root->size) {
if(root->free)
r_write(fd,root->value,root->size);
else
r_write(fd,root->svalue,root->size);
if(root->size) {
if(root->free) {
if (gz == NULL) {
r_write(fd,root->value,root->size);
}
else {
gzip_write(gz,root->value,root->size);
}
}
if(root->children) {
if(daap_serialize(root->children,fd,gzip))
return -1;
else {
if (gz == NULL) {
r_write(fd,root->svalue,root->size);
}
else {
gzip_write(gz,root->svalue,root->size);
}
}
}
root=root->next;
if(root->children) {
if(daap_serialize(root->children,fd,gz))
return -1;
}
root=root->next;
}
return 0;

View File

@ -23,6 +23,24 @@
#define _DAAP_PROTO_H_
#include "zlib.h"
#define GZIP_CHUNK 16384
#define GZIP_COMPRESSION_LEVEL Z_DEFAULT_COMPRESSION
typedef struct gzip_stream_tag {
int bytes_in;
int bytes_out;
int in_size;
char *in;
char *out;
} GZIP_STREAM;
GZIP_STREAM *gzip_alloc(void);
ssize_t gzip_write(GZIP_STREAM *gz, void *buf, size_t size);
int gzip_compress(GZIP_STREAM *gz);
int gzip_close(GZIP_STREAM *gz, int fd);
typedef struct daap_block_tag {
char tag[4];
int reported_size;
@ -42,7 +60,7 @@ DAAP_BLOCK *daap_add_empty(DAAP_BLOCK *parent, char *tag);
DAAP_BLOCK *daap_add_char(DAAP_BLOCK *parent, char *tag, char value);
DAAP_BLOCK *daap_add_short(DAAP_BLOCK *parent, char *tag, short int value);
DAAP_BLOCK *daap_add_long(DAAP_BLOCK *parent, char *tag, int v1, int v2);
int daap_serialize(DAAP_BLOCK *root, int fd, int gzip);
int daap_serialize(DAAP_BLOCK *root, int fd, GZIP_STREAM *gz);
void daap_free(DAAP_BLOCK *root);
// remove a block from it's parent (and free it)

View File

@ -54,6 +54,7 @@ typedef struct tag_config {
int always_scan; /**< 0 to minimize disk usage (embedded devices) */
int process_m3u; /**< Should we process m3u files? */
int scan_type; /**< How hard to search mp3 files. see scan_get_mp3fileinfo() */
int compress; /**< Should we compress? */
char *adminpassword; /**< Password to web management pages */
char *readpassword; /**< iTunes password */
char *mp3dir; /**< root directory of the mp3 files */

View File

@ -171,6 +171,10 @@ void daap_handler(WS_CONNINFO *pwsc) {
char *first, *last;
char* index = 0;
int streaming=0;
int compress =0;
int start_time;
int end_time;
int bytes_written;
MP3FILE *pmp3;
int file_fd;
@ -325,21 +329,39 @@ void daap_handler(WS_CONNINFO *pwsc) {
if(!streaming) {
DPRINTF(E_DBG,L_WS,"Satisfying request\n");
ws_addresponseheader(pwsc,"Content-Length","%d",root->reported_size + 8);
ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
DPRINTF(E_DBG,L_WS,"Emitting headers\n");
ws_emitheaders(pwsc);
/*
if(ws_testrequestheader(pwsc,"Accept-Encoding","gzip")) {
ws_addresponseheader(pwsc,"Content-Encoding","gzip");
if((config.compress) && ws_testrequestheader(pwsc,"Accept-Encoding","gzip") && root->reported_size >= 1000) {
compress=1;
}
*/
}
DPRINTF(E_DBG,L_WS|L_DAAP,"Serializing\n");
daap_serialize(root,pwsc->fd,0);
start_time = time(NULL);
if (compress) {
DPRINTF(E_DBG,L_WS|L_DAAP,"Using compression: %s\n", pwsc->uri);
GZIP_STREAM *gz = gzip_alloc();
daap_serialize(root,pwsc->fd,gz);
gzip_compress(gz);
bytes_written = gz->bytes_out;
ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
ws_addresponseheader(pwsc,"Content-Length","%d",bytes_written);
ws_addresponseheader(pwsc,"Content-Encoding","gzip");
DPRINTF(E_DBG,L_WS,"Emitting headers\n");
ws_emitheaders(pwsc);
if (gzip_close(gz,pwsc->fd) != bytes_written) {
DPRINTF(E_LOG,L_WS|L_DAAP,"Error compressing data\n");
}
DPRINTF(E_DBG,L_WS|L_DAAP,"Compression ratio: %f\n",((double) bytes_written)/(8.0 + root->reported_size))
}
else {
bytes_written = root->reported_size + 8;
ws_addresponseheader(pwsc,"Content-Length","%d",bytes_written);
ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
DPRINTF(E_DBG,L_WS,"Emitting headers\n");
ws_emitheaders(pwsc);
daap_serialize(root,pwsc->fd,NULL);
}
end_time = time(NULL);
DPRINTF(E_DBG,L_WS|L_DAAP,"Sent %d bytes in %d seconds\n",bytes_written,end_time-start_time);
DPRINTF(E_DBG,L_WS|L_DAAP,"Done, freeing\n");
daap_free(root);
} else {