Commit 04455a06 authored by Ryan Bloom's avatar Ryan Bloom
Browse files

Enabled layered I/O. Docs are forthcoming.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@84837 13f79535-47bb-0310-9956-ffa450edef68
parent 185537d0
Loading
Loading
Loading
Loading
+11 −1
Changes for include/httpd.h: 11 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -391,7 +391,10 @@ API_EXPORT(const char *) ap_get_server_built(void);
				 *  - it's safe to die() with no more output
				 */
#define OK 0			/* Module has handled this stage. */

#define RERUN_HANDLERS 1        /* Module has handled this request, but
                                 * realizes others may also want to handle
                                 * it.
                                 */

/* ----------------------- HTTP Status Codes  ------------------------- */

@@ -580,6 +583,13 @@ struct request_rec {
    conn_rec *connection;
    server_rec *server;

    BUFF *input;                /* Where to get the data (usually a pipe
                                 * or a file currently). 
                                 */
    BUFF *output;               /* Where to send the data (usually, a pipe
                                 * or the socket currently).
                                 */

    request_rec *next;		/* If we wind up getting redirected,
				 * pointer to the request we redirected to.
				 */
+53 −8
Changes for modules/filters/mod_include.c: 53 added lines, 8 removed lines.
Original line number Diff line number Diff line
@@ -2364,20 +2364,30 @@ static const char *set_xbithack(cmd_parms *cmd, void *xbp, char *arg)
    return NULL;
}

static int send_parsed_file(request_rec *r)
struct {
    ap_thread_t *thread;
    request_rec *r;
} ssi_rec;

void * API_THREAD_FUNC sub_send_parsed_file(void *rec)
{
    ap_file_t *f = NULL;
    struct ssi_rec *dumb_rec = (struct ssi_rec *)rec;
    ap_thread_t *subthread = dumb_rec->thread
    request_rec *r = dumb_rec->r;
    enum xbithack *state =
    (enum xbithack *) ap_get_module_config(r->per_dir_config, &includes_module);
    int errstatus;
    request_rec *parent;

    if (!(ap_allow_options(r) & OPT_INCLUDES)) {
        return DECLINED;
        ap_thread_exit(0);
/*        return DECLINED;*/
    }
    r->allowed |= (1 << M_GET);
    if (r->method_number != M_GET) {
        return DECLINED;
        ap_thread_exit(0);
/*        return DECLINED;*/
    }
    if (r->finfo.protection == 0) {
        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
@@ -2385,7 +2395,8 @@ static int send_parsed_file(request_rec *r)
                    (r->path_info
                     ? ap_pstrcat(r->pool, r->filename, r->path_info, NULL)
                     : r->filename));
        return HTTP_NOT_FOUND;
        ap_thread_exit(0);
/*        return HTTP_NOT_FOUND;*/
    }

    errstatus = ap_open(&f, r->filename, APR_READ, 0, r->pool);
@@ -2393,7 +2404,8 @@ static int send_parsed_file(request_rec *r)
    if (errstatus != APR_SUCCESS) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, errstatus, r,
                    "file permissions deny server access: %s", r->filename);
        return HTTP_FORBIDDEN;
        ap_thread_exit(0);
/*        return HTTP_FORBIDDEN;*/
    }

    if ((*state == xbithack_full)
@@ -2406,14 +2418,16 @@ static int send_parsed_file(request_rec *r)
        ap_set_last_modified(r);
    }
    if ((errstatus = ap_meets_conditions(r)) != OK) {
        return errstatus;
        ap_thread_exit(0);
/*        return errstatus;*/
    }

    ap_send_http_header(r);

    if (r->header_only) {
        ap_close(f);
        return OK;
        ap_thread_exit(0);
/*        return OK;*/
    }

    if ((parent = ap_get_module_config(r->request_config, &includes_module))) {
@@ -2453,8 +2467,39 @@ static int send_parsed_file(request_rec *r)
	ap_set_module_config(r->request_config, &includes_module,
	    NESTED_INCLUDE_MAGIC);
    }
    ap_thread_exit(0);
/*    return OK;*/
}

    return OK;
