]> granicus.if.org Git - apache/commitdiff
Add the AsyncFilter directive that allows the asynchronous filter
authorGraham Leggett <minfrin@apache.org>
Tue, 6 Oct 2015 22:33:03 +0000 (22:33 +0000)
committerGraham Leggett <minfrin@apache.org>
Tue, 6 Oct 2015 22:33:03 +0000 (22:33 +0000)
functionality to be switched off for certain classes of filters.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1707161 13f79535-47bb-0310-9956-ffa450edef68

docs/manual/mod/core.xml
include/ap_mmn.h
include/http_core.h
include/httpd.h
server/core.c
server/request.c
server/util_filter.c

index e4974c86bc7d4b0aab40d178d54cb11f57ebd0e5..effedee540b309e776cacfb3ec688a542ab531fc 100644 (file)
@@ -551,6 +551,32 @@ AllowOverrideList CookieTracking CookieName
 <seealso><a href="../howto/htaccess.html">.htaccess Files</a></seealso>
 </directivesynopsis>
 
+<directivesynopsis>
+    <name>AsyncFilter</name>
+    <description>Set the minimum filter type eligible for asynchronous handling</description>
+    <syntax>AsyncFilter request|connection|network</syntax>
+    <default>AsyncFilter request</default>
+    <contextlist><context>server config</context><context>virtual host</context></contextlist>
+    <compatibility>Only available from Apache 2.5.0 and later.</compatibility>
+
+    <usage>
+        <p>This directive controls the minimum filter levels that are eligible
+        for asynchronous handling. This may be necessary to support legacy external
+        filters that did not handle meta buckets correctly.</p>
+
+        <p>If set to "network", asynchronous handling will be limited to the network
+        filter only. If set to "connection", all connection and network filters
+        will be eligible for asynchronous handling, including <module>mod_ssl</module>.
+        If set to "request", all filters will be eligible for asynchronous handling.</p>
+        
+        <p>With <directive>ProtocolsHonorOrder</directive> set to <code>on</code> 
+            (default), the client ordering does not matter and only the ordering 
+            in the server settings influences the outcome of the protocol 
+            negotiation.</p>
+        
+    </usage>
+</directivesynopsis>
+
 <directivesynopsis>
 <name>CGIMapExtension</name>
 <description>Technique for locating the interpreter for CGI
index 631562e4afcc09cdeda2761d350e226812c54fcc..ea2e0f148f7eda70b41005fb74994e6c7e400626 100644 (file)
  *                         ap_filter_reinstate_brigade() and
  *                         ap_filter_should_yield(). Add empty and filters to
  *                         conn_rec.
+ * 20150222.6 (2.5.0-dev)  Add async_filter to conn_rec.
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20150222
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 5                 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 6                 /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index dbb310db8ed32503e016fb66d8a2c687ad9caba6..cbd4b81d1031c6d58cf23880213ff20b650a1eec 100644 (file)
@@ -711,6 +711,8 @@ typedef struct {
 
     apr_array_header_t *protocols;
     int protocols_honor_order;
+    int async_filter;
+    int async_filter_set:1;
 } core_server_config;
 
 /* for AddOutputFiltersByType in core.c */
index d36ed10a02aa3ab246a0fbdfa2707421811d8e92..91cd45a86a37d60be22c6872ff1ec36298d57521 100644 (file)
@@ -1198,6 +1198,9 @@ struct conn_rec {
 
     /** Hashtable of filters with setaside buckets for write completion */
     apr_hash_t *filters;
+
+    /** The minimum level of filter type to allow setaside buckets */
+    int async_filter;
 };
 
 struct conn_slave_rec {
index de3fa23f917b1f27ff3d58ef3c4d552812cd5bf0..d340d5e3defbb602c04b5682a8a5b22d26a411f2 100644 (file)
@@ -481,7 +481,8 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s)
 
     conf->protocols = apr_array_make(a, 5, sizeof(const char *));
     conf->protocols_honor_order = -1;
-    
+    conf->async_filter = 0;
+
     return (void *)conf;
 }
 
@@ -555,12 +556,16 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
                            ? virt->merge_trailers
                            : base->merge_trailers;
 
