summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko2007-08-12 21:05:49 +0000
committerDenis Vlasenko2007-08-12 21:05:49 +0000
commit1b9064d5355b5c26676e8447a1900116066e42e4 (patch)
tree5f1c4a0e433a10b6778fa95d16eb4366777630d2
parentff65cd469b5f9acc43c79df98ac8e375a257f152 (diff)
downloadbusybox-1b9064d5355b5c26676e8447a1900116066e42e4.zip
busybox-1b9064d5355b5c26676e8447a1900116066e42e4.tar.gz
httpd: sendfile support
-rw-r--r--networking/Config.in8
-rw-r--r--networking/httpd.c60
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: */