diff options
author | Bill Stoddard <stoddard@apache.org> | 2000-07-10 23:49:22 +0200 |
---|---|---|
committer | Bill Stoddard <stoddard@apache.org> | 2000-07-10 23:49:22 +0200 |
commit | 6aa73a79bcaad20bfb18ab505cf182d357c9b780 (patch) | |
tree | 406d9d06a0c10a11ab637ae0c27ee4c5b361e736 /modules | |
parent | Move setup_listeners to listen.c. This renames it to ap_setup_listeners, (diff) | |
download | apache2-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.c | 27 | ||||
-rw-r--r-- | modules/generators/mod_asis.c | 3 | ||||
-rw-r--r-- | modules/http/http_core.c | 13 | ||||
-rw-r--r-- | modules/http/http_protocol.c | 121 |
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; } /* |