-    conf->protocols = ((virt->protocols->nelts > 0)
+    conf->protocols = ((virt->protocols->nelts > 0) ?
                        virt->protocols : base->protocols);
-    conf->protocols_honor_order = ((virt->protocols_honor_order < 0)?
+    conf->protocols_honor_order = ((virt->protocols_honor_order < 0) ?
                                        base->protocols_honor_order :
                                        virt->protocols_honor_order);
-    
+    conf->async_filter = ((virt->async_filter_set) ?
+                                       virt->async_filter :
+                                       base->async_filter);
+    conf->async_filter_set = base->async_filter_set || virt->async_filter_set;
+
     return conf;
 }
 
@@ -3887,6 +3892,34 @@ static const char *set_http_protocol(cmd_parms *cmd, void *dummy,
     return NULL;
 }
 
+static const char *set_async_filter(cmd_parms *cmd, void *dummy,
+                                             const char *arg)
+{
+    core_server_config *conf =
+    ap_get_core_module_config(cmd->server->module_config);
+    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE);
+
+    if (err) {
+        return err;
+    }
+
+    if (strcasecmp(arg, "network") == 0) {
+        conf->async_filter = AP_FTYPE_NETWORK;
+    }
+    else if (strcasecmp(arg, "connection") == 0) {
+        conf->async_filter = AP_FTYPE_CONNECTION;
+    }
+    else if (strcasecmp(arg, "request") == 0) {
+        conf->async_filter = 0;
+    }
+    else {
+        return "AsyncFilter must be 'network', 'connection' or 'request'";
+    }
+    conf->async_filter_set = 1;
+
+    return NULL;
+}
+
 static const char *set_http_method(cmd_parms *cmd, void *conf, const char *arg)
 {
     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
@@ -4502,6 +4535,9 @@ AP_INIT_ITERATE("Protocols", set_protocols, NULL, RSRC_CONF,
 AP_INIT_TAKE1("ProtocolsHonorOrder", set_protocols_honor_order, NULL, RSRC_CONF,
               "'off' (default) or 'on' to respect given order of protocols, "
               "by default the client specified order determines selection"),
+AP_INIT_TAKE1("AsyncFilter", set_async_filter, NULL, RSRC_CONF,
+              "'network', 'connection' (default) or 'request' to limit the "
+              "types of filters that support asynchronous handling"),
 { NULL }
 };
 
@@ -5010,6 +5046,7 @@ static conn_rec *core_create_conn(apr_pool_t *ptrans, server_rec *s,
     c->bucket_alloc = alloc;
     c->empty = apr_brigade_create(c->pool, c->bucket_alloc);
     c->filters = apr_hash_make(c->pool);
+    c->async_filter = sconf->async_filter;
 
     c->clogging_input_filters = 0;
 
index 9c9ad9f93b8ed7c36034a9d52b634faf34c5eeb0..abf084e31aaceea9c071ff63c5e477cc47b41b30 100644 (file)
@@ -2043,6 +2043,15 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_request_core_filter(ap_filter_t *f,
     apr_status_t status = APR_SUCCESS;
     apr_bucket_brigade *tmp_bb = f->ctx;
 
+    /*
+     * Handle the AsyncFilter directive. We limit the filters that are
+     * eligible for asynchronous handling here.
+     */
+    if (f->frec->ftype < f->c->async_filter) {
+        ap_remove_output_filter(f);
+        return ap_pass_brigade(f->next, bb);
+    }
+
     if (!tmp_bb) {
         tmp_bb = f->ctx = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
     }
index ad14112ddba3dfa984d97be8e20c15e34829f52e..949d13e0a8b7dafc5c26eeb1455e8d4e1a77ff1f 100644 (file)
@@ -893,6 +893,14 @@ AP_DECLARE(apr_status_t) ap_filter_reinstate_brigade(ap_filter_t *f,
 
 AP_DECLARE(int) ap_filter_should_yield(ap_filter_t *f)
 {
+    /*
+     * Handle the AsyncFilter directive. We limit the filters that are
+     * eligible for asynchronous handling here.
+     */
+    if (f->frec->ftype < f->c->async_filter) {
+        return 0;
+    }
+
     /*
      * This function decides whether a filter should yield due to buffered
      * data in a downstream filter. If a downstream filter buffers we