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
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)) {
#endif
return OK;
}
+#endif
static int file_cache_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);
}
}
}
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)
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;
}
}
SET_BYTES_SENT(r);
- return total_bytes_sent;
+ *nbytes = total_bytes_sent;
+ return rv;
}
/*