*/
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, apr_size_t *readbytes);
+ ap_input_mode_t mode, apr_size_t readbytes);
typedef union ap_filter_func {
ap_out_filter_func out_func;
* a single line should be read.
*/
AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket,
- ap_input_mode_t mode, apr_size_t *readbytes);
+ 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, apr_size_t *readbytes)
+ 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 0
static int ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
- ap_input_mode_t mode, apr_size_t *readbytes)
+ ap_input_mode_t mode, apr_size_t readbytes)
{
apr_status_t rv;
apr_bucket *b;
struct dechunk_ctx {
apr_size_t chunk_size;
apr_size_t bytes_delivered;
- enum {WANT_HDR /* must have value zero */, WANT_BODY, WANT_TRL} state;
+ enum {
+ WANT_HDR /* must have value zero */,
+ WANT_BODY,
+ WANT_TRL
+ } state;
};
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, apr_size_t *readbytes)
+ ap_input_mode_t mode, apr_size_t readbytes)
{
apr_status_t rv;
struct dechunk_ctx *ctx = f->ctx;
*/
char line[30];
- if ((rv = ap_getline(line, sizeof(line), f->r, 0)) < 0) {
+ if ((rv = ap_getline(line, sizeof(line), f->r,
+ 0 /* readline */)) < 0) {
return rv;
}
switch(ctx->state) {
/* bad trailer */
}
if (ctx->chunk_size == 0) { /* we just finished the last chunk? */
+ /* ### woah... ap_http_filter() is doing this, too */
/* append eos bucket and get out */
b = apr_bucket_eos_create();
APR_BRIGADE_INSERT_TAIL(bb, b);
if (ctx->state == WANT_BODY) {
/* Tell ap_http_filter() how many bytes to deliver. */
- apr_size_t readbytes = ctx->chunk_size - ctx->bytes_delivered;
- if ((rv = ap_get_brigade(f->next, bb, mode, &readbytes)) != APR_SUCCESS) {
+ apr_size_t chunk_bytes = ctx->chunk_size - ctx->bytes_delivered;
+
+ if ((rv = ap_get_brigade(f->next, bb, mode,
+ chunk_bytes)) != APR_SUCCESS) {
return rv;
}
- /* Walk through the body, accounting for bytes, and removing an eos bucket if
- * ap_http_filter() delivered the entire chunk.
+
+ /* Walk through the body, accounting for bytes, and removing an eos
+ * bucket if ap_http_filter() delivered the entire chunk.
+ *
+ * ### this shouldn't be necessary. 1) ap_http_filter shouldn't be
+ * ### adding EOS buckets. 2) it shouldn't return more bytes than
+ * ### we requested, therefore the total len can be found with a
+ * ### simple call to apr_brigade_length(). no further munging
+ * ### would be needed.
*/
b = APR_BRIGADE_FIRST(bb);
while (b != APR_BRIGADE_SENTINEL(bb) && !APR_BUCKET_IS_EOS(b)) {
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_size_t *readbytes)
+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 (*readbytes) {
+ /* readbytes == 0 is "read a single line". otherwise, read a block. */
+ if (readbytes) {
+
+ /* ### the code below, which moves bytes from one brigade to the
+ ### other is probably bogus. presuming the next filter down was
+ ### working properly, it should not have returned more than
+ ### READBYTES bytes, and we wouldn't have to do any work. further,
+ ### we could probably just use brigade_partition() in here.
+ */
+
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 (*readbytes < len) {
- apr_bucket_split(e, *readbytes);
- *readbytes = 0;
+ if (readbytes < len) {
+ apr_bucket_split(e, readbytes);
+ readbytes = 0;
}
else {
- *readbytes -= len;
+ readbytes -= len;
}
APR_BUCKET_REMOVE(e);
APR_BRIGADE_INSERT_TAIL(b, e);
}
apr_bucket_delete(e);
}
- if (*readbytes == 0) {
+
+ /* ### this is a hack. it is saying, "if we have read everything
+ ### that was requested, then we are at the end of the request."
+ ### it presumes that the next filter up will *only* call us
+ ### with readbytes set to the Content-Length of the request.
+ ### that may not always be true, and this code is *definitely*
+ ### too presumptive of the caller's intent. the point is: this
+ ### filter is not the guy that is parsing the headers or the
+ ### chunks to determine where the end of the request is, so we
+ ### shouldn't be monkeying with EOS buckets.
+ */
+ if (readbytes == 0) {
apr_bucket *eos = apr_bucket_eos_create();
APR_BRIGADE_INSERT_TAIL(b, eos);
return APR_SUCCESS;
}
+ /* we are reading a single line, e.g. the HTTP headers */
while (!APR_BRIGADE_EMPTY(ctx->b)) {
e = APR_BRIGADE_FIRST(ctx->b);
if ((rv = apr_bucket_read(e, (const char **)&buff, &len, mode)) != APR_SUCCESS) {
do {
if (APR_BRIGADE_EMPTY(bb)) {
- if (ap_get_brigade(r->input_filters, bb, AP_MODE_BLOCKING, &r->remaining) != 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.
*/
return -1;
}
}
- b = APR_BRIGADE_FIRST(bb);
} while (APR_BRIGADE_EMPTY(bb));
- if (APR_BUCKET_IS_EOS(b)) { /* reached eos on previous invocation */
+ b = APR_BRIGADE_FIRST(bb);
+ if (APR_BUCKET_IS_EOS(b)) { /* reached eos on previous invocation */
apr_bucket_delete(b);
return 0;
}
+ /* ### it would be nice to replace the code below with "consume N bytes
+ ### from this brigade, placing them into that buffer." there are
+ ### other places where we do the same...
+ ###
+ ### alternatively, we could partition the brigade, then call a
+ ### function which serializes a given brigade into a buffer. that
+ ### semantic is used elsewhere, too...
+ */
+
total = 0;
- while (total < bufsiz && b != APR_BRIGADE_SENTINEL(bb) && !APR_BUCKET_IS_EOS(b)) {
+ while (total < bufsiz
+ && b != APR_BRIGADE_SENTINEL(bb)
+ && !APR_BUCKET_IS_EOS(b)) {
+
if ((rv = apr_bucket_read(b, &tempbuf, &len_read, APR_BLOCK_READ)) != APR_SUCCESS) {
return -1;
}
### 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:
*
* 2) there isn't a request ready to be read
*/
/* ### shouldn't this read from the connection input filters? */
+ /* ### is zero correct? that means "read one line" */
if (!r->connection->keepalive ||
- ap_get_brigade(r->input_filters, bb, AP_MODE_PEEK, &zero) != APR_SUCCESS) {
+ ap_get_brigade(r->input_filters, bb, AP_MODE_PEEK, 0) != 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_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);
+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,apr_size_t *readbytes)
+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;
{
TLSFilterCtx *pCtx=f->ctx;
apr_bucket *pbktIn;
- apr_size_t zero = 0;
APR_BRIGADE_FOREACH(pbktIn,pbbIn) {
const char *data;
ret=churn_output(pCtx);
if(ret != APR_SUCCESS)
return ret;
- ret=churn(pCtx,APR_NONBLOCK_READ,&zero);
+ ret=churn(pCtx,APR_NONBLOCK_READ,0);
if(ret != APR_SUCCESS) {
if(ret == APR_EOF)
return APR_SUCCESS;
if(APR_BUCKET_IS_FLUSH(pbktIn)) {
/* assume that churn will flush (or already has) if there's output */
- ret=churn(pCtx,APR_NONBLOCK_READ,&zero);
+ ret=churn(pCtx,APR_NONBLOCK_READ,0);
if(ret != APR_SUCCESS)
return ret;
continue;
}
static apr_status_t tls_in_filter(ap_filter_t *f,apr_bucket_brigade *pbbOut,
- ap_input_mode_t eMode, apr_size_t *readbytes)
+ 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 :
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, apr_size_t *readbytes)
+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;
-
+
+ /* ### we should obey readbytes. the policy is to not insert more than
+ ### READBYTES into the brigade. the caller knows the amount that is
+ ### proper for the protocol. reading more than that could cause
+ ### problems.
+ ### (of course, we can read them from the socket, we just should not
+ ### return them until asked)
+ */
+
if (!f->ctx) { /* If we haven't passed up the socket yet... */
f->ctx = (void *)1;
e = apr_bucket_socket_create(f->c->client_socket);
&mpm_perchild_module);
char *foo;
apr_size_t len;
- apr_size_t readbytes = 0;
apr_pool_userdata_get((void **)&foo, "PERCHILD_BUFFER", r->connection->pool);
len = strlen(foo);
}
write(sconf->sd2, foo, len);
-
- while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING, &readbytes) == APR_SUCCESS) {
+
+ /* ### this "read one line" doesn't seem right... shouldn't we be
+ ### reading large chunks of data or something?
+ */
+ while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING,
+ 0 /* read one line */) == APR_SUCCESS) {
apr_bucket *e;
APR_BRIGADE_FOREACH(e, bb) {
const char *str;
return OK;
}
-static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes)
+static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t readbytes)
{
apr_bucket *e;
apr_status_t rv;
&mpm_perchild_module);
char *foo;
apr_size_t len;
- apr_size_t readbytes = 0;
apr_pool_userdata_get((void **)&foo, "PERCHILD_BUFFER", r->connection->pool);
len = strlen(foo);
}
write(sconf->sd2, foo, len);
-
- while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING, &readbytes) == APR_SUCCESS) {
+
+ /* ### this "read one line" doesn't seem right... shouldn't we be
+ ### reading large chunks of data or something?
+ */
+ while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING,
+ 0 /* read one line */) == APR_SUCCESS) {
apr_bucket *e;
APR_BRIGADE_FOREACH(e, bb) {
const char *str;
return OK;
}
-static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes)
+static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t readbytes)
{
apr_bucket *e;
apr_status_t rv;
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, &zero)) != APR_SUCCESS ||
+ if ((retval = ap_get_brigade(c->input_filters, b,
+ AP_MODE_BLOCKING,
+ 0 /* readline */)) != APR_SUCCESS ||
APR_BRIGADE_EMPTY(b)) {
apr_brigade_destroy(b);
return -1;
* save data off to the side should probably create their own temporary
* 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, apr_size_t *readbytes)
+AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next,
+ apr_bucket_brigade *bb,
+ ap_input_mode_t mode,
+ apr_size_t readbytes)
{
if (next) {
return next->frec->filter_func.in_func(next, bb, mode, readbytes);