diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-08-12 21:05:49 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-08-12 21:05:49 +0000 |
commit | 1b9064d5355b5c26676e8447a1900116066e42e4 (patch) | |
tree | 5f1c4a0e433a10b6778fa95d16eb4366777630d2 | |
parent | ff65cd469b5f9acc43c79df98ac8e375a257f152 (diff) | |
download | busybox-w32-1b9064d5355b5c26676e8447a1900116066e42e4.tar.gz busybox-w32-1b9064d5355b5c26676e8447a1900116066e42e4.tar.bz2 busybox-w32-1b9064d5355b5c26676e8447a1900116066e42e4.zip |
httpd: sendfile support
-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 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 | ||
86 | config 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 | |||
86 | config FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP | 94 | config 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 | ****************************************************************************/ |
1343 | static int sendFile(const char *url) | 1346 | static 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: */ |