int send_parsed_file(request_rec *r)
{
    struct ssi_rec dumb_rec;
    ap_thread_t *subthread = NULL;
    ap_file_t *pipein = NULL;
    ap_file_t *pipeout = NULL;
    ap_iol *iolin;
    ap_iol *iolout;
    BUFF *bpipeint = NULL;
    BUFF *bpipeout = NULL;

    ap_create_pipe(&pipein, &pipeout, r->pool);

    iolin = ap_create_file_iol(pipein);
    ap_bpush_iol(bpipein, iolin);

    iolout = ap_create_file_iol(pipeout);
    ap_bpush_iol(bpipeout, iolout);
    r->output = bpipeout;

    ap_setup_input(r);

    dumb_rec->thread = subthread;
    dumb_rec->r = r;
    ap_create_thread(&subthread, NULL, sub_send_parsed_file, dumb_rec, r->pool);
    r->input = bpipein;
        

    return RERUN_HANDLERS;
}

static int send_shtml_file(request_rec *r)
+11 −7
Changes for modules/generators/mod_cgi.c: 11 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -621,7 +621,9 @@ static int cgi_handler(request_rec *r)
	    ap_table_unset(r->headers_in, "Content-Length");

	    ap_internal_redirect_handler(location, r);
	    return OK;
/*            r->content_type = NULL;*/
            r->handler = NULL;
	    return RERUN_HANDLERS;
	}
	else if (location && r->status == 200) {
	    /* XX Note that if a script wants to produce its own Redirect
@@ -630,12 +632,12 @@ static int cgi_handler(request_rec *r)
	    return REDIRECT;
	}

	ap_send_http_header(r);
/*	ap_send_http_header(r);*/
	if (!r->header_only) {
	    ap_send_fb(script_in, r);
            r->input = script_in;
	}
	ap_bclose(script_in);

/*	ap_bclose(script_in);
*/
	while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
	    continue;
	}
@@ -643,10 +645,12 @@ static int cgi_handler(request_rec *r)
    }

    if (script_in && nph) {
	ap_send_fb(script_in, r);
        r->input = script_in;
    }

    return OK;			/* NOT r->status, even if it has changed. */
/*    r->content_type = NULL;*/
    r->handler = NULL;
    return RERUN_HANDLERS;	/* NOT r->status, even if it has changed. */
}

static const handler_rec cgi_handlers[] =
+6 −4
Changes for modules/http/http_core.c: 6 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -2530,12 +2530,15 @@ static int default_handler(request_rec *r)
    if (r->method_number != M_GET) {
        return METHOD_NOT_ALLOWED;
    }
	
/*	
    if ((status = ap_open(&fd, r->filename, APR_READ | APR_BINARY, 0, r->pool)) != APR_SUCCESS) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
		     "file permissions deny server access: %s", r->filename);
        return FORBIDDEN;
    }
    }*/

    ap_setup_input(r);

    ap_update_mtime(r, r->finfo.mtime);
    ap_set_last_modified(r);
    ap_set_etag(r);
@@ -2583,7 +2586,7 @@ static int default_handler(request_rec *r)
	
	if (!r->header_only) {
	    if (!rangestatus) {
		ap_send_fd(fd, r);
		ap_send_fb(r->input, r);
	    }
	    else {
		long     length;
@@ -2634,7 +2637,6 @@ static int default_handler(request_rec *r)
    }
#endif

    ap_close(fd);
    return OK;
}

+72 −35
Changes for modules/http/http_protocol.c: 72 added lines, 35 removed lines.
Original line number Diff line number Diff line
@@ -959,6 +959,30 @@ static void get_mime_headers(request_rec *r)
    ap_overlap_tables(r->headers_in, tmp_headers, AP_OVERLAP_TABLES_MERGE);
}

ap_status_t ap_setup_input(request_rec *r)
{
    BUFF *temp = NULL;
    ap_iol *iol;
    ap_file_t *fd = NULL;
    ap_status_t status;

    if (!r->input) {
        if ((status = ap_open(&fd, r->filename, APR_READ | APR_BINARY, 0, r->pool)) != APR_SUCCESS) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
                         "file permissions deny server access: %s", r->filename);
            return status;
        }

        iol = ap_create_file_iol(fd);
        if (!iol)
            return APR_EBADF;
        temp = ap_bcreate(r->pool, B_RD);
        ap_bpush_iol(temp, iol);   
        r->input = temp;
    }
    return APR_SUCCESS;
}

