mirror of
https://github.com/apache/httpd.git
synced 2025-08-07 04:02:58 +03:00
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
This commit is contained in:
6
CHANGES
6
CHANGES
@@ -1,4 +1,10 @@
|
|||||||
Changes with Apache 2.0.18-dev
|
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
|
*) Fix seg fault at start-up introduced by Ryan's change to enable
|
||||||
modules to specify their own logging tags. mod_log_config
|
modules to specify their own logging tags. mod_log_config
|
||||||
registers an optional function, ap_register_log_handler().
|
registers an optional function, ap_register_log_handler().
|
||||||
|
@@ -697,7 +697,7 @@ struct request_rec {
|
|||||||
apr_off_t clength;
|
apr_off_t clength;
|
||||||
|
|
||||||
/** bytes left to read */
|
/** bytes left to read */
|
||||||
long remaining;
|
apr_size_t remaining;
|
||||||
/** bytes that have been read */
|
/** bytes that have been read */
|
||||||
long read_length;
|
long read_length;
|
||||||
/** how the request body should be read */
|
/** 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
|
/** A list of output filters to be used for this connection
|
||||||
* @defvar ap_filter_t *filters */
|
* @defvar ap_filter_t *filters */
|
||||||
struct ap_filter_t *output_filters;
|
struct ap_filter_t *output_filters;
|
||||||
/** The length of the current request body
|
|
||||||
* @defvar long remain */
|
|
||||||
long remain;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Per-vhost config... */
|
/* Per-vhost config... */
|
||||||
|
@@ -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_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,
|
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 {
|
typedef union ap_filter_func {
|
||||||
ap_out_filter_func out_func;
|
ap_out_filter_func out_func;
|
||||||
ap_in_filter_func in_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
|
* @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_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
|
* Pass the current bucket brigade down to the next filter on the filter
|
||||||
|
@@ -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,
|
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;
|
apr_status_t rv;
|
||||||
charset_req_t *reqinfo = ap_get_module_config(f->r->request_config,
|
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) {
|
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 (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;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -749,7 +749,7 @@ static apr_status_t ef_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static int ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
|
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_status_t rv;
|
||||||
apr_bucket *b;
|
apr_bucket *b;
|
||||||
@@ -757,7 +757,7 @@ static int ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
|
|||||||
apr_ssize_t len;
|
apr_ssize_t len;
|
||||||
char *zero;
|
char *zero;
|
||||||
|
|
||||||
rv = ap_get_brigade(f->next, bb, mode);
|
rv = ap_get_brigade(f->next, bb, mode, readbytes);
|
||||||
if (rv != APR_SUCCESS) {
|
if (rv != APR_SUCCESS) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@@ -420,7 +420,7 @@ struct dechunk_ctx {
|
|||||||
static long get_chunk_size(char *);
|
static long get_chunk_size(char *);
|
||||||
|
|
||||||
apr_status_t ap_dechunk_filter(ap_filter_t *f, apr_bucket_brigade *bb,
|
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;
|
apr_status_t rv;
|
||||||
struct dechunk_ctx *ctx = f->ctx;
|
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) {
|
if (ctx->state == WANT_BODY) {
|
||||||
/* Tell ap_http_filter() how many bytes to deliver. */
|
/* Tell ap_http_filter() how many bytes to deliver. */
|
||||||
f->c->remain = ctx->chunk_size - ctx->bytes_delivered;
|
apr_size_t readbytes = ctx->chunk_size - ctx->bytes_delivered;
|
||||||
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;
|
return rv;
|
||||||
}
|
}
|
||||||
/* Walk through the body, accounting for bytes, and removing an eos bucket if
|
/* 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;
|
apr_bucket_brigade *b;
|
||||||
} http_ctx_t;
|
} 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;
|
apr_bucket *e;
|
||||||
char *buff;
|
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 (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;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f->c->remain) {
|
if (*readbytes) {
|
||||||
while (!APR_BRIGADE_EMPTY(ctx->b)) {
|
while (!APR_BRIGADE_EMPTY(ctx->b)) {
|
||||||
const char *ignore;
|
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()
|
* a time - don't assume that one call to apr_bucket_read()
|
||||||
* will return the full string.
|
* will return the full string.
|
||||||
*/
|
*/
|
||||||
if (f->c->remain < len) {
|
if (*readbytes < len) {
|
||||||
apr_bucket_split(e, f->c->remain);
|
apr_bucket_split(e, *readbytes);
|
||||||
f->c->remain = 0;
|
*readbytes = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
f->c->remain -= len;
|
*readbytes -= len;
|
||||||
}
|
}
|
||||||
APR_BUCKET_REMOVE(e);
|
APR_BUCKET_REMOVE(e);
|
||||||
APR_BRIGADE_INSERT_TAIL(b, 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);
|
apr_bucket_delete(e);
|
||||||
}
|
}
|
||||||
if (f->c->remain == 0) {
|
if (*readbytes == 0) {
|
||||||
apr_bucket *eos = apr_bucket_eos_create();
|
apr_bucket *eos = apr_bucket_eos_create();
|
||||||
|
|
||||||
APR_BRIGADE_INSERT_TAIL(b, eos);
|
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;
|
return HTTP_BAD_REQUEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
r->connection->remain = r->remaining = atol(lenp);
|
r->remaining = atol(lenp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((r->read_body == REQUEST_NO_BODY) &&
|
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 {
|
do {
|
||||||
if (APR_BRIGADE_EMPTY(bb)) {
|
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
|
/* if we actually fail here, we want to just return and
|
||||||
* stop trying to read data from the client.
|
* stop trying to read data from the client.
|
||||||
*/
|
*/
|
||||||
|
@@ -367,6 +367,7 @@ static void check_pipeline_flush(request_rec *r)
|
|||||||
### allow us to defer creation of the brigade to when we actually
|
### allow us to defer creation of the brigade to when we actually
|
||||||
### need to send a FLUSH. */
|
### need to send a FLUSH. */
|
||||||
apr_bucket_brigade *bb = apr_brigade_create(r->pool);
|
apr_bucket_brigade *bb = apr_brigade_create(r->pool);
|
||||||
|
apr_size_t zero = 0;
|
||||||
|
|
||||||
/* Flush the filter contents if:
|
/* 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? */
|
/* ### shouldn't this read from the connection input filters? */
|
||||||
if (!r->connection->keepalive ||
|
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();
|
apr_bucket *e = apr_bucket_flush_create();
|
||||||
|
|
||||||
/* We just send directly to the connection based filters. At
|
/* We just send directly to the connection based filters. At
|
||||||
|
@@ -73,8 +73,8 @@ extern "C" {
|
|||||||
/*
|
/*
|
||||||
* These (input) filters are internal to the mod_core operation.
|
* 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_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_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);
|
char *ap_response_code_string(request_rec *r, int error_index);
|
||||||
|
|
||||||
|
@@ -186,14 +186,14 @@ static apr_status_t churn_output(TLSFilterCtx *pCtx)
|
|||||||
return APR_SUCCESS;
|
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_input_mode_t eMode=eReadType == APR_BLOCK_READ ? AP_MODE_BLOCKING
|
||||||
: AP_MODE_NONBLOCKING;
|
: AP_MODE_NONBLOCKING;
|
||||||
apr_bucket *pbktIn;
|
apr_bucket *pbktIn;
|
||||||
|
|
||||||
if(APR_BRIGADE_EMPTY(pCtx->pbbInput)) {
|
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))
|
if(APR_BRIGADE_EMPTY(pCtx->pbbInput))
|
||||||
return APR_EOF;
|
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,
|
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;
|
TLSFilterCtx *pCtx=f->ctx;
|
||||||
apr_read_type_e eReadType=eMode == AP_MODE_BLOCKING ? APR_BLOCK_READ :
|
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);
|
assert(eMode != AP_MODE_PEEK);
|
||||||
|
|
||||||
// churn the state machine
|
// churn the state machine
|
||||||
ret=churn(pCtx,eReadType);
|
ret=churn(pCtx,eReadType,readbytes);
|
||||||
if(ret != APR_SUCCESS)
|
if(ret != APR_SUCCESS)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@@ -2995,7 +2995,7 @@ static int default_handler(request_rec *r)
|
|||||||
return ap_pass_brigade(r->output_filters, bb);
|
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;
|
apr_bucket *e;
|
||||||
|
|
||||||
|
@@ -203,6 +203,7 @@ AP_CORE_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold)
|
|||||||
int retval;
|
int retval;
|
||||||
int total = 0;
|
int total = 0;
|
||||||
int looking_ahead = 0;
|
int looking_ahead = 0;
|
||||||
|
apr_size_t zero = 0;
|
||||||
apr_size_t length;
|
apr_size_t length;
|
||||||
conn_rec *c = r->connection;
|
conn_rec *c = r->connection;
|
||||||
core_request_config *req_cfg;
|
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) {
|
while (1) {
|
||||||
if (APR_BRIGADE_EMPTY(b)) {
|
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_EMPTY(b)) {
|
||||||
apr_brigade_destroy(b);
|
apr_brigade_destroy(b);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -548,8 +549,6 @@ request_rec *ap_read_request(conn_rec *conn)
|
|||||||
const char *expect;
|
const char *expect;
|
||||||
int access_status;
|
int access_status;
|
||||||
|
|
||||||
AP_DEBUG_ASSERT(conn->remain == 0);
|
|
||||||
|
|
||||||
apr_pool_create(&p, conn->pool);
|
apr_pool_create(&p, conn->pool);
|
||||||
r = apr_pcalloc(p, sizeof(request_rec));
|
r = apr_pcalloc(p, sizeof(request_rec));
|
||||||
r->pool = p;
|
r->pool = p;
|
||||||
|
@@ -209,10 +209,10 @@ AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
|
|||||||
* brigade especially for that use.
|
* brigade especially for that use.
|
||||||
*/
|
*/
|
||||||
AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next, apr_bucket_brigade *bb,
|
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) {
|
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;
|
return AP_NOBODY_READ;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user