summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorBill Stoddard <stoddard@apache.org>2000-07-10 23:49:22 +0200
committerBill Stoddard <stoddard@apache.org>2000-07-10 23:49:22 +0200
commit6aa73a79bcaad20bfb18ab505cf182d357c9b780 (patch)
tree406d9d06a0c10a11ab637ae0c27ee4c5b361e736 /modules
parentMove setup_listeners to listen.c. This renames it to ap_setup_listeners, (diff)
downloadapache2-6aa73a79bcaad20bfb18ab505cf182d357c9b780.tar.xz
apache2-6aa73a79bcaad20bfb18ab505cf182d357c9b780.zip
Reimplement ap_send_fd. Eliminate ap_send_fd_length. If APR_HAS_SENDFILE is
defined but ap_sendfile fails with APR_ENOTIMPL, the BUFF implementation of ap_send_fd will get a shot at serving the request. This fix is required to get Apache working on 95/98 again and can also be useful on Unix systems where sendfile is available via a servicepack/fixpack/PTF on a particular level of the OS (e.g., AIX 4.3.2 base does not include sendfile but is is available with a PTF). This fix also reimplements the mod_file_cache sendfile_handler using ap_send_fd and sets the connection aborted flag if the sendfile fails. Future modification... Add code to ap_send_fd to hijack any data in the client BUFF structure and send it along with the sendfile. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@85810 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules')
-rw-r--r--modules/cache/mod_file_cache.c27
-rw-r--r--modules/generators/mod_asis.c3
-rw-r--r--modules/http/http_core.c13
-rw-r--r--modules/http/http_protocol.c121
4 files changed, 108 insertions, 56 deletions
diff --git a/modules/cache/mod_file_cache.c b/modules/cache/mod_file_cache.c
index 23548d23f4..a711f7daad 100644
--- a/modules/cache/mod_file_cache.c
+++ b/modules/cache/mod_file_cache.c
@@ -398,7 +398,31 @@ static int mmap_handler(request_rec *r, a_file *file, int rangestatus)
return OK;
}
+static int sendfile_handler(request_rec *r, a_file *file, int rangestatus)
+{
+#if APR_HAS_SENDFILE
+ ap_size_t length, nbytes;
+ ap_off_t offset = 0;
+ ap_status_t rv;
+ if (!rangestatus) {
+ rv = ap_send_fd(file->file, r, 0, file->finfo.size, &nbytes);
+ }
+ else {
+ while (ap_each_byterange(r, &offset, &length)) {
+ if ((rv = ap_send_fd(file->file, r, offset, length, &nbytes)) != APR_SUCCESS)
+ break;
+ }
+ }
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "mod_file_cache: sendfile_handler error serving file: %s", r->filename);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+#endif
+ return OK;
+}
+#if 0
static int sendfile_handler(request_rec *r, a_file *file, int rangestatus)
{
#if APR_HAS_SENDFILE
@@ -447,7 +471,7 @@ static int sendfile_handler(request_rec *r, a_file *file, int rangestatus)
if (rv != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"mod_file_cache: iol_sendfile failed.");
- }
+ }
}
else {
while (ap_each_byterange(r, &offset, &length)) {
@@ -467,6 +491,7 @@ static int sendfile_handler(request_rec *r, a_file *file, int rangestatus)
#endif
return OK;
}
+#endif
static int file_cache_handler(request_rec *r)
{
diff --git a/modules/generators/mod_asis.c b/modules/generators/mod_asis.c
index 7e06698f28..4048008565 100644
--- a/modules/generators/mod_asis.c
+++ b/modules/generators/mod_asis.c
@@ -72,6 +72,7 @@ static int asis_handler(request_rec *r)
ap_file_t *f = NULL;
ap_status_t status;
const char *location;
+ ap_size_t nbytes;
r->allowed |= (1 << M_GET);
if (r->method_number != M_GET)
@@ -112,7 +113,7 @@ static int asis_handler(request_rec *r)
ap_send_http_header(r);
if (!r->header_only) {
- ap_send_fd(f, r);
+ ap_send_fd(f, r, 0, r->finfo.size, &nbytes);
}
ap_close(f);
diff --git a/modules/http/http_core.c b/modules/http/http_core.c
index 2340f33975..1e770ce5b2 100644
--- a/modules/http/http_core.c
+++ b/modules/http/http_core.c
@@ -2771,21 +2771,20 @@ static int default_handler(request_rec *r)
ap_send_http_header(r);
if (!r->header_only) {
+ ap_size_t length = r->finfo.size;
+ ap_off_t offset = 0;
+ ap_size_t nbytes = 0;
+
if (!rangestatus) {
- ap_send_fd(fd, r);
+ ap_send_fd(fd, r, offset, length, &nbytes);
}
else {
- long length;
- ap_off_t offset;
-
while (ap_each_byterange(r, &offset, &length)) {
- if ((status = ap_seek(fd, APR_SET, &offset)) != APR_SUCCESS) {
+ if ((status = ap_send_fd(fd, r, offset, length, &nbytes)) != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
"error byteserving file: %s", r->filename);
- ap_close(fd);
return HTTP_INTERNAL_SERVER_ERROR;
}
- ap_send_fd_length(fd, r, length);
}
}
}
diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c
index 4f511c3b60..bb78d74920 100644
--- a/modules/http/http_protocol.c
+++ b/modules/http/http_protocol.c
@@ -2243,63 +2243,88 @@ API_EXPORT(int) ap_discard_request_body(request_rec *r)
return OK;
}
+#if APR_HAS_SENDFILE
+static ap_status_t static_send_file(ap_file_t *fd, request_rec *r, ap_off_t offset,
+ ap_size_t length, ap_size_t *nbytes)
+{
+ ap_int32_t flags = 0;
+ ap_status_t rv;
+
+ ap_bsetopt(r->connection->client, BO_TIMEOUT,
+ r->connection->keptalive
+ ? &r->server->keep_alive_timeout
+ : &r->server->timeout);
+
+ ap_bflush(r->connection->client);
+
+ if (!r->connection->keepalive) {
+ /* Prepare the socket to be reused */
+ flags |= APR_SENDFILE_DISCONNECT_SOCKET;
+ }
+
+ rv = iol_sendfile(r->connection->client->iol,
+ fd, /* The file to send */
+ NULL, /* Header and trailer iovecs */
+ &offset, /* Offset in file to begin sending from */
+ &length,
+ flags);
+
+ if (r->connection->keptalive) {
+ ap_bsetopt(r->connection->client, BO_TIMEOUT,
+ &r->server->timeout);
+ }
+
+ *nbytes = length;
+
+ return rv;
+}
+#endif
/*
* Send the body of a response to the client.
*/
-API_EXPORT(long) ap_send_fd(ap_file_t *fd, request_rec *r)
+API_EXPORT(ap_status_t) ap_send_fd(ap_file_t *fd, request_rec *r, ap_off_t offset,
+ ap_size_t length, ap_size_t *nbytes)
{
- ap_size_t len = r->finfo.size;
+ ap_status_t rv = APR_SUCCESS;
+ ap_size_t total_bytes_sent = 0;
+ register int o;
+ ap_ssize_t n;
+ char buf[IOBUFSIZE];
+
+ if ((length == 0) || r->connection->aborted) {
+ *nbytes = 0;
+ return APR_SUCCESS;
+ }
+
#if APR_HAS_SENDFILE
- ap_int32_t flags = 0;
+ /* Chunked encoding must be handled in the BUFF */
if (!r->chunked) {
- ap_status_t rv;
- ap_bsetopt(r->connection->client, BO_TIMEOUT,
- r->connection->keptalive
- ? &r->server->keep_alive_timeout
- : &r->server->timeout);
- ap_bflush(r->connection->client);
-
- if (!r->connection->keepalive) {
- /* Prepare the socket to be reused. Ignored on systems
- * that do not support reusing the accept socket
- */
- flags |= APR_SENDFILE_DISCONNECT_SOCKET;
- }
-
- rv = iol_sendfile(r->connection->client->iol,
- fd, /* The file to send */
- NULL, /* header and trailer iovecs */
- 0, /* Offset in file to begin sending from */
- &len,
- flags);
- if (rv != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "ap_send_fd: iol_sendfile failed.");
+ rv = static_send_file(fd, r, offset, length, &total_bytes_sent);
+ if (rv == APR_SUCCESS) {
+ r->bytes_sent += total_bytes_sent;
+ *nbytes = total_bytes_sent;
+ return rv;
}
- if (r->connection->keptalive) {
- ap_bsetopt(r->connection->client, BO_TIMEOUT,
- &r->server->timeout);
+ /* Don't consider APR_ENOTIMPL a failure */
+ if (rv != APR_ENOTIMPL) {
+ check_first_conn_error(r, "send_fd", rv);
+ r->bytes_sent += total_bytes_sent;
+ *nbytes = total_bytes_sent;
+ return rv;
}
}
- else {
- len = ap_send_fd_length(fd, r, -1);
- }
-#else
- len = ap_send_fd_length(fd, r, -1);
#endif
- return len;
-}
-API_EXPORT(long) ap_send_fd_length(ap_file_t *fd, request_rec *r, long length)
-{
- char buf[IOBUFSIZE];
- long total_bytes_sent = 0;
- register int o;
- ap_ssize_t n;
- ap_status_t rv;
-
- if (length == 0)
- return 0;
+ /* Either sendfile is not defined or it failed with APR_ENOTIMPL */
+ if (offset) {
+ /* Seek the file to the offset */
+ rv = ap_seek(fd, APR_SET, &offset);
+ if (rv != APR_SUCCESS) {
+ *nbytes = total_bytes_sent;
+ /* ap_close(fd); close the file or let the caller handle it? */
+ return rv;
+ }
+ }
while (!r->connection->aborted) {
if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length)
@@ -2311,6 +2336,7 @@ API_EXPORT(long) ap_send_fd_length(ap_file_t *fd, request_rec *r, long length)
rv = ap_read(fd, buf, &n);
} while (rv == APR_EINTR && !r->connection->aborted);
+ /* Is this still the right check? maybe check for n==0 or rv == APR_EOF? */
if (n < 1) {
break;
}
@@ -2322,7 +2348,8 @@ API_EXPORT(long) ap_send_fd_length(ap_file_t *fd, request_rec *r, long length)
}
SET_BYTES_SENT(r);
- return total_bytes_sent;
+ *nbytes = total_bytes_sent;
+ return rv;
}
/*