summaryrefslogtreecommitdiff
path: root/server/util_filter.c
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2021-06-29 21:16:21 +0000
committerYann Ylavic <ylavic@apache.org>2021-06-29 21:16:21 +0000
commit891c3237d4dff0b0ff7a7226d7a39bbeb59087c1 (patch)
treed46fbd8aed4380d39229547389fcff32d5a216e1 /server/util_filter.c
parent90215f54520278e22a7e821c090a3c4649789ffd (diff)
downloadhttpd-891c3237d4dff0b0ff7a7226d7a39bbeb59087c1.tar.gz
core: Write Completion (WC) bucket type.
A WC bucket is meant to prevent buffering/coalescing filters from retaining data, but unlike a FLUSH bucket it won't cause the core output filter to block trying to flush anything before. It can be passed by async handlers which want to never block, followed by ap_filter_should_yield() to check for pending data and eventually suspend processing until MPM/asynchronous write completion finishes. In this commit it's used that way by the tunneling loop of mod_proxy to prevent SSL coaslescing. gh: closes #200 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1891148 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server/util_filter.c')
-rw-r--r--server/util_filter.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/server/util_filter.c b/server/util_filter.c
index e012265305..ff33bfde21 100644
--- a/server/util_filter.c
+++ b/server/util_filter.c
@@ -976,6 +976,12 @@ AP_DECLARE(apr_status_t) ap_filter_setaside_brigade(ap_filter_t *f,
e = next) {
next = APR_BUCKET_NEXT(e);
+ /* Strip WC buckets added by ap_filter_output_pending(). */
+ if (AP_BUCKET_IS_WC(e)) {
+ apr_bucket_delete(e);
+ continue;
+ }
+
/* Opaque buckets (length == -1) are moved, so assumed to have
* next EOR's lifetime or at least the lifetime of the connection.
*/
@@ -1268,7 +1274,10 @@ AP_DECLARE_NONSTD(int) ap_filter_output_pending(conn_rec *c)
if (!APR_BRIGADE_EMPTY(fp->bb)) {
ap_filter_t *f = fp->f;
apr_status_t rv;
+ apr_bucket *b;
+ b = ap_bucket_wc_create(bb->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, b);
rv = ap_pass_brigade(f, bb);
apr_brigade_cleanup(bb);
@@ -1279,8 +1288,7 @@ AP_DECLARE_NONSTD(int) ap_filter_output_pending(conn_rec *c)
break;
}
- if ((fp->bb && !APR_BRIGADE_EMPTY(fp->bb))
- || (f->next && ap_filter_should_yield(f->next))) {
+ if (ap_filter_should_yield(f)) {
rc = OK;
break;
}
@@ -1391,3 +1399,41 @@ AP_DECLARE(void) ap_filter_protocol(ap_filter_t *f, unsigned int flags)
{
f->frec->proto_flags = flags ;
}
+
+
+static apr_status_t wc_bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ *str = NULL;
+ *len = 0;
+ return APR_SUCCESS;
+}
+
+AP_DECLARE(apr_bucket *) ap_bucket_wc_make(apr_bucket *b)
+{
+ b->length = 0;
+ b->start = 0;
+ b->data = NULL;
+ b->type = &ap_bucket_type_wc;
+
+ return b;
+}
+
+AP_DECLARE(apr_bucket *) ap_bucket_wc_create(apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ return ap_bucket_wc_make(b);
+}
+
+AP_DECLARE_DATA const apr_bucket_type_t ap_bucket_type_wc = {
+ "WC", 5, APR_BUCKET_METADATA,
+ apr_bucket_destroy_noop,
+ wc_bucket_read,
+ apr_bucket_setaside_noop,
+ apr_bucket_split_notimpl,
+ apr_bucket_simple_copy
+};