aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-08-12 21:05:49 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-08-12 21:05:49 +0000
commit1b9064d5355b5c26676e8447a1900116066e42e4 (patch)
tree5f1c4a0e433a10b6778fa95d16eb4366777630d2
parentff65cd469b5f9acc43c79df98ac8e375a257f152 (diff)
downloadbusybox-w32-1b9064d5355b5c26676e8447a1900116066e42e4.tar.gz
busybox-w32-1b9064d5355b5c26676e8447a1900116066e42e4.tar.bz2
busybox-w32-1b9064d5355b5c26676e8447a1900116066e42e4.zip
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 2ea0650a0..3013be676 100644
--- a/networking/Config.in
+++ b/networking/Config.in
@@ -83,6 +83,14 @@ config HTTPD
83 help 83 help
84 Serve web pages via an HTTP server. 84 Serve web pages via an HTTP server.
85 85
86config FEATURE_HTTPD_USE_SENDFILE
87 bool "Use sendfile system call"
88 default n
89 depends on HTTPD
90 help
91 When enabled, httpd will use the kernel sendfile() function
92 instead of read/write loop.
93
86config FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP 94config FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
87 bool "Support reloading the global config file using hup signal" 95 bool "Support reloading the global config file using hup signal"
88 default n 96 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 @@
92*/ 92*/
93 93
94#include "libbb.h" 94#include "libbb.h"
95#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
96#include <sys/sendfile.h>
97#endif
95 98
96/* amount of buffering in a pipe */ 99/* amount of buffering in a pipe */
97#ifndef PIPE_BUF 100#ifndef PIPE_BUF
@@ -922,15 +925,15 @@ static int sendHeaders(HttpResponseNum responseNum)
922 len += 2; 925 len += 2;
923 if (infoString) { 926 if (infoString) {
924 len += sprintf(buf+len, 927 len += sprintf(buf+len,
925 "<HEAD><TITLE>%d %s</TITLE></HEAD>\n" 928 "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n"
926 "<BODY><H1>%d %s</H1>\n%s\n</BODY>\n", 929 "<BODY><H1>%d %s</H1>\n%s\n</BODY></HTML>\n",
927 responseNum, responseString, 930 responseNum, responseString,
928 responseNum, responseString, infoString); 931 responseNum, responseString, infoString);
929 } 932 }
930 if (DEBUG) 933 if (DEBUG)
931 fprintf(stderr, "headers: '%s'\n", buf); 934 fprintf(stderr, "headers: '%s'\n", buf);
932 i = accepted_socket; 935 i = accepted_socket;
933 if (i == 0) i++; /* write to fd# 1 in inetd mode */ 936 if (i == 0) i++; /* write to fd #1 in inetd mode */
934 return full_write(i, buf, len); 937 return full_write(i, buf, len);
935} 938}
936 939
@@ -1342,10 +1345,15 @@ static int sendCgi(const char *url,
1342 ****************************************************************************/ 1345 ****************************************************************************/
1343static int sendFile(const char *url) 1346static int sendFile(const char *url)
1344{ 1347{
1345 char * suffix; 1348 char *suffix;
1346 int f; 1349 int f;
1350 int fd;
1347 const char *const *table; 1351 const char *const *table;
1348 const char *try_suffix; 1352 const char *try_suffix;
1353 ssize_t count;
1354#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
1355 off_t offset = 0;
1356#endif
1349 1357
1350 suffix = strrchr(url, '.'); 1358 suffix = strrchr(url, '.');
1351 1359
@@ -1360,7 +1368,6 @@ static int sendFile(const char *url)
1360#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES 1368#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
1361 if (suffix) { 1369 if (suffix) {
1362 Htaccess * cur; 1370 Htaccess * cur;
1363
1364 for (cur = mime_a; cur; cur = cur->next) { 1371 for (cur = mime_a; cur; cur = cur->next) {
1365 if (strcmp(cur->before_colon, suffix) == 0) { 1372 if (strcmp(cur->before_colon, suffix) == 0) {
1366 found_mime_type = cur->after_colon; 1373 found_mime_type = cur->after_colon;
@@ -1375,25 +1382,36 @@ static int sendFile(const char *url)
1375 url, found_mime_type); 1382 url, found_mime_type);
1376 1383
1377 f = open(url, O_RDONLY); 1384 f = open(url, O_RDONLY);
1378 if (f >= 0) { 1385 if (f < 0) {
1379 int count;
1380 char *buf = iobuf;
1381
1382 sendHeaders(HTTP_OK);
1383 /* TODO: sendfile() */
1384 while ((count = full_read(f, buf, MAX_MEMORY_BUFF)) > 0) {
1385 int fd = accepted_socket;
1386 if (fd == 0) fd++; /* write to fd# 1 in inetd mode */
1387 if (full_write(fd, buf, count) != count)
1388 break;
1389 }
1390 close(f);
1391 } else {
1392 if (DEBUG) 1386 if (DEBUG)
1393 bb_perror_msg("cannot open '%s'", url); 1387 bb_perror_msg("cannot open '%s'", url);
1394 sendHeaders(HTTP_NOT_FOUND); 1388 sendHeaders(HTTP_NOT_FOUND);
1389 return 0;
1395 } 1390 }
1396 1391
1392 sendHeaders(HTTP_OK);
1393 fd = accepted_socket;
1394 if (fd == 0)
1395 fd++; /* write to fd #1 in inetd mode */
1396#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
1397 do {
1398 count = sendfile(fd, f, &offset, MAXINT(ssize_t));
1399 if (count < 0) {
1400 if (offset == 0)
1401 goto fallback;
1402 bb_perror_msg("sendfile '%s'", url);
1403 }
1404 } while (count > 0);
1405 close(f);
1406 return 0;
1407
1408 fallback:
1409#endif
1410 while ((count = full_read(f, iobuf, MAX_MEMORY_BUFF)) > 0) {
1411 if (full_write(fd, iobuf, count) != count)
1412 break;
1413 }
1414 close(f);
1397 return 0; 1415 return 0;
1398} 1416}
1399 1417
@@ -1689,11 +1707,11 @@ static void handleIncoming(void)
1689 if ((STRNCASECMP(buf, "Content-length:") == 0)) { 1707 if ((STRNCASECMP(buf, "Content-length:") == 0)) {
1690 /* extra read only for POST */ 1708 /* extra read only for POST */
1691 if (prequest != request_GET) { 1709 if (prequest != request_GET) {
1692 test = buf + sizeof("Content-length:")-1; 1710 test = buf + sizeof("Content-length:") - 1;
1693 if (!test[0]) 1711 if (!test[0])
1694 goto bail_out; 1712 goto bail_out;
1695 errno = 0; 1713 errno = 0;
1696 /* not using strtoul: it ignores leading munis! */ 1714 /* not using strtoul: it ignores leading minus! */
1697 length = strtol(test, &test, 10); 1715 length = strtol(test, &test, 10);
1698 /* length is "ulong", but we need to pass it to int later */ 1716 /* length is "ulong", but we need to pass it to int later */
1699 /* so we check for negative or too large values in one go: */ 1717 /* so we check for negative or too large values in one go: */