diff options
author | Denis Vlasenko | 2007-08-12 21:05:49 +0000 |
---|---|---|
committer | Denis Vlasenko | 2007-08-12 21:05:49 +0000 |
commit | 1b9064d5355b5c26676e8447a1900116066e42e4 (patch) | |
tree | 5f1c4a0e433a10b6778fa95d16eb4366777630d2 /networking | |
parent | ff65cd469b5f9acc43c79df98ac8e375a257f152 (diff) | |
download | busybox-1b9064d5355b5c26676e8447a1900116066e42e4.zip busybox-1b9064d5355b5c26676e8447a1900116066e42e4.tar.gz |
httpd: sendfile support
Diffstat (limited to 'networking')
-rw-r--r-- | networking/Config.in | 8 | ||||
-rw-r--r-- | networking/httpd.c | 60 |
2 files changed, 47 insertions, 21 deletions
diff --git a/networking/Config.in b/networking/Config.in index 2ea0650..3013be6 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 b083d64..3e3117a 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -92,6 +92,9 @@ */ #include "libbb.h" +#if ENABLE_FEATURE_HTTPD_USE_SENDFILE +#include <sys/sendfile.h> +#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, - "<HEAD><TITLE>%d %s</TITLE></HEAD>\n" - "<BODY><H1>%d %s</H1>\n%s\n</BODY>\n", + "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n" + "<BODY><H1>%d %s</H1>\n%s\n</BODY></HTML>\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: */ |