From eb94b557ee33fceeee3358a165f13273ab8d8603 Mon Sep 17 00:00:00 2001 From: Ryan Bloom Date: Sun, 22 Apr 2001 22:19:32 +0000 Subject: [PATCH] At the hack-athon we decided to change the way that input filters determine how much data is returned to the previous filter. Prior to this change, we used a field in the conn_rec to determine how much to return. After this change, we use an argument to ap_get_brigade. This makes it much more obvious how things work at all levels, so that module authors can easily determine how much data is supposed to be returned to them. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@88912 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 6 ++++++ include/httpd.h | 5 +---- include/util_filter.h | 5 +++-- modules/experimental/mod_charset_lite.c | 6 +++--- modules/experimental/mod_ext_filter.c | 4 ++-- modules/http/http_protocol.c | 26 ++++++++++++------------- modules/http/http_request.c | 3 ++- modules/http/mod_core.h | 4 ++-- modules/tls/mod_tls.c | 8 ++++---- server/core.c | 2 +- server/protocol.c | 5 ++--- server/util_filter.c | 4 ++-- 12 files changed, 41 insertions(+), 37 deletions(-) diff --git a/CHANGES b/CHANGES index 6f780d4b35..e338adb78a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,10 @@ Changes with Apache 2.0.18-dev + + *) Change how input filters decide how much data is returned to the + higher filter. We used to use a field in the conn_rec, with this + change, we use an argument to ap_get_brigade to determine how much + data is retrieved. [Ryan Bloom] + *) Fix seg fault at start-up introduced by Ryan's change to enable modules to specify their own logging tags. mod_log_config registers an optional function, ap_register_log_handler(). diff --git a/include/httpd.h b/include/httpd.h index d1f00af5d8..27423fc17a 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -697,7 +697,7 @@ struct request_rec { apr_off_t clength; /** bytes left to read */ - long remaining; + apr_size_t remaining; /** bytes that have been read */ long read_length; /** how the request body should be read */ @@ -887,9 +887,6 @@ struct conn_rec { /** A list of output filters to be used for this connection * @defvar ap_filter_t *filters */ struct ap_filter_t *output_filters; - /** The length of the current request body - * @defvar long remain */ - long remain; }; /* Per-vhost config... */ diff --git a/include/util_filter.h b/include/util_filter.h index 4784f8af97..1b9e2490ef 100644 --- a/include/util_filter.h +++ b/include/util_filter.h @@ -155,7 +155,8 @@ typedef struct ap_filter_t ap_filter_t; */ typedef apr_status_t (*ap_out_filter_func)(ap_filter_t *f, apr_bucket_brigade *b); typedef apr_status_t (*ap_in_filter_func)(ap_filter_t *f, apr_bucket_brigade *b, - ap_input_mode_t mode); + ap_input_mode_t mode, apr_size_t *readbytes); + typedef union ap_filter_func { ap_out_filter_func out_func; ap_in_filter_func in_func; @@ -273,7 +274,7 @@ struct ap_filter_t { * @param mode ::AP_MODE_BLOCKING, ::AP_MODE_NONBLOCKING, or ::AP_MODE_PEEK */ AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket, - ap_input_mode_t mode); + ap_input_mode_t mode, apr_size_t *readbytes); /** * Pass the current bucket brigade down to the next filter on the filter diff --git a/modules/experimental/mod_charset_lite.c b/modules/experimental/mod_charset_lite.c index 8cadc729cf..79830eed08 100644 --- a/modules/experimental/mod_charset_lite.c +++ b/modules/experimental/mod_charset_lite.c @@ -1005,7 +1005,7 @@ static void transfer_brigade(apr_bucket_brigade *in, apr_bucket_brigade *out) } static int xlate_in_filter(ap_filter_t *f, apr_bucket_brigade *bb, - ap_input_mode_t mode) + ap_input_mode_t mode, apr_size_t *readbytes) { apr_status_t rv; charset_req_t *reqinfo = ap_get_module_config(f->r->request_config, @@ -1049,11 +1049,11 @@ static int xlate_in_filter(ap_filter_t *f, apr_bucket_brigade *bb, } if (ctx->noop) { - return ap_get_brigade(f->next, bb, mode); + return ap_get_brigade(f->next, bb, mode, readbytes); } if (APR_BRIGADE_EMPTY(ctx->bb)) { - if ((rv = ap_get_brigade(f->next, bb, mode)) != APR_SUCCESS) { + if ((rv = ap_get_brigade(f->next, bb, mode, readbytes)) != APR_SUCCESS) { return rv; } } diff --git a/modules/experimental/mod_ext_filter.c b/modules/experimental/mod_ext_filter.c index defc85492c..46b4b1e527 100644 --- a/modules/experimental/mod_ext_filter.c +++ b/modules/experimental/mod_ext_filter.c @@ -749,7 +749,7 @@ static apr_status_t ef_output_filter(ap_filter_t *f, apr_bucket_brigade *bb) #if 0 static int ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb, - ap_input_mode_t mode) + ap_input_mode_t mode, apr_size_t *readbytes) { apr_status_t rv; apr_bucket *b; @@ -757,7 +757,7 @@ static int ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb, apr_ssize_t len; char *zero; - rv = ap_get_brigade(f->next, bb, mode); + rv = ap_get_brigade(f->next, bb, mode, readbytes); if (rv != APR_SUCCESS) { return rv; } diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index 6e1298a9da..a4426466be 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -420,7 +420,7 @@ struct dechunk_ctx { static long get_chunk_size(char *); apr_status_t ap_dechunk_filter(ap_filter_t *f, apr_bucket_brigade *bb, - ap_input_mode_t mode) + ap_input_mode_t mode, apr_size_t *readbytes) { apr_status_t rv; struct dechunk_ctx *ctx = f->ctx; @@ -475,8 +475,8 @@ apr_status_t ap_dechunk_filter(ap_filter_t *f, apr_bucket_brigade *bb, if (ctx->state == WANT_BODY) { /* Tell ap_http_filter() how many bytes to deliver. */ - f->c->remain = ctx->chunk_size - ctx->bytes_delivered; - if ((rv = ap_get_brigade(f->next, bb, mode)) != APR_SUCCESS) { + apr_size_t readbytes = ctx->chunk_size - ctx->bytes_delivered; + if ((rv = ap_get_brigade(f->next, bb, mode, &readbytes)) != APR_SUCCESS) { return rv; } /* Walk through the body, accounting for bytes, and removing an eos bucket if @@ -503,7 +503,7 @@ typedef struct http_filter_ctx { apr_bucket_brigade *b; } http_ctx_t; -apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode) +apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes) { apr_bucket *e; char *buff; @@ -556,12 +556,12 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode } if (APR_BRIGADE_EMPTY(ctx->b)) { - if ((rv = ap_get_brigade(f->next, ctx->b, mode)) != APR_SUCCESS) { + if ((rv = ap_get_brigade(f->next, ctx->b, mode, readbytes)) != APR_SUCCESS) { return rv; } } - if (f->c->remain) { + if (*readbytes) { while (!APR_BRIGADE_EMPTY(ctx->b)) { const char *ignore; @@ -580,12 +580,12 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode * a time - don't assume that one call to apr_bucket_read() * will return the full string. */ - if (f->c->remain < len) { - apr_bucket_split(e, f->c->remain); - f->c->remain = 0; + if (*readbytes < len) { + apr_bucket_split(e, *readbytes); + *readbytes = 0; } else { - f->c->remain -= len; + *readbytes -= len; } APR_BUCKET_REMOVE(e); APR_BRIGADE_INSERT_TAIL(b, e); @@ -593,7 +593,7 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode } apr_bucket_delete(e); } - if (f->c->remain == 0) { + if (*readbytes == 0) { apr_bucket *eos = apr_bucket_eos_create(); APR_BRIGADE_INSERT_TAIL(b, eos); @@ -1258,7 +1258,7 @@ AP_DECLARE(int) ap_setup_client_block(request_rec *r, int read_policy) return HTTP_BAD_REQUEST; } - r->connection->remain = r->remaining = atol(lenp); + r->remaining = atol(lenp); } if ((r->read_body == REQUEST_NO_BODY) && @@ -1366,7 +1366,7 @@ AP_DECLARE(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz) do { if (APR_BRIGADE_EMPTY(bb)) { - if (ap_get_brigade(r->input_filters, bb, AP_MODE_BLOCKING) != APR_SUCCESS) { + if (ap_get_brigade(r->input_filters, bb, AP_MODE_BLOCKING, &r->remaining) != APR_SUCCESS) { /* if we actually fail here, we want to just return and * stop trying to read data from the client. */ diff --git a/modules/http/http_request.c b/modules/http/http_request.c index 17b0de9d0a..56064c451b 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -367,6 +367,7 @@ static void check_pipeline_flush(request_rec *r) ### allow us to defer creation of the brigade to when we actually ### need to send a FLUSH. */ apr_bucket_brigade *bb = apr_brigade_create(r->pool); + apr_size_t zero = 0; /* Flush the filter contents if: * @@ -375,7 +376,7 @@ static void check_pipeline_flush(request_rec *r) */ /* ### shouldn't this read from the connection input filters? */ if (!r->connection->keepalive || - ap_get_brigade(r->input_filters, bb, AP_MODE_PEEK) != APR_SUCCESS) { + ap_get_brigade(r->input_filters, bb, AP_MODE_PEEK, &zero) != APR_SUCCESS) { apr_bucket *e = apr_bucket_flush_create(); /* We just send directly to the connection based filters. At diff --git a/modules/http/mod_core.h b/modules/http/mod_core.h index e9ff827ed1..29fef07b65 100644 --- a/modules/http/mod_core.h +++ b/modules/http/mod_core.h @@ -73,8 +73,8 @@ extern "C" { /* * These (input) filters are internal to the mod_core operation. */ -apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode); -apr_status_t ap_dechunk_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode); +apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes); +apr_status_t ap_dechunk_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes); char *ap_response_code_string(request_rec *r, int error_index); diff --git a/modules/tls/mod_tls.c b/modules/tls/mod_tls.c index fda4240854..f8f78302ff 100644 --- a/modules/tls/mod_tls.c +++ b/modules/tls/mod_tls.c @@ -186,14 +186,14 @@ static apr_status_t churn_output(TLSFilterCtx *pCtx) return APR_SUCCESS; } -static apr_status_t churn(TLSFilterCtx *pCtx,apr_read_type_e eReadType) +static apr_status_t churn(TLSFilterCtx *pCtx,apr_read_type_e eReadType,apr_size_t *readbytes) { ap_input_mode_t eMode=eReadType == APR_BLOCK_READ ? AP_MODE_BLOCKING : AP_MODE_NONBLOCKING; apr_bucket *pbktIn; if(APR_BRIGADE_EMPTY(pCtx->pbbInput)) { - ap_get_brigade(pCtx->pInputFilter->next,pCtx->pbbInput,eMode); + ap_get_brigade(pCtx->pInputFilter->next,pCtx->pbbInput,eMode,readbytes); if(APR_BRIGADE_EMPTY(pCtx->pbbInput)) return APR_EOF; } @@ -329,7 +329,7 @@ static apr_status_t tls_out_filter(ap_filter_t *f,apr_bucket_brigade *pbbIn) } static apr_status_t tls_in_filter(ap_filter_t *f,apr_bucket_brigade *pbbOut, - ap_input_mode_t eMode) + ap_input_mode_t eMode, apr_size_t *readbytes) { TLSFilterCtx *pCtx=f->ctx; apr_read_type_e eReadType=eMode == AP_MODE_BLOCKING ? APR_BLOCK_READ : @@ -340,7 +340,7 @@ static apr_status_t tls_in_filter(ap_filter_t *f,apr_bucket_brigade *pbbOut, assert(eMode != AP_MODE_PEEK); // churn the state machine - ret=churn(pCtx,eReadType); + ret=churn(pCtx,eReadType,readbytes); if(ret != APR_SUCCESS) return ret; diff --git a/server/core.c b/server/core.c index 7dded2f8b7..355b55ed7c 100644 --- a/server/core.c +++ b/server/core.c @@ -2995,7 +2995,7 @@ static int default_handler(request_rec *r) return ap_pass_brigade(r->output_filters, bb); } -static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode) +static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes) { apr_bucket *e; diff --git a/server/protocol.c b/server/protocol.c index 45395faabe..8b14fb7d31 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -203,6 +203,7 @@ AP_CORE_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold) int retval; int total = 0; int looking_ahead = 0; + apr_size_t zero = 0; apr_size_t length; conn_rec *c = r->connection; core_request_config *req_cfg; @@ -217,7 +218,7 @@ AP_CORE_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold) while (1) { if (APR_BRIGADE_EMPTY(b)) { - if ((retval = ap_get_brigade(c->input_filters, b, AP_MODE_BLOCKING)) != APR_SUCCESS || + if ((retval = ap_get_brigade(c->input_filters, b, AP_MODE_BLOCKING, &zero)) != APR_SUCCESS || APR_BRIGADE_EMPTY(b)) { apr_brigade_destroy(b); return -1; @@ -548,8 +549,6 @@ request_rec *ap_read_request(conn_rec *conn) const char *expect; int access_status; - AP_DEBUG_ASSERT(conn->remain == 0); - apr_pool_create(&p, conn->pool); r = apr_pcalloc(p, sizeof(request_rec)); r->pool = p; diff --git a/server/util_filter.c b/server/util_filter.c index 381cf03b51..2291919eb9 100644 --- a/server/util_filter.c +++ b/server/util_filter.c @@ -209,10 +209,10 @@ AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f) * brigade especially for that use. */ AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next, apr_bucket_brigade *bb, - ap_input_mode_t mode) + ap_input_mode_t mode, apr_size_t *readbytes) { if (next) { - return next->frec->filter_func.in_func(next, bb, mode); + return next->frec->filter_func.in_func(next, bb, mode, readbytes); } return AP_NOBODY_READ; } -- 2.50.1