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().
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 */
/** 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... */
*/
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;
* @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
}
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,
}
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;
}
}
#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;
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;
}
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;
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
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;
}
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;
* 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);
}
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);
return HTTP_BAD_REQUEST;
}
- r->connection->remain = r->remaining = atol(lenp);
+ r->remaining = atol(lenp);
}
if ((r->read_body == REQUEST_NO_BODY) &&
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.
*/
### 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:
*
*/
/* ### 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
/*
* 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);
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;
}
}
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 :
assert(eMode != AP_MODE_PEEK);
// churn the state machine
- ret=churn(pCtx,eReadType);
+ ret=churn(pCtx,eReadType,readbytes);
if(ret != APR_SUCCESS)
return ret;
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;
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;
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;
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;
* 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;
}