From: Jeff Trawick Date: Sat, 21 Oct 2000 13:20:36 +0000 (+0000) Subject: Input filters and ap_get_brigade() now have a input mode parameter X-Git-Tag: APACHE_2_0_ALPHA_8~293 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=96cf82e63b6c906ac526b24684c5685c660efbbd;p=apache Input filters and ap_get_brigade() now have a input mode parameter (blocking, non-blocking, peek) instead of a length parameter. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86684 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/include/http_protocol.h b/include/http_protocol.h index 1d76e1d32b..eff978a9f5 100644 --- a/include/http_protocol.h +++ b/include/http_protocol.h @@ -529,8 +529,8 @@ AP_DECLARE(int) ap_method_number_of(const char *method); */ AP_DECLARE(const char *) ap_method_name_of(int methnum); -int http_filter(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t length); -apr_status_t dechunk_filter(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t length); +apr_status_t http_filter(ap_filter_t *f, ap_bucket_brigade *b, ap_input_mode_t mode); +apr_status_t dechunk_filter(ap_filter_t *f, ap_bucket_brigade *b, ap_input_mode_t mode); /* Hooks */ /* diff --git a/include/util_filter.h b/include/util_filter.h index 8a9b959390..edcc4eb636 100644 --- a/include/util_filter.h +++ b/include/util_filter.h @@ -74,11 +74,29 @@ extern "C" { #define AP_NOBODY_WROTE -1 #define AP_NOBODY_READ -2 -/* Input filtering macros */ -#define AP_GET_LINE 0 /* Get one line from the next filter */ -#define AP_GET_ANY_AMOUNT -1 /* Get as much data as the next filter - * is willing to give up. - */ +/* ap_input_mode_t - input filtering modes + * + * AP_MODE_BLOCKING + * + * The filter shouldn't return until data is received or EOF is hit or an error + * occurs. + * + * AP_MODE_NONBLOCKING + * + * The filter should process any available data/status as normal, but will not + * wait for additional data. + * + * AP_MODE_PEEK + * + * The filter should return APR_SUCCESS if data is available or APR_EOF + * otherwise. The filter must not return any buckets of data. Data returned + * on a subsequent call, when mode is AP_MODE_BLOCKING or AP_MODE_NONBLOCKING. + */ +typedef enum { + AP_MODE_BLOCKING, + AP_MODE_NONBLOCKING, + AP_MODE_PEEK +} ap_input_mode_t; /* * FILTER CHAIN @@ -132,7 +150,8 @@ typedef struct ap_filter_t ap_filter_t; * The return value of a filter should be an APR status value. */ typedef apr_status_t (*ap_out_filter_func)(ap_filter_t *f, ap_bucket_brigade *b); -typedef apr_status_t (*ap_in_filter_func)(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t length); +typedef apr_status_t (*ap_in_filter_func)(ap_filter_t *f, ap_bucket_brigade *b, + ap_input_mode_t mode); typedef union ap_filter_func { ap_out_filter_func out_func; ap_in_filter_func in_func; @@ -243,19 +262,12 @@ struct ap_filter_t { * filter doesn't write to the network, then AP_NOBODY_READ is returned. * @param filter The next filter in the chain * @param bucket The current bucket brigade - * @param length The maximum amount of data to be returned from the next - * lowest filter. If filter a requests 15 bytes - * from the filter b, that doesn't stop the b - * from requesting 30 bytes from filter c. It just - * stops b from returning more that 15 bytes to a. The other - * 15 must be stored by b. A value of AP_GET_LINE (0) tells - * the filter to only ever return a single line. A value of - * AP_GET_ANY_AMOUNT (-1) tells a filter to return everything - * it has. + * @param mode AP_MODE_BLOCKING, AP_MODE_NONBLOCKING, or AP_MODE_PEEK * @return apr_status_t value - * @deffunc apr_status_t ap_get_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket, apr_ssize_t length) + * @deffunc apr_status_t ap_get_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket, ap_input_mode_t mode) */ -AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket, apr_ssize_t length); +AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket, + ap_input_mode_t mode); /** * Pass the current bucket brigade down to the next filter on the filter diff --git a/modules/http/http_core.c b/modules/http/http_core.c index 6db7ebe731..bd914f749c 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -3327,12 +3327,7 @@ static apr_status_t chunk_filter(ap_filter_t *f, ap_bucket_brigade *b) return APR_SUCCESS; } -/* This function only understands a length of AP_GET_ANY_AMOUNT. It will - * ignore length values and always return the entire brigade. This is - * pretty safe to do, because we know there always needs to be an intervening - * filter just above this that will only make requests for AP_GET_ANY_AMOUNT - */ -static int core_input_filter(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t length) +static int core_input_filter(ap_filter_t *f, ap_bucket_brigade *b, ap_input_mode_t mode) { ap_bucket *e; @@ -3359,7 +3354,7 @@ typedef struct CORE_OUTPUT_FILTER_CTX { ap_bucket_brigade *b; } core_output_filter_ctx_t; #define MAX_IOVEC_TO_WRITE 16 -static int core_output_filter(ap_filter_t *f, ap_bucket_brigade *b) +static apr_status_t core_output_filter(ap_filter_t *f, ap_bucket_brigade *b) { apr_status_t rv; ap_bucket_brigade *more = NULL; diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index 2b798ba37d..5e8e2ff2a2 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -850,7 +850,7 @@ static long get_chunk_size(char *); static int getline(char *s, int n, request_rec *r, int fold); apr_status_t dechunk_filter(ap_filter_t *f, ap_bucket_brigade *bb, - apr_ssize_t length) + ap_input_mode_t mode) { apr_status_t rv; struct dechunk_ctx *ctx = f->ctx; @@ -907,7 +907,7 @@ apr_status_t dechunk_filter(ap_filter_t *f, ap_bucket_brigade *bb, if (ctx->state == WANT_BODY) { /* Tell http_filter() how many bytes to deliver. */ f->c->remain = ctx->chunk_size - ctx->bytes_delivered; - if ((rv = ap_get_brigade(f->next, bb, 999)) != APR_SUCCESS) { + if ((rv = ap_get_brigade(f->next, bb, mode)) != APR_SUCCESS) { return rv; } /* Walk through the body, accounting for bytes, and removing an eos bucket if @@ -935,7 +935,7 @@ typedef struct http_filter_ctx { ap_bucket_brigade *b; } http_ctx_t; -apr_status_t http_filter(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t length) +apr_status_t http_filter(ap_filter_t *f, ap_bucket_brigade *b, ap_input_mode_t mode) { #define ASCII_LF '\012' ap_bucket *e; @@ -948,15 +948,27 @@ apr_status_t http_filter(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t lengt if (!ctx) { f->ctx = ctx = apr_pcalloc(f->c->pool, sizeof(*ctx)); ctx->b = ap_brigade_create(f->c->pool); - if ((rv = ap_get_brigade(f->next, ctx->b, AP_GET_ANY_AMOUNT)) != APR_SUCCESS) { - return rv; - } } - else { + + if (mode == AP_MODE_PEEK) { + /* XXX make me *try* to read from the network if AP_BRIGADE_EMPTY(). + * For now, we can't do a non-blocking read so we bypass this. + * + * Also, note that in the cases where another request can be read now + * without blocking, it is likely already in our brigadet, so this hack + * isn't so bad after all. + */ if (AP_BRIGADE_EMPTY(ctx->b)) { - if ((rv = ap_get_brigade(f->next, ctx->b, AP_GET_LINE)) != APR_SUCCESS) { - return rv; - } + return APR_EOF; + } + else { + return APR_SUCCESS; + } + } + + if (AP_BRIGADE_EMPTY(ctx->b)) { + if ((rv = ap_get_brigade(f->next, ctx->b, mode)) != APR_SUCCESS) { + return rv; } } @@ -1053,7 +1065,7 @@ static int getline(char *s, int n, request_rec *r, int fold) while (1) { if (AP_BRIGADE_EMPTY(b)) { - if (ap_get_brigade(c->input_filters, b, AP_GET_LINE) != APR_SUCCESS || + if (ap_get_brigade(c->input_filters, b, AP_MODE_BLOCKING) != APR_SUCCESS || AP_BRIGADE_EMPTY(b)) { return -1; } diff --git a/server/util_filter.c b/server/util_filter.c index 41bcb84fc6..85780a04f6 100644 --- a/server/util_filter.c +++ b/server/util_filter.c @@ -195,11 +195,11 @@ AP_DECLARE(void) ap_add_output_filter(const char *name, void *ctx, * 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, - ap_bucket_brigade *bb, apr_ssize_t length) +AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next, ap_bucket_brigade *bb, + ap_input_mode_t mode) { if (next) { - return next->frec->filter_func.in_func(next, bb, length); + return next->frec->filter_func.in_func(next, bb, mode); } return AP_NOBODY_READ; }