mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-25 22:55:56 -05:00
Add gzip content-encoding from patch by Ciamac Moallemi
This commit is contained in:
parent
a82653e538
commit
1e17bf8c41
4
CREDITS
4
CREDITS
@ -58,3 +58,7 @@ Gavin Shelley
|
||||
|
||||
Stephen Rubner
|
||||
* fixes for ulong ino_t
|
||||
|
||||
Ciamac Moallemi
|
||||
* gzip content-encoding
|
||||
|
||||
|
@ -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");
|
||||
|
145
src/daap-proto.c
145
src/daap-proto.c
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
44
src/main.c
44
src/main.c
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user