request_rec *ap_read_request(conn_rec *conn)
{
    request_rec *r;
@@ -1860,10 +1884,13 @@ API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz)
    long chunk_start = 0;
    unsigned long max_body;
    ap_status_t rv;
    BUFF *used_buff;

    used_buff = r->input ? r->input : r->connection->client;

    if (!r->read_chunked) {     /* Content-length read */
        len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
        rv = ap_bread(r->connection->client, buffer, len_to_read, &len_read);
        rv = ap_bread(used_buff, buffer, len_to_read, &len_read);
        if (len_read == 0) {    /* error or eof */
            if (rv != APR_SUCCESS) {
                r->connection->keepalive = -1;
@@ -1902,7 +1929,7 @@ API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz)

    if (r->remaining == 0) {    /* Start of new chunk */

        chunk_start = getline(buffer, bufsiz, r->connection->client, 0);
        chunk_start = getline(buffer, bufsiz, used_buff, 0);
        if ((chunk_start <= 0) || (chunk_start >= (bufsiz - 1))
            || !ap_isxdigit(*buffer)) {
            r->connection->keepalive = -1;
@@ -1943,7 +1970,7 @@ API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz)
        len_read = chunk_start;

        while ((bufsiz > 1) && ((len_read =
                  getline(buffer, bufsiz, r->connection->client, 1)) > 0)) {
                  getline(buffer, bufsiz, used_buff, 1)) > 0)) {

            if (len_read != (bufsiz - 1)) {
                buffer[len_read++] = CR;        /* Restore footer line end  */
@@ -1977,7 +2004,7 @@ API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz)

    len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;

    (void) ap_bread(r->connection->client, buffer, len_to_read, &len_read);
    (void) ap_bread(used_buff, buffer, len_to_read, &len_read);
    if (len_read == 0) {        /* error or eof */
        r->connection->keepalive = -1;
        return -1;
@@ -1986,8 +2013,8 @@ API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz)
    r->remaining -= len_read;

    if (r->remaining == 0) {    /* End of chunk, get trailing CRLF */
        if ((c = ap_bgetc(r->connection->client)) == CR) {
            c = ap_bgetc(r->connection->client);
        if ((c = ap_bgetc(used_buff)) == CR) {
            c = ap_bgetc(used_buff);
        }
        if (c != LF) {
            r->connection->keepalive = -1;
@@ -2050,16 +2077,17 @@ API_EXPORT(int) ap_discard_request_body(request_rec *r)
 */
API_EXPORT(long) ap_send_fd(ap_file_t *fd, request_rec *r)
{
    BUFF *used_buff = r->output ? r->output : r->connection->client;
    long len = r->finfo.size;
#ifdef HAVE_SENDFILE
    if (!r->chunked) {
	ap_status_t rv;
        ap_bsetopt(r->connection->client, BO_TIMEOUT,
        ap_bsetopt(used_buff, BO_TIMEOUT,
                   r->connection->keptalive
                   ? &r->server->keep_alive_timeout
                   : &r->server->timeout);
        ap_bflush(r->connection->client);
        rv = iol_sendfile(r->connection->client->iol, 
        ap_bflush(used_buff);
        rv = iol_sendfile(used_buff->iol, 
                          fd,     /* The file to send */
                          NULL,   /* header and trailer iovecs */
                          0,      /* Offset in file to begin sending from */
@@ -2070,7 +2098,7 @@ API_EXPORT(long) ap_send_fd(ap_file_t *fd, request_rec *r)
                          "ap_send_fd: iol_sendfile failed.");
        }
        if (r->connection->keptalive) {
            ap_bsetopt(r->connection->client, BO_TIMEOUT, 
            ap_bsetopt(used_buff, BO_TIMEOUT, 
                       &r->server->timeout);
        }
    }
@@ -2091,6 +2119,7 @@ API_EXPORT(long) ap_send_fd_length(ap_file_t *fd, request_rec *r, long length)
    ap_ssize_t w;
    ap_ssize_t n;
    ap_status_t rv;
    BUFF *used_buff = r->output ? r->output : r->connection->client;

    if (length == 0)
        return 0;
@@ -2113,7 +2142,7 @@ API_EXPORT(long) ap_send_fd_length(ap_file_t *fd, request_rec *r, long length)
        o = 0;

        while (n && !ap_is_aborted(r->connection)) {
            rv = ap_bwrite(r->connection->client, &buf[o], n, &w);
            rv = ap_bwrite(used_buff, &buf[o], n, &w);
            if (w > 0) {
                total_bytes_sent += w;
                n -= w;
@@ -2123,7 +2152,7 @@ API_EXPORT(long) ap_send_fd_length(ap_file_t *fd, request_rec *r, long length)
                if (!ap_is_aborted(r->connection)) {
                    ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, r,
                     "client stopped connection before send body completed");
                    ap_bsetflag(r->connection->client, B_EOUT, 1);
                    ap_bsetflag(used_buff, B_EOUT, 1);
                    r->connection->aborted = 1;
                }
                break;
@@ -2152,6 +2181,7 @@ API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length)
    ap_ssize_t w;
    ap_ssize_t n;
    ap_status_t rv;
    BUFF *used_buff = r->output ? r->output : r->connection->client;

    if (length == 0) {
        return 0;
@@ -2193,7 +2223,7 @@ API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length)
        
        o = 0;
        while (n && !ap_is_aborted(r->connection)) {
            rv = ap_bwrite(r->connection->client, &buf[o], n, &w);
            rv = ap_bwrite(used_buff, &buf[o], n, &w);
            if (w > 0) {
                total_bytes_sent += w;
                n -= w;
@@ -2203,7 +2233,7 @@ API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length)
                if (!ap_is_aborted(r->connection)) {
                    ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, r,
                        "client stopped connection before rflush completed");
                    ap_bsetflag(r->connection->client, B_EOUT, 1);
                    ap_bsetflag(used_buff, B_EOUT, 1);
                    r->connection->aborted = 1;
                }
                break;
@@ -2238,6 +2268,7 @@ API_EXPORT(size_t) ap_send_mmap(ap_mmap_t *mm, request_rec *r, size_t offset,
    ap_ssize_t w;
    ap_status_t rv;
    char *addr;
    BUFF *used_buff = r->output ? r->output : r->connection->client;
    
    if (length == 0)
        return 0;
@@ -2254,7 +2285,7 @@ API_EXPORT(size_t) ap_send_mmap(ap_mmap_t *mm, request_rec *r, size_t offset,

        while (n && !r->connection->aborted) {
            ap_mmap_offset((void**)&addr, mm, offset);
            rv = ap_bwrite(r->connection->client, addr, n, &w);
            rv = ap_bwrite(used_buff, addr, n, &w);
            if (w > 0) {
                total_bytes_sent += w;
                n -= w;
@@ -2268,7 +2299,7 @@ API_EXPORT(size_t) ap_send_mmap(ap_mmap_t *mm, request_rec *r, size_t offset,
                else {
                    ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, r,
                     "client stopped connection before send mmap completed");
                    ap_bsetflag(r->connection->client, B_EOUT, 1);
                    ap_bsetflag(used_buff, B_EOUT, 1);
                    r->connection->aborted = 1;
                    break;
                }
@@ -2283,15 +2314,16 @@ API_EXPORT(size_t) ap_send_mmap(ap_mmap_t *mm, request_rec *r, size_t offset,

API_EXPORT(int) ap_rputc(int c, request_rec *r)
{
    BUFF *used_buff = r->output ? r->output : r->connection->client;
    if (r->connection->aborted)
        return EOF;

    if (ap_bputc(c, r->connection->client) < 0) {
    if (ap_bputc(c, used_buff) < 0) {
        if (!r->connection->aborted) {
            ap_log_rerror(APLOG_MARK, APLOG_INFO,
                ap_berror(r->connection->client), r,
                ap_berror(used_buff), r,
                "client stopped connection before rputc completed");
            ap_bsetflag(r->connection->client, B_EOUT, 1);
            ap_bsetflag(used_buff, B_EOUT, 1);
            r->connection->aborted = 1;
        }
        return EOF;
@@ -2303,17 +2335,18 @@ API_EXPORT(int) ap_rputc(int c, request_rec *r)
API_EXPORT(int) ap_rputs(const char *str, request_rec *r)
{
    int rcode;
    BUFF *used_buff = r->output ? r->output : r->connection->client; 

    if (r->connection->aborted)
        return EOF;
    
    rcode = ap_bputs(str, r->connection->client);
    rcode = ap_bputs(str, used_buff);
    if (rcode < 0) {
        if (!r->connection->aborted) {
            ap_log_rerror(APLOG_MARK, APLOG_INFO,
                ap_berror(r->connection->client), r,
                ap_berror(used_buff), r,
                "client stopped connection before rputs completed");
            ap_bsetflag(r->connection->client, B_EOUT, 1);
            ap_bsetflag(used_buff, B_EOUT, 1);
            r->connection->aborted = 1;
        }
        return EOF;
@@ -2326,16 +2359,17 @@ API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
{
    ap_ssize_t n;
    ap_status_t rv;
    BUFF *used_buff = r->output ? r->output : r->connection->client; 

    if (r->connection->aborted)
        return EOF;

    rv = ap_bwrite(r->connection->client, buf, nbyte, &n);
    rv = ap_bwrite(used_buff, buf, nbyte, &n);
    if (n < 0) {
        if (!r->connection->aborted) {
            ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, r,
                "client stopped connection before rwrite completed");
            ap_bsetflag(r->connection->client, B_EOUT, 1);
            ap_bsetflag(used_buff, B_EOUT, 1);
            r->connection->aborted = 1;
        }
        return EOF;
@@ -2347,18 +2381,19 @@ API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
API_EXPORT(int) ap_vrprintf(request_rec *r, const char *fmt, va_list ap)
{
    int n;
    BUFF *used_buff = r->output ? r->output : r->connection->client; 

    if (r->connection->aborted)
        return -1;

    n = ap_vbprintf(r->connection->client, fmt, ap);
    n = ap_vbprintf(used_buff, fmt, ap);

    if (n < 0) {
        if (!r->connection->aborted) {
            ap_log_rerror(APLOG_MARK, APLOG_INFO,
                ap_berror(r->connection->client), r,
                ap_berror(used_buff), r,
                "client stopped connection before vrprintf completed");
            ap_bsetflag(r->connection->client, B_EOUT, 1);
            ap_bsetflag(used_buff, B_EOUT, 1);
            r->connection->aborted = 1;
        }
        return -1;
@@ -2371,20 +2406,21 @@ API_EXPORT(int) ap_rprintf(request_rec *r, const char *fmt,...)
{
    va_list vlist;
    int n;
    BUFF *used_buff = r->output ? r->output : r->connection->client; 

    if (r->connection->aborted)
        return -1;

    va_start(vlist, fmt);
    n = ap_vbprintf(r->connection->client, fmt, vlist);
    n = ap_vbprintf(used_buff, fmt, vlist);
    va_end(vlist);

    if (n < 0) {
        if (!r->connection->aborted) {
            ap_log_rerror(APLOG_MARK, APLOG_INFO,
                ap_berror(r->connection->client), r,
                ap_berror(used_buff), r,
                "client stopped connection before rprintf completed");
            ap_bsetflag(r->connection->client, B_EOUT, 1);
            ap_bsetflag(used_buff, B_EOUT, 1);
            r->connection->aborted = 1;
        }
        return -1;
@@ -2399,7 +2435,7 @@ API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...)
    ap_ssize_t i;
    int j, k;
    const char *x;
    BUFF *fb = r->connection->client;
    BUFF *used_buff = r->output ? r->output : r->connection->client; 
    ap_status_t rv;

    if (r->connection->aborted)
@@ -2411,13 +2447,13 @@ API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...)
        if (x == NULL)
            break;
        j = strlen(x);
        rv = ap_bwrite(fb, x, j, &i);
        rv = ap_bwrite(used_buff, x, j, &i);
        if (i != j) {
            va_end(args);
            if (!r->connection->aborted) {
                ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, r,
                    "client stopped connection before rvputs completed");
                ap_bsetflag(r->connection->client, B_EOUT, 1);
                ap_bsetflag(used_buff, B_EOUT, 1);
                r->connection->aborted = 1;
            }
            return EOF;
@@ -2433,12 +2469,13 @@ API_EXPORT_NONSTD(int) ap_rvputs(request_rec *r,...)
API_EXPORT(int) ap_rflush(request_rec *r)
{
    ap_status_t rv;
    BUFF *used_buff = r->output ? r->output : r->connection->client; 

    if ((rv = ap_bflush(r->connection->client)) != APR_SUCCESS) {
    if ((rv = ap_bflush(used_buff)) != APR_SUCCESS) {
        if (!ap_is_aborted(r->connection)) {
            ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, r,
                "client stopped connection before rflush completed");
            ap_bsetflag(r->connection->client, B_EOUT, 1);
            ap_bsetflag(used_buff, B_EOUT, 1);
            r->connection->aborted = 1;
        }
        return EOF;
Loading