From 1b9064d5355b5c26676e8447a1900116066e42e4 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sun, 12 Aug 2007 21:05:49 +0000 Subject: [PATCH] httpd: sendfile support --- networking/Config.in | 8 ++++++ networking/httpd.c | 60 ++++++++++++++++++++++++++++---------------- 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/networking/Config.in b/networking/Config.in index 2ea0650a0..3013be676 100644 --- a/networking/Config.in +++ b/networking/Config.in @@ -83,6 +83,14 @@ config HTTPD help Serve web pages via an HTTP server. +config FEATURE_HTTPD_USE_SENDFILE + bool "Use sendfile system call" + default n + depends on HTTPD + help + When enabled, httpd will use the kernel sendfile() function + instead of read/write loop. + config FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP bool "Support reloading the global config file using hup signal" default n diff --git a/networking/httpd.c b/networking/httpd.c index b083d645c..3e3117a79 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -92,6 +92,9 @@ */ #include "libbb.h" +#if ENABLE_FEATURE_HTTPD_USE_SENDFILE +#include +#endif /* amount of buffering in a pipe */ #ifndef PIPE_BUF @@ -922,15 +925,15 @@ static int sendHeaders(HttpResponseNum responseNum) len += 2; if (infoString) { len += sprintf(buf+len, - "%d %s\n" - "

%d %s

\n%s\n\n", + "%d %s\n" + "

%d %s

\n%s\n\n", responseNum, responseString, responseNum, responseString, infoString); } if (DEBUG) fprintf(stderr, "headers: '%s'\n", buf); i = accepted_socket; - if (i == 0) i++; /* write to fd# 1 in inetd mode */ + if (i == 0) i++; /* write to fd #1 in inetd mode */ return full_write(i, buf, len); } @@ -1342,10 +1345,15 @@ static int sendCgi(const char *url, ****************************************************************************/ static int sendFile(const char *url) { - char * suffix; + char *suffix; int f; + int fd; const char *const *table; const char *try_suffix; + ssize_t count; +#if ENABLE_FEATURE_HTTPD_USE_SENDFILE + off_t offset = 0; +#endif suffix = strrchr(url, '.'); @@ -1360,7 +1368,6 @@ static int sendFile(const char *url) #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES if (suffix) { Htaccess * cur; - for (cur = mime_a; cur; cur = cur->next) { if (strcmp(cur->before_colon, suffix) == 0) { found_mime_type = cur->after_colon; @@ -1375,25 +1382,36 @@ static int sendFile(const char *url) url, found_mime_type); f = open(url, O_RDONLY); - if (f >= 0) { - int count; - char *buf = iobuf; - - sendHeaders(HTTP_OK); - /* TODO: sendfile() */ - while ((count = full_read(f, buf, MAX_MEMORY_BUFF)) > 0) { - int fd = accepted_socket; - if (fd == 0) fd++; /* write to fd# 1 in inetd mode */ - if (full_write(fd, buf, count) != count) - break; - } - close(f); - } else { + if (f < 0) { if (DEBUG) bb_perror_msg("cannot open '%s'", url); sendHeaders(HTTP_NOT_FOUND); + return 0; } + sendHeaders(HTTP_OK); + fd = accepted_socket; + if (fd == 0) + fd++; /* write to fd #1 in inetd mode */ +#if ENABLE_FEATURE_HTTPD_USE_SENDFILE + do { + count = sendfile(fd, f, &offset, MAXINT(ssize_t)); + if (count < 0) { + if (offset == 0) + goto fallback; + bb_perror_msg("sendfile '%s'", url); + } + } while (count > 0); + close(f); + return 0; + + fallback: +#endif + while ((count = full_read(f, iobuf, MAX_MEMORY_BUFF)) > 0) { + if (full_write(fd, iobuf, count) != count) + break; + } + close(f); return 0; } @@ -1689,11 +1707,11 @@ static void handleIncoming(void) if ((STRNCASECMP(buf, "Content-length:") == 0)) { /* extra read only for POST */ if (prequest != request_GET) { - test = buf + sizeof("Content-length:")-1; + test = buf + sizeof("Content-length:") - 1; if (!test[0]) goto bail_out; errno = 0; - /* not using strtoul: it ignores leading munis! */ + /* not using strtoul: it ignores leading minus! */ length = strtol(test, &test, 10); /* length is "ulong", but we need to pass it to int later */ /* so we check for negative or too large values in one go: */