You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ic...@apache.org on 2015/12/14 14:02:50 UTC

svn commit: r1719901 - in /httpd/httpd/trunk/modules/http2: h2_conn.c h2_conn.h h2_ctx.c h2_ctx.h h2_h2.c h2_session.c h2_switch.c h2_worker.c

Author: icing
Date: Mon Dec 14 13:02:50 2015
New Revision: 1719901

URL: http://svn.apache.org/viewvc?rev=1719901&view=rev
Log:
internal rewiring to prepare for return from connection processing frequently before session end

Modified:
    httpd/httpd/trunk/modules/http2/h2_conn.c
    httpd/httpd/trunk/modules/http2/h2_conn.h
    httpd/httpd/trunk/modules/http2/h2_ctx.c
    httpd/httpd/trunk/modules/http2/h2_ctx.h
    httpd/httpd/trunk/modules/http2/h2_h2.c
    httpd/httpd/trunk/modules/http2/h2_session.c
    httpd/httpd/trunk/modules/http2/h2_switch.c
    httpd/httpd/trunk/modules/http2/h2_worker.c

Modified: httpd/httpd/trunk/modules/http2/h2_conn.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_conn.c?rev=1719901&r1=1719900&r2=1719901&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_conn.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_conn.c Mon Dec 14 13:02:50 2015
@@ -126,12 +126,10 @@ static module *h2_conn_mpm_module(void)
     return mpm_module;
 }
 
-apr_status_t h2_conn_process(conn_rec *c, request_rec *r, server_rec *s)
+apr_status_t h2_conn_setup(h2_ctx *ctx, conn_rec *c, request_rec *r)
 {
-    apr_status_t status;
     h2_session *session;
     const h2_config *config;
-    int rv;
     
     if (!workers) {
         ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02911) 
@@ -139,28 +137,34 @@ apr_status_t h2_conn_process(conn_rec *c
         return APR_EGENERAL;
     }
     
-    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "h2_conn_process start");
-    
-    if (!s && r) {
-        s = r->server;
-    }
-    
-    config = s? h2_config_sget(s) : h2_config_get(c);
+    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "h2_conn_setup");
+    config = h2_config_sget(h2_ctx_server_get(ctx));
     if (r) {
         session = h2_session_rcreate(r, config, workers);
     }
     else {
         session = h2_session_create(c, config, workers);
     }
+
+    h2_ctx_session_set(ctx, session);
+    return APR_SUCCESS;
+}
+
+apr_status_t h2_conn_process(h2_ctx *ctx)
+{
+    apr_status_t status;
+    h2_session *session;
+    conn_rec *c;
+    int rv;
+    
+    session = h2_ctx_session_get(ctx);
+    c = session->c;
     
     if (!h2_is_acceptable_connection(c, 1)) {
         nghttp2_submit_goaway(session->ngh2, NGHTTP2_FLAG_NONE, 0,
                               NGHTTP2_INADEQUATE_SECURITY, NULL, 0);
     } 
 
-    /* What do install instead? */
-    ap_remove_input_filter_byhandle(c->input_filters, "reqtimeout");
-    
     ap_update_child_status_from_conn(c->sbh, SERVER_BUSY_READ, c);
     status = h2_session_start(session, &rv);
     
@@ -176,20 +180,34 @@ apr_status_t h2_conn_process(conn_rec *c
     
     status = h2_session_process(session);
 
-    ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, session->c,
-                  "h2_session(%ld): done", session->id);
-    /* Make sure this connection gets closed properly. */
-    ap_update_child_status_from_conn(c->sbh, SERVER_CLOSING, c);
-    c->keepalive = AP_CONN_CLOSE;
-    if (c->cs) {
-        c->cs->state = CONN_STATE_WRITE_COMPLETION;
+    if (status == APR_EOF) {
+        ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, session->c,
+                      "h2_session(%ld): done", session->id);
+        /* Make sure this connection gets closed properly. */
+        ap_update_child_status_from_conn(c->sbh, SERVER_CLOSING, c);
+        c->keepalive = AP_CONN_CLOSE;
+        if (c->cs) {
+            c->cs->state = CONN_STATE_WRITE_COMPLETION;
+        }
+        
+        h2_session_close(session);
+        /* hereafter session will be gone */
     }
-
-    h2_session_close(session);
-    /* hereafter session will be gone */
+    
     return status;
 }
 
