From f0239951e1b181d09cdd9e416a6655c128c3f58e Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Tue, 2 Feb 2010 21:03:29 +0100 Subject: [PATCH] Replace evbuffer_read(); should not be applied to files evbuffer_read() is really meant to read from sockets and not regular files. It also looks like evbuffer_read() was causing issues with large files, locking up a little below 2 GB for an unknown reason (couldn't reproduce). --- src/httpd.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/httpd.c b/src/httpd.c index 1fd1864c..af9f5a0e 100644 --- a/src/httpd.c +++ b/src/httpd.c @@ -79,6 +79,7 @@ struct content_type_map { struct stream_ctx { struct evhttp_request *req; + uint8_t *buf; struct evbuffer *evbuf; struct event ev; int id; @@ -129,7 +130,10 @@ stream_end(struct stream_ctx *st, int failed) if (st->xcode) transcode_cleanup(st->xcode); else - close(st->fd); + { + free(st->buf); + close(st->fd); + } free(st); } @@ -249,7 +253,7 @@ stream_chunk_raw_cb(int fd, short event, void *arg) else chunk_size = STREAM_CHUNK_SIZE; - ret = evbuffer_read(st->evbuf, st->fd, chunk_size); + ret = read(st->fd, st->buf, chunk_size); if (ret <= 0) { if (ret == 0) @@ -263,6 +267,8 @@ stream_chunk_raw_cb(int fd, short event, void *arg) DPRINTF(E_DBG, L_HTTPD, "Read %d bytes; streaming file id %d\n", ret, st->id); + evbuffer_add(st->evbuf, st->buf, ret); + evhttp_send_reply_chunk_with_cb(st->req, st->evbuf, stream_chunk_resched_cb, st); st->offset += ret; @@ -403,6 +409,18 @@ httpd_stream_file(struct evhttp_request *req, int id) /* Stream the raw file */ DPRINTF(E_INFO, L_HTTPD, "Preparing to stream %s\n", mfi->path); + st->buf = (uint8_t *)malloc(STREAM_CHUNK_SIZE); + if (!st->buf) + { + DPRINTF(E_LOG, L_HTTPD, "Out of memory for raw streaming buffer\n"); + + evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error"); + + free(st); + free_mfi(mfi, 0); + return; + } + stream_cb = stream_chunk_raw_cb; st->fd = open(mfi->path, O_RDONLY); @@ -412,6 +430,7 @@ httpd_stream_file(struct evhttp_request *req, int id) evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); + free(st->buf); free(st); free_mfi(mfi, 0); return; @@ -425,6 +444,7 @@ httpd_stream_file(struct evhttp_request *req, int id) evhttp_send_error(req, HTTP_NOTFOUND, "Not Found"); close(st->fd); + free(st->buf); free(st); free_mfi(mfi, 0); return; @@ -439,6 +459,7 @@ httpd_stream_file(struct evhttp_request *req, int id) evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); close(st->fd); + free(st->buf); free(st); free_mfi(mfi, 0); return; @@ -487,7 +508,10 @@ httpd_stream_file(struct evhttp_request *req, int id) if (transcode) transcode_cleanup(st->xcode); else - close(st->fd); + { + free(st->buf); + close(st->fd); + } free(st); free_mfi(mfi, 0); return; @@ -504,7 +528,10 @@ httpd_stream_file(struct evhttp_request *req, int id) if (transcode) transcode_cleanup(st->xcode); else - close(st->fd); + { + free(st->buf); + close(st->fd); + } evbuffer_free(st->evbuf); free(st); free_mfi(mfi, 0); @@ -525,7 +552,10 @@ httpd_stream_file(struct evhttp_request *req, int id) if (transcode) transcode_cleanup(st->xcode); else - close(st->fd); + { + free(st->buf); + close(st->fd); + } evbuffer_free(st->evbuf); free(st); free_mfi(mfi, 0);