From 2ea7764431b5c81a3885d5be1fa48b92ef36fc53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Wed, 2 Mar 2011 23:32:45 +0100 Subject: [PATCH] Fix a couple of bugs related to sending files > 2GB Ticket #391 --- src/http.c | 8 +++++--- src/http.h | 3 ++- src/webui/webui.c | 27 ++++++++++++++++++--------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/http.c b/src/http.c index 9cca5036..8d94c8bc 100644 --- a/src/http.c +++ b/src/http.c @@ -123,7 +123,8 @@ static const char * http_rc2str(int code) { switch(code) { - case HTTP_STATUS_OK: return "Ok"; + case HTTP_STATUS_OK: return "OK"; + case HTTP_STATUS_PARTIAL_CONTENT: return "Partial Content"; case HTTP_STATUS_NOT_FOUND: return "Not found"; case HTTP_STATUS_UNAUTHORIZED: return "Unauthorized"; case HTTP_STATUS_BAD_REQUEST: return "Bad request"; @@ -149,7 +150,8 @@ static const char *cachemonths[12] = { */ void http_send_header(http_connection_t *hc, int rc, const char *content, - int contentlen, const char *encoding, const char *location, + int64_t contentlen, + const char *encoding, const char *location, int maxage, const char *range) { struct tm tm0, *tm; @@ -204,7 +206,7 @@ http_send_header(http_connection_t *hc, int rc, const char *content, htsbuf_qprintf(&hdrs, "Content-Type: %s\r\n", content); if(contentlen > 0) - htsbuf_qprintf(&hdrs, "Content-Length: %d\r\n", contentlen); + htsbuf_qprintf(&hdrs, "Content-Length: %"PRId64"\r\n", contentlen); if(range) { htsbuf_qprintf(&hdrs, "Accept-Ranges: %s\r\n", "bytes"); diff --git a/src/http.h b/src/http.h index 27897dfe..86adf1b0 100644 --- a/src/http.h +++ b/src/http.h @@ -30,6 +30,7 @@ typedef struct http_arg { } http_arg_t; #define HTTP_STATUS_OK 200 +#define HTTP_STATUS_PARTIAL_CONTENT 206 #define HTTP_STATUS_FOUND 302 #define HTTP_STATUS_BAD_REQUEST 400 #define HTTP_STATUS_UNAUTHORIZED 401 @@ -111,7 +112,7 @@ void http_output_content(http_connection_t *hc, const char *content); void http_redirect(http_connection_t *hc, const char *location); void http_send_header(http_connection_t *hc, int rc, const char *content, - int contentlen, const char *encoding, + int64_t contentlen, const char *encoding, const char *location, int maxage, const char *range); typedef int (http_callback_t)(http_connection_t *hc, diff --git a/src/webui/webui.c b/src/webui/webui.c index 723d5676..6c721ac6 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -525,7 +525,8 @@ page_dvrfile(http_connection_t *hc, const char *remain, void *opaque) dvr_entry_t *de; char *fname; char range_buf[255]; - off_t content_len, file_start, file_end; + off_t content_len, file_start, file_end, chunk; + ssize_t r; if(remain == NULL) return 404; @@ -577,19 +578,27 @@ page_dvrfile(http_connection_t *hc, const char *remain, void *opaque) content_len = file_end - file_start+1; - sprintf(range_buf, "bytes %"PRId64"-%"PRId64"/%"PRId64"", file_start, file_end, st.st_size); + sprintf(range_buf, "bytes %"PRId64"-%"PRId64"/%"PRId64"", + file_start, file_end, st.st_size); if(file_start > 0) lseek(fd, file_start, SEEK_SET); - http_send_header(hc, 200, content, content_len, NULL, NULL, 10, range_buf); - sendfile(hc->hc_fd, fd, NULL, content_len); - close(fd); + http_send_header(hc, range ? HTTP_STATUS_PARTIAL_CONTENT : HTTP_STATUS_OK, + content, content_len, NULL, NULL, 10, + range ? range_buf : NULL); - if(range) - return 206; - else - return 0; + if(!hc->hc_no_output) { + while(content_len > 0) { + chunk = MIN(1024 * 1024 * 1024, content_len); + r = sendfile(hc->hc_fd, fd, NULL, chunk); + if(r == -1) + return -1; + content_len -= r; + } + } + close(fd); + return 0; }