]> granicus.if.org Git - apache/commitdiff
Reimplement ap_send_fd. Eliminate ap_send_fd_length. If APR_HAS_SENDFILE is
authorBill Stoddard <stoddard@apache.org>
Mon, 10 Jul 2000 21:49:22 +0000 (21:49 +0000)
committerBill Stoddard <stoddard@apache.org>
Mon, 10 Jul 2000 21:49:22 +0000 (21:49 +0000)
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

ApacheCore.def
include/http_protocol.h
libhttpd.def
modules/cache/mod_file_cache.c
modules/generators/mod_asis.c
modules/http/http_core.c
modules/http/http_protocol.c

index 7ac67b95ce72e58b5a60ce96929a22bce0bb534a..d472426cee6f942dca2da8ed373be0be0fe830cf 100644 (file)
@@ -219,7 +219,7 @@ EXPORTS
        ;ap_send_fb   @212
        ;ap_send_fb_length   @213
        ap_send_fd   @214
-       ap_send_fd_length   @215
+;      ap_send_fd_length   @215
        ap_send_http_header   @216
        ap_send_http_trace   @217
 ;      ap_send_mmap   @218
index c52b141d1f0ce12401cd0290edcac58ad9f356e2..14cb6c0adcfc86cb19d1751a45230a9de72d599f 100644 (file)
@@ -136,8 +136,8 @@ API_EXPORT(int) ap_meets_conditions(request_rec *r);
  * (Ditto the send_header stuff).
  */
 
-API_EXPORT(long) ap_send_fd(ap_file_t *fd, request_rec *r);
-API_EXPORT(long) ap_send_fd_length(ap_file_t *fd, request_rec *r, long length);
+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);
 
 API_EXPORT(long) ap_send_fb(BUFF *f, request_rec *r);
 API_EXPORT(long) ap_send_fb_length(BUFF *f, request_rec *r, long length);
index 7ac67b95ce72e58b5a60ce96929a22bce0bb534a..d472426cee6f942dca2da8ed373be0be0fe830cf 100644 (file)
@@ -219,7 +219,7 @@ EXPORTS
        ;ap_send_fb   @212
        ;ap_send_fb_length   @213
        ap_send_fd   @214
-       ap_send_fd_length   @215
+;      ap_send_fd_length   @215
        ap_send_http_header   @216
        ap_send_http_trace   @217
 ;      ap_send_mmap   @218
index 23548d23f4a6d7b105a8ccce7fac36cfb018a009..a711f7daadda231fe60a1df6bc4d6bdf21ad22ce 100644 (file)
@@ -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) 
 {
index 7e06698f28d28b9f2694a3265817332068c05ede..404800856561ac619b95dc6d911c19125cf39a15 100644 (file)
@@ -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);
index 2340f33975d08426d467c7679330a57b87b0fbcc..1e770ce5b291496f3dfe4995d838dca037f638c7 100644 (file)
@@ -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);
                }
            }
        }
index 4f511c3b60be2d2dccc535c23843ed53e7e61c03..bb78d74920b12bec5bcf10e2bcf2f40c1ad446ef 100644 (file)
@@ -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;
 }
 
 /*