]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Added ap_read_async_request()...
authorBrian Pane <brianp@apache.org>
Sun, 4 Dec 2005 20:38:25 +0000 (20:38 +0000)
committerBrian Pane <brianp@apache.org>
Sun, 4 Dec 2005 20:38:25 +0000 (20:38 +0000)
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

include/http_protocol.h
include/httpd.h
modules/http/http_core.c
server/protocol.c

index c2c933e8588e668af4f741e6865812a2b0c1b1b6..9c2bb1b35c152eff3cb928d37d358d37168a2b93 100644 (file)
@@ -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
index ef488238e1c7cf75e9e573aa75b096284dbfdb4c..65468874fc7b048ad77e06fd7df3ad6e8587f22e 100644 (file)
@@ -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;
 };
 
 /** 
index 14d8a1b598b8b1198d33ffa3b8682ea2b015a99b..fe291c85f782e13ee6abab4ef56549c579ee52b6 100644 (file)
@@ -108,42 +108,36 @@ 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))) {
-
-            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) {
-                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;
-            }
-
-            if (cs->state != CONN_STATE_WRITE_COMPLETION) {
-                /* Something went wrong; close the connection */
-                cs->state = CONN_STATE_LINGER;
-            }
+    ap_update_child_status(c->sbh, SERVER_BUSY_READ, NULL);
+
+    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, c->request);
+        if (c->request->status == HTTP_OK) {
+            cs->state = CONN_STATE_HANDLER;
+            ap_process_async_request(c->request);
+            c->request = NULL;
         }
-        else {   /* ap_read_request failed - client may have closed */
+
+        if (cs->state != CONN_STATE_WRITE_COMPLETION) {
+            /* Something went wrong; close the connection */
             cs->state = CONN_STATE_LINGER;
         }
     }
+    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
index 8425678ad90373c39ca5156f8b919e47bb46d635..0e741bbf8498768479a5cabbbb52c5af0bf9592f 100644 (file)
@@ -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);