Commit 63147ac0 authored by Brian Pane's avatar Brian Pane
Browse files

Added ap_read_async_request()...

At the moment, asynchronous MPMs still read the request headers
with the connection in blocking mode.  To enable asynchronous
read completion, we'll need to make some changes in the Event MPM.



git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/async-read-dev@353904 13f79535-47bb-0310-9956-ffa450edef68
parent bb1762e4
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -61,6 +61,16 @@ AP_DECLARE_DATA extern ap_filter_rec_t *ap_old_write_func;
 */ 
request_rec *ap_read_request(conn_rec *c);

/**
 * Read part or all of a request and fill in the fields.
 * @param c The current connection
 * @return APR_SUCCESS if the request header is completely read,
 *         APR_EAGAIN if the caller should wait for readability on
 *         the connection and try again, arbirary other apr_status_t
 *         values if the read fails for any other reason
 */ 
apr_status_t ap_read_async_request(conn_rec *c);

/**
 * Read the mime-encoded headers.
 * @param r The current request
+3 −0
Original line number Diff line number Diff line
@@ -1078,6 +1078,9 @@ struct conn_rec {
    int data_in_input_filters;
    /** Is there data pending in the output filters? */
    int data_in_output_filters;
    /** The request (possibly incomplete) currently being processed
     *  on this connection, or NULL if not applicable */
    request_rec *request;
};

/** 
+24 −29
Original line number Diff line number Diff line
@@ -108,31 +108,22 @@ static apr_port_t http_port(const request_rec *r)

static int ap_process_http_async_connection(conn_rec *c)
{
    request_rec *r;
    apr_status_t rv;
    conn_state_t *cs = c->cs;

    AP_DEBUG_ASSERT(cs->state == CONN_STATE_READ_REQUEST_LINE);

    while (cs->state == CONN_STATE_READ_REQUEST_LINE) {
    ap_update_child_status(c->sbh, SERVER_BUSY_READ, NULL);

        if ((r = ap_read_request(c))) {

    rv = ap_read_async_request(c);
    if (rv == APR_SUCCESS) {
        c->keepalive = AP_CONN_UNKNOWN;
        /* process the request if it was read without error */

            ap_update_child_status(c->sbh, SERVER_BUSY_WRITE, r);
            if (r->status == HTTP_OK) {
        ap_update_child_status(c->sbh, SERVER_BUSY_WRITE, c->request);
        if (c->request->status == HTTP_OK) {
            cs->state = CONN_STATE_HANDLER;
                ap_process_async_request(r);
                /* After the call to ap_process_request, the
                 * request pool may have been deleted.  We set
                 * r=NULL here to ensure that any dereference
                 * of r that might be added later in this function
                 * will result in a segfault immediately instead
                 * of nondeterministic failures later.
                 */
                r = NULL;
            ap_process_async_request(c->request);
            c->request = NULL;
        }

        if (cs->state != CONN_STATE_WRITE_COMPLETION) {
@@ -140,10 +131,13 @@ static int ap_process_http_async_connection(conn_rec *c)
            cs->state = CONN_STATE_LINGER;
        }
    }
        else {   /* ap_read_request failed - client may have closed */
    else if (!APR_STATUS_IS_EAGAIN(rv)) {
        /* EAGAIN means that we've successfully read a partial request
         * header, which is valid in an async server.  For any other error,
         * close the connection.
         */
        cs->state = CONN_STATE_LINGER;
    }
    }

    return OK;
}
@@ -164,11 +158,12 @@ static int ap_process_http_connection(conn_rec *c)

        c->keepalive = AP_CONN_UNKNOWN;
        /* process the request if it was read without error */

        c->request = r;
        ap_update_child_status(c->sbh, SERVER_BUSY_WRITE, r);
        if (r->status == HTTP_OK) {
            cs->state = CONN_STATE_HANDLER;
            ap_process_request(r);
            c->request = NULL;
            /* After the call to ap_process_request, the
             * request pool will have been deleted.  We set
             * r=NULL here to ensure that any dereference
+49 −1
Original line number Diff line number Diff line
@@ -1002,6 +1002,55 @@ static apr_status_t read_partial_request(request_rec *r) {
    return rv;
}

AP_DECLARE(apr_status_t) ap_read_async_request(conn_rec *conn)
{
    apr_status_t rv;
    request_rec *r;

    if (conn->request == NULL) {
        conn->request = init_request(conn);
        if (conn->request == NULL) {
            return APR_EGENERAL;
        }
    }

    r = conn->request;
    rv = read_partial_request(r);
    if (APR_STATUS_IS_EAGAIN(rv)) {
        return APR_EAGAIN;
    }
    if (r->status != HTTP_OK) {
        ap_send_error_response(r, 0);
        ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
        ap_run_log_transaction(r);
        return APR_EGENERAL;
    }

    if (r->assbackwards && r->header_only) {
        /*
         * Client asked for headers only with HTTP/0.9, which doesn't send
         * headers! Have to dink things just to make sure the error message
         * comes through...
         */
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                      "client sent invalid HTTP/0.9 request: HEAD %s",
                      r->uri);
        r->header_only = 0;
        r->status = HTTP_BAD_REQUEST;
        ap_send_error_response(r, 0);
        ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
        ap_run_log_transaction(r);
        return APR_EGENERAL;
    }

    if (request_post_read(r, conn) == NULL) {
        return APR_EGENERAL;
    }
    else {
        return APR_SUCCESS;
    }
}

request_rec *ap_read_request(conn_rec *conn)
{
    request_rec *r;
@@ -1010,7 +1059,6 @@ request_rec *ap_read_request(conn_rec *conn)
    r = init_request(conn);

    rv = read_partial_request(r);
    /* TODO poll if EAGAIN */
    if (r->status != HTTP_OK) {
        ap_send_error_response(r, 0);
        ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);