+apr_status_t h2_conn_run(struct h2_ctx *ctx)
+{
+    apr_status_t status;
+    
+    do {
+        status = h2_conn_process(ctx);
+    } while (status == APR_SUCCESS);
+    
+    return (status == APR_EOF)? APR_SUCCESS : status;
+}
+
 
 static void fix_event_conn(conn_rec *c, conn_rec *master);
 
@@ -220,8 +238,8 @@ conn_rec *h2_conn_create(conn_rec *maste
     return c;
 }
 
-apr_status_t h2_conn_setup(h2_task *task, apr_bucket_alloc_t *bucket_alloc,
-                           apr_thread_t *thread, apr_socket_t *socket)
+apr_status_t h2_slave_setup(h2_task *task, apr_bucket_alloc_t *bucket_alloc,
+                            apr_thread_t *thread, apr_socket_t *socket)
 {
     conn_rec *master = task->mplx->c;
     

Modified: httpd/httpd/trunk/modules/http2/h2_conn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_conn.h?rev=1719901&r1=1719900&r2=1719901&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_conn.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_conn.h Mon Dec 14 13:02:50 2015
@@ -16,18 +16,36 @@
 #ifndef __mod_h2__h2_conn__
 #define __mod_h2__h2_conn__
 
+struct h2_ctx;
 struct h2_task;
 
 /**
- * Process the connection that is now starting the HTTP/2
- * conversation. Return when the HTTP/2 session is done
- * and the connection will close.
+ * Setup the connection and our context for HTTP/2 processing
  *
+ * @param ctx the http2 context to setup
  * @param c the connection HTTP/2 is starting on
  * @param r the upgrade request that still awaits an answer, optional
- * @param s the server selected by request or, if NULL, connection
  */
-apr_status_t h2_conn_process(conn_rec *c, request_rec *r, server_rec *s);
+apr_status_t h2_conn_setup(struct h2_ctx *ctx, conn_rec *c, request_rec *r);
+
+/**
+ * Process the HTTP/2 connection. Return whenever blocking reads or
+ * long writes have to be performed.
+ *
+ * @param ctx the http2 context to process
+ * @return APR_SUCCESS as long as processing needs to continue, APR_EOF
+ *         when HTTP/2 session is done.
+ */
+apr_status_t h2_conn_process(struct h2_ctx *ctx);
+
+/**
+ * Run the HTTP/2 connection. Return when the HTTP/2 session is done
+ * and the connection will close or a fatal error occured.
+ *
+ * @param ctx the http2 context to run
+ * @return APR_SUCCESS when session is done.
+ */
+apr_status_t h2_conn_run(struct h2_ctx *ctx);
 
 /* Initialize this child process for h2 connection work,
  * to be called once during child init before multi processing
@@ -49,7 +67,7 @@ h2_mpm_type_t h2_conn_mpm_type(void);
 
 conn_rec *h2_conn_create(conn_rec *master, apr_pool_t *stream_pool);
 
-apr_status_t h2_conn_setup(struct h2_task *task, apr_bucket_alloc_t *bucket_alloc,
-                           apr_thread_t *thread, apr_socket_t *socket);
+apr_status_t h2_slave_setup(struct h2_task *task, apr_bucket_alloc_t *bucket_alloc,
+                            apr_thread_t *thread, apr_socket_t *socket);
 
 #endif /* defined(__mod_h2__h2_conn__) */

Modified: httpd/httpd/trunk/modules/http2/h2_ctx.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_ctx.c?rev=1719901&r1=1719900&r2=1719901&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_ctx.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_ctx.c Mon Dec 14 13:02:50 2015
@@ -30,6 +30,7 @@ static h2_ctx *h2_ctx_create(const conn_
     h2_ctx *ctx = apr_pcalloc(c->pool, sizeof(h2_ctx));
     AP_DEBUG_ASSERT(ctx);
     ap_set_module_config(c->conn_config, &http2_module, ctx);
+    h2_ctx_server_set(ctx, c->base_server);
     return ctx;
 }
 
@@ -78,6 +79,11 @@ void h2_ctx_session_set(h2_ctx *ctx, str
     ctx->session = session;
 }
 
+server_rec *h2_ctx_server_get(h2_ctx *ctx)
+{
+    return ctx? ctx->server : NULL;
+}
+
 h2_ctx *h2_ctx_server_set(h2_ctx *ctx, server_rec *s)
 {
     ctx->server = s;

Modified: httpd/httpd/trunk/modules/http2/h2_ctx.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_ctx.h?rev=1719901&r1=1719900&r2=1719901&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_ctx.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_ctx.h Mon Dec 14 13:02:50 2015
@@ -57,6 +57,7 @@ h2_ctx *h2_ctx_protocol_set(h2_ctx *ctx,
 /* Set the server_rec relevant for this context.
  */
 h2_ctx *h2_ctx_server_set(h2_ctx *ctx, server_rec *s);
+server_rec *h2_ctx_server_get(h2_ctx *ctx);
 
 struct h2_session *h2_ctx_session_get(h2_ctx *ctx);
 void h2_ctx_session_set(h2_ctx *ctx, struct h2_session *session);

Modified: httpd/httpd/trunk/modules/http2/h2_h2.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_h2.c?rev=1719901&r1=1719900&r2=1719901&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_h2.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_h2.c Mon Dec 14 13:02:50 2015
@@ -554,15 +554,19 @@ int h2_allows_h2_upgrade(conn_rec *c)
 /*******************************************************************************
  * Register various hooks
  */
-static const char* const mod_ssl[]        = {"mod_ssl.c", NULL};
+static const char* const mod_ssl[]        = { "mod_ssl.c", NULL};
+static const char* const mod_reqtimeout[] = { "mod_reqtimeout.c", NULL};
 
 void h2_h2_register_hooks(void)
 {
-    /* When the connection processing actually starts, we might to
-     * take over, if h2* was selected as protocol.
+    /* Our main processing needs to run quite late. Definitely after mod_ssl,
+     * as we need its connection filters, but also before reqtimeout as its
+     * method of timeouts is specific to HTTP/1.1 (as of now).
+     * The core HTTP/1 processing run as REALLY_LAST, so we will have
+     * a chance to take over before it.
      */
     ap_hook_process_connection(h2_h2_process_conn, 
-                               mod_ssl, NULL, APR_HOOK_MIDDLE);
+                               mod_ssl, mod_reqtimeout, APR_HOOK_LAST);
                                
     /* With "H2SerializeHeaders On", we install the filter in this hook
      * that parses the response. This needs to happen before any other post
@@ -574,6 +578,7 @@ void h2_h2_register_hooks(void)
 
 int h2_h2_process_conn(conn_rec* c)
 {
+    apr_status_t status;
     h2_ctx *ctx;
     
     if (c->master) {
@@ -586,19 +591,16 @@ int h2_h2_process_conn(conn_rec* c)
         /* our stream pseudo connection */
         return DECLINED;
     }
-
-    if (h2_ctx_protocol_get(c)) {
-        /* Something has been negotiated */
-    }
-    else if (!strcmp(AP_PROTOCOL_HTTP1, ap_get_protocol(c))
-             && h2_allows_h2_direct(c) 
-             && h2_is_acceptable_connection(c, 1)) {
-        /* connection still is on http/1.1 and H2Direct is enabled. 
+    
+    if (!ctx && c->keepalives == 0
+        && !strcmp(AP_PROTOCOL_HTTP1, ap_get_protocol(c))
+        && h2_allows_h2_direct(c) 
+        && h2_is_acceptable_connection(c, 1)) {
+        /* Fresh connection still is on http/1.1 and H2Direct is enabled. 
          * Otherwise connection is in a fully acceptable state.
          * -> peek at the first 24 incoming bytes
          */
         apr_bucket_brigade *temp;
-        apr_status_t status;
         char *s = NULL;
         apr_size_t slen;
         
@@ -630,19 +632,17 @@ int h2_h2_process_conn(conn_rec* c)
         
         apr_brigade_destroy(temp);
     }
-    else {
-        /* the connection is not HTTP/1.1 or not for us, don't touch it */
-        return DECLINED;
-    }
 
-    /* If "h2" was selected as protocol (by whatever mechanism), take over
-     * the connection.
-     */
     if (ctx) {
-        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
-                      "h2_h2, connection, h2 active");
-        
-        return h2_conn_process(c, NULL, ctx->server);
+        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "process_conn");
+        if (!h2_ctx_session_get(ctx)) {
+            status = h2_conn_setup(ctx, c, NULL);
+            if (status != APR_SUCCESS) {
+                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, c, "conn_setup");
+                return status;
+            }
+        }
+        return h2_conn_process(ctx);
     }
     
     ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c, "h2_h2, declined");

Modified: httpd/httpd/trunk/modules/http2/h2_session.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_session.c?rev=1719901&r1=1719900&r2=1719901&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_session.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_session.c Mon Dec 14 13:02:50 2015
@@ -1596,6 +1596,7 @@ apr_status_t h2_session_process(h2_sessi
                                           "h2_session: send: %s", nghttp2_strerror(rv));
                             if (nghttp2_is_fatal(rv)) {
                                 h2_session_abort(session, status, rv);
+                                status = APR_EGENERAL;
                                 goto end_process;
                             }
                         }
@@ -1622,6 +1623,7 @@ apr_status_t h2_session_process(h2_sessi
                               "h2_session: send: %s", nghttp2_strerror(rv));
                 if (nghttp2_is_fatal(rv)) {
                     h2_session_abort(session, status, rv);
+                    status = APR_EGENERAL;
                     goto end_process;
                 }
             }
@@ -1760,6 +1762,8 @@ apr_status_t h2_session_process(h2_sessi
             h2_conn_io_flush(&session->io);
         }
     }
+    /* normal end of session */
+    status = APR_EOF;
     
 end_process:
     return status;

Modified: httpd/httpd/trunk/modules/http2/h2_switch.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_switch.c?rev=1719901&r1=1719900&r2=1719901&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_switch.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_switch.c Mon Dec 14 13:02:50 2015
@@ -155,12 +155,15 @@ static int h2_protocol_switch(conn_rec *
             ap_remove_output_filter_byhandle(r->output_filters, "HTTP_HEADER");
             
             /* Ok, start an h2_conn on this one. */
-            status = h2_conn_process(r->connection, r, r->server);
-            if (status != DONE) {
-                /* Nothing really to do about this. */
+            h2_ctx_server_set(ctx, r->server);
+            status = h2_conn_setup(ctx, r->connection, r);
+            if (status != APR_SUCCESS) {
                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r,
-                              "session proessed, unexpected status");
+                              "session setup");
+                return status;
             }
+            
+            return h2_conn_run(ctx);
         }
         return DONE;
     }

Modified: httpd/httpd/trunk/modules/http2/h2_worker.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_worker.c?rev=1719901&r1=1719900&r2=1719901&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_worker.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_worker.c Mon Dec 14 13:02:50 2015
@@ -182,8 +182,8 @@ apr_status_t h2_worker_setup_task(h2_wor
     apr_status_t status;
     
     
-    status = h2_conn_setup(task, apr_bucket_alloc_create(task->pool),
-                           worker->thread, worker->socket);
+    status = h2_slave_setup(task, apr_bucket_alloc_create(task->pool),
+                            worker->thread, worker->socket);
     
     return status;
 }