mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
Input filtering prototype change: Socket blocking type should be
separate from the input filter mode type. We also no longer look at readbytes to determine the method of filter operation. This makes the use of filters more obvious and allows a wider range of options for input filters modes. To start with, the new input filter modes are: AP_MODE_READBYTES (no more than *readbytes returned) AP_MODE_GETLINE (old *readbytes == 0 case) AP_MODE_EATCRLF (old AP_MODE_PEEK) AP_MODE_SPECULATIVE (will be used in a future ap_getline rewrite) AP_MODE_EXHAUSTIVE (old *readbytes == -1 case) AP_MODE_INIT (special case for NNTP over SSL) The block parameter is an apr_read_type_e: APR_BLOCK_READ, APR_NONBLOCK_READ This also allows cleanup of mod_ssl's handling in the getline case. Reviewed by: Ryan Bloom (concept), Greg Stein (concept) git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@92928 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -1,5 +1,8 @@
|
|||||||
Changes with Apache 2.0.31-dev
|
Changes with Apache 2.0.31-dev
|
||||||
|
|
||||||
|
*) Split out blocking from the mode in the input filters.
|
||||||
|
[Justin Erenkrantz]
|
||||||
|
|
||||||
*) Fix a segfault in mod_include. [Justin Erenkrantz, Jeff Trawick]
|
*) Fix a segfault in mod_include. [Justin Erenkrantz, Jeff Trawick]
|
||||||
|
|
||||||
*) Cause Win32 to capture all child-worker process errors in
|
*) Cause Win32 to capture all child-worker process errors in
|
||||||
|
@@ -92,6 +92,7 @@
|
|||||||
* 20020111 (2.0.31-dev) bump for ETag fields added at end of cor_dir_config
|
* 20020111 (2.0.31-dev) bump for ETag fields added at end of cor_dir_config
|
||||||
* 20020114 (2.0.31-dev) mod_dav changed how it asks its provider to fulfill
|
* 20020114 (2.0.31-dev) mod_dav changed how it asks its provider to fulfill
|
||||||
* a GET request
|
* a GET request
|
||||||
|
* 20020118 (2.0.31-dev) Input filtering split of blocking and mode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */
|
#define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */
|
||||||
|
@@ -84,23 +84,27 @@ extern "C" {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* input filtering modes
|
* input filtering modes
|
||||||
* @see apr_read_type_e in apr_buckets.h -- this is a superset of it
|
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/** The filter shouldn't return until data is received or EOF is hit
|
/** The filter should return at most *readbytes data. */
|
||||||
* or an error occurs. */
|
AP_MODE_READBYTES,
|
||||||
AP_MODE_BLOCKING = APR_BLOCK_READ,
|
/** The filter should return at most one line of CRLF data.
|
||||||
/** The filter should process any available data/status as normal,
|
* (If a potential line is too long or no CRLF is found, the
|
||||||
* but will not wait for additional data. */
|
* filter may return partial data).
|
||||||
AP_MODE_NONBLOCKING = APR_NONBLOCK_READ,
|
*/
|
||||||
/** The filter should return ::APR_SUCCESS if data is available or
|
AP_MODE_GETLINE,
|
||||||
* ::APR_EOF otherwise. The filter must not return any buckets of
|
/** The filter should implicitly eat any CRLF pairs that it sees. */
|
||||||
* data. Data returned on a subsequent call, when mode is
|
AP_MODE_EATCRLF,
|
||||||
* ::AP_MODE_BLOCKING or ::AP_MODE_NONBLOCKING. */
|
/** The filter read should be treated as speculative and any returned
|
||||||
AP_MODE_PEEK,
|
* data should be stored for later retrieval in another mode. */
|
||||||
/*
|
AP_MODE_SPECULATIVE,
|
||||||
* the filter should initialize the connection if needed,
|
/** The filter read should be exhaustive and read until it can not
|
||||||
* NNTP or FTP over SSL for example.
|
* read any more.
|
||||||
|
* Use this mode with extreme caution.
|
||||||
|
*/
|
||||||
|
AP_MODE_EXHAUSTIVE,
|
||||||
|
/** The filter should initialize the connection if needed,
|
||||||
|
* NNTP or FTP over SSL for example.
|
||||||
*/
|
*/
|
||||||
AP_MODE_INIT
|
AP_MODE_INIT
|
||||||
} ap_input_mode_t;
|
} ap_input_mode_t;
|
||||||
@@ -161,7 +165,7 @@ 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, apr_off_t *readbytes);
|
ap_input_mode_t mode, apr_read_type_e block, apr_off_t *readbytes);
|
||||||
|
|
||||||
typedef union ap_filter_func {
|
typedef union ap_filter_func {
|
||||||
ap_out_filter_func out_func;
|
ap_out_filter_func out_func;
|
||||||
@@ -277,12 +281,16 @@ struct ap_filter_t {
|
|||||||
* filter doesn't read from the network, then ::AP_NOBODY_READ is returned.
|
* filter doesn't read from the network, then ::AP_NOBODY_READ is returned.
|
||||||
* @param filter The next filter in the chain
|
* @param filter The next filter in the chain
|
||||||
* @param bucket The current bucket brigade
|
* @param bucket The current bucket brigade
|
||||||
* @param mode ::AP_MODE_BLOCKING, ::AP_MODE_NONBLOCKING, or ::AP_MODE_PEEK
|
* @param mode The way in which the data should be read
|
||||||
* @param readbytes How many bytes to read from the next filter. 0 means that
|
* @param block How the operations should be performed
|
||||||
* a single line should be read.
|
* ::APR_BLOCK_READ, ::APR_NONBLOCK_READ
|
||||||
|
* @param readbytes How many bytes to read from the next filter.
|
||||||
*/
|
*/
|
||||||
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,
|
||||||
ap_input_mode_t mode, apr_off_t *readbytes);
|
apr_bucket_brigade *bucket,
|
||||||
|
ap_input_mode_t mode,
|
||||||
|
apr_read_type_e block,
|
||||||
|
apr_off_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
|
||||||
|
@@ -106,8 +106,8 @@ static int process_echo_connection(conn_rec *c)
|
|||||||
|
|
||||||
for ( ; ; ) {
|
for ( ; ; ) {
|
||||||
/* Get a single line of input from the client */
|
/* Get a single line of input from the client */
|
||||||
if ((rv = ap_get_brigade(c->input_filters, bb,
|
if ((rv = ap_get_brigade(c->input_filters, bb, AP_MODE_GETLINE,
|
||||||
AP_MODE_BLOCKING, &zero) != APR_SUCCESS ||
|
APR_BLOCK_READ, &zero) != APR_SUCCESS ||
|
||||||
APR_BRIGADE_EMPTY(bb))) {
|
APR_BRIGADE_EMPTY(bb))) {
|
||||||
apr_brigade_destroy(bb);
|
apr_brigade_destroy(bb);
|
||||||
break;
|
break;
|
||||||
|
@@ -101,6 +101,7 @@ static void CaseFilterInInsertFilter(request_rec *r)
|
|||||||
static apr_status_t CaseFilterInFilter(ap_filter_t *f,
|
static apr_status_t CaseFilterInFilter(ap_filter_t *f,
|
||||||
apr_bucket_brigade *pbbOut,
|
apr_bucket_brigade *pbbOut,
|
||||||
ap_input_mode_t eMode,
|
ap_input_mode_t eMode,
|
||||||
|
apr_read_type_e eBlock,
|
||||||
apr_off_t *nBytes)
|
apr_off_t *nBytes)
|
||||||
{
|
{
|
||||||
request_rec *r = f->r;
|
request_rec *r = f->r;
|
||||||
@@ -113,9 +114,9 @@ static apr_status_t CaseFilterInFilter(ap_filter_t *f,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (APR_BRIGADE_EMPTY(pCtx->pbbTmp)) {
|
if (APR_BRIGADE_EMPTY(pCtx->pbbTmp)) {
|
||||||
ret = ap_get_brigade(f->next, pCtx->pbbTmp, eMode, nBytes);
|
ret = ap_get_brigade(f->next, pCtx->pbbTmp, eMode, eBlock, nBytes);
|
||||||
|
|
||||||
if (eMode == AP_MODE_PEEK || ret != APR_SUCCESS)
|
if (eMode == AP_MODE_EATCRLF || ret != APR_SUCCESS)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ static apr_status_t CaseFilterInFilter(ap_filter_t *f,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret=apr_bucket_read(pbktIn, &data, &len, eMode);
|
ret=apr_bucket_read(pbktIn, &data, &len, eBlock);
|
||||||
if(ret != APR_SUCCESS)
|
if(ret != APR_SUCCESS)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@@ -990,7 +990,8 @@ 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, apr_off_t *readbytes)
|
ap_input_mode_t mode, apr_read_type_e block,
|
||||||
|
apr_off_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,
|
||||||
@@ -1034,11 +1035,12 @@ 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, readbytes);
|
return ap_get_brigade(f->next, bb, mode, block, readbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (APR_BRIGADE_EMPTY(ctx->bb)) {
|
if (APR_BRIGADE_EMPTY(ctx->bb)) {
|
||||||
if ((rv = ap_get_brigade(f->next, bb, mode, readbytes)) != APR_SUCCESS) {
|
if ((rv = ap_get_brigade(f->next, bb, mode, block,
|
||||||
|
readbytes)) != APR_SUCCESS) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -749,7 +749,8 @@ 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, apr_off_t *readbytes)
|
ap_input_mode_t mode, apr_read_type_e block,
|
||||||
|
apr_off_t *readbytes)
|
||||||
{
|
{
|
||||||
apr_status_t rv;
|
apr_status_t rv;
|
||||||
apr_bucket *b;
|
apr_bucket *b;
|
||||||
@@ -757,7 +758,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, readbytes);
|
rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
|
||||||
if (rv != APR_SUCCESS) {
|
if (rv != APR_SUCCESS) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@@ -533,15 +533,16 @@ typedef struct http_filter_ctx {
|
|||||||
* are successfully parsed.
|
* are successfully parsed.
|
||||||
*/
|
*/
|
||||||
apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
|
apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
|
||||||
ap_input_mode_t mode, apr_off_t *readbytes)
|
ap_input_mode_t mode, apr_read_type_e block,
|
||||||
|
apr_off_t *readbytes)
|
||||||
{
|
{
|
||||||
apr_bucket *e;
|
apr_bucket *e;
|
||||||
http_ctx_t *ctx = f->ctx;
|
http_ctx_t *ctx = f->ctx;
|
||||||
apr_status_t rv;
|
apr_status_t rv;
|
||||||
|
|
||||||
/* just get out of the way of this thing. */
|
/* just get out of the way of this thing. */
|
||||||
if (mode == AP_MODE_PEEK) {
|
if (mode == AP_MODE_EATCRLF) {
|
||||||
return ap_get_brigade(f->next, b, mode, readbytes);
|
return ap_get_brigade(f->next, b, mode, block, readbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@@ -648,7 +649,7 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
|
|||||||
AP_DEBUG_ASSERT(*readbytes > 0); /* shouldn't be in getline mode */
|
AP_DEBUG_ASSERT(*readbytes > 0); /* shouldn't be in getline mode */
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = ap_get_brigade(f->next, b, mode, readbytes);
|
rv = ap_get_brigade(f->next, b, mode, block, readbytes);
|
||||||
|
|
||||||
if (rv != APR_SUCCESS) {
|
if (rv != APR_SUCCESS) {
|
||||||
return rv;
|
return rv;
|
||||||
@@ -1479,8 +1480,8 @@ AP_DECLARE(long) ap_get_client_block(request_rec *r, char *buffer,
|
|||||||
/* read until we get a non-empty brigade */
|
/* read until we get a non-empty brigade */
|
||||||
while (APR_BRIGADE_EMPTY(bb)) {
|
while (APR_BRIGADE_EMPTY(bb)) {
|
||||||
apr_off_t len_read = bufsiz;
|
apr_off_t len_read = bufsiz;
|
||||||
if (ap_get_brigade(r->input_filters, bb, AP_MODE_BLOCKING,
|
if (ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
|
||||||
&len_read) != APR_SUCCESS) {
|
APR_BLOCK_READ, &len_read) != 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.
|
||||||
*/
|
*/
|
||||||
|
@@ -249,7 +249,8 @@ 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? */
|
||||||
/* ### is zero correct? that means "read one line" */
|
/* ### is zero correct? that means "read one line" */
|
||||||
if (!r->connection->keepalive ||
|
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_EATCRLF,
|
||||||
|
APR_NONBLOCK_READ, &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
|
||||||
|
@@ -74,7 +74,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,
|
apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b,
|
||||||
ap_input_mode_t mode, apr_off_t *readbytes);
|
ap_input_mode_t mode, apr_read_type_e block,
|
||||||
|
apr_off_t *readbytes);
|
||||||
|
|
||||||
char *ap_response_code_string(request_rec *r, int error_index);
|
char *ap_response_code_string(request_rec *r, int error_index);
|
||||||
|
|
||||||
|
@@ -1586,7 +1586,8 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf,
|
|||||||
"proxy: FTP: start body send");
|
"proxy: FTP: start body send");
|
||||||
|
|
||||||
/* read the body, pass it to the output filters */
|
/* read the body, pass it to the output filters */
|
||||||
while (ap_get_brigade(remote->input_filters, bb, AP_MODE_BLOCKING, &readbytes) == APR_SUCCESS) {
|
while (ap_get_brigade(remote->input_filters, bb, AP_MODE_READBYTES,
|
||||||
|
APR_BLOCK_READ, &readbytes) == APR_SUCCESS) {
|
||||||
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
|
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
|
||||||
ap_pass_brigade(r->output_filters, bb);
|
ap_pass_brigade(r->output_filters, bb);
|
||||||
break;
|
break;
|
||||||
|
@@ -844,8 +844,9 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
|
|||||||
apr_bucket *e;
|
apr_bucket *e;
|
||||||
readbytes = AP_IOBUFSIZE;
|
readbytes = AP_IOBUFSIZE;
|
||||||
while (ap_get_brigade(rp->input_filters,
|
while (ap_get_brigade(rp->input_filters,
|
||||||
bb,
|
bb,
|
||||||
AP_MODE_BLOCKING,
|
AP_MODE_READBYTES,
|
||||||
|
APR_BLOCK_READ,
|
||||||
&readbytes) == APR_SUCCESS) {
|
&readbytes) == APR_SUCCESS) {
|
||||||
#if DEBUGGING
|
#if DEBUGGING
|
||||||
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
|
ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
|
||||||
|
@@ -1017,7 +1017,8 @@ PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade
|
|||||||
apr_off_t zero = 0;
|
apr_off_t zero = 0;
|
||||||
/* get brigade from network one line at a time */
|
/* get brigade from network one line at a time */
|
||||||
if (APR_SUCCESS != (rv = ap_get_brigade(c->input_filters, bb,
|
if (APR_SUCCESS != (rv = ap_get_brigade(c->input_filters, bb,
|
||||||
AP_MODE_BLOCKING,
|
AP_MODE_GETLINE,
|
||||||
|
APR_BLOCK_READ,
|
||||||
&zero /* readline */))) {
|
&zero /* readline */))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@@ -297,7 +297,7 @@ typedef struct {
|
|||||||
ap_filter_t *f;
|
ap_filter_t *f;
|
||||||
apr_status_t rc;
|
apr_status_t rc;
|
||||||
ap_input_mode_t mode;
|
ap_input_mode_t mode;
|
||||||
int getline;
|
apr_read_type_e block;
|
||||||
apr_bucket_brigade *bb;
|
apr_bucket_brigade *bb;
|
||||||
apr_bucket *bucket;
|
apr_bucket *bucket;
|
||||||
char_buffer_t cbuf;
|
char_buffer_t cbuf;
|
||||||
@@ -368,7 +368,7 @@ static int bio_bucket_in_read(BIO *bio, char *in, int inl)
|
|||||||
|
|
||||||
/* first use data already read from socket if any */
|
/* first use data already read from socket if any */
|
||||||
if ((len = char_buffer_read(&inbio->cbuf, in, inl))) {
|
if ((len = char_buffer_read(&inbio->cbuf, in, inl))) {
|
||||||
if ((len <= inl) || inbio->getline) {
|
if ((len <= inl) || inbio->mode == AP_MODE_GETLINE) {
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -386,8 +386,11 @@ static int bio_bucket_in_read(BIO *bio, char *in, int inl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (APR_BRIGADE_EMPTY(inbio->bb)) {
|
if (APR_BRIGADE_EMPTY(inbio->bb)) {
|
||||||
|
/* We will always call with READBYTES even if the user wants
|
||||||
|
* GETLINE.
|
||||||
|
*/
|
||||||
inbio->rc = ap_get_brigade(inbio->f->next, inbio->bb,
|
inbio->rc = ap_get_brigade(inbio->f->next, inbio->bb,
|
||||||
inbio->mode, &readbytes);
|
AP_MODE_READBYTES, inbio->block, &readbytes);
|
||||||
|
|
||||||
if ((inbio->rc != APR_SUCCESS) || APR_BRIGADE_EMPTY(inbio->bb))
|
if ((inbio->rc != APR_SUCCESS) || APR_BRIGADE_EMPTY(inbio->bb))
|
||||||
{
|
{
|
||||||
@@ -398,7 +401,7 @@ static int bio_bucket_in_read(BIO *bio, char *in, int inl)
|
|||||||
inbio->bucket = APR_BRIGADE_FIRST(inbio->bb);
|
inbio->bucket = APR_BRIGADE_FIRST(inbio->bb);
|
||||||
|
|
||||||
inbio->rc = apr_bucket_read(inbio->bucket,
|
inbio->rc = apr_bucket_read(inbio->bucket,
|
||||||
&buf, &buf_len, inbio->mode);
|
&buf, &buf_len, inbio->block);
|
||||||
|
|
||||||
if (inbio->rc != APR_SUCCESS) {
|
if (inbio->rc != APR_SUCCESS) {
|
||||||
apr_bucket_delete(inbio->bucket);
|
apr_bucket_delete(inbio->bucket);
|
||||||
@@ -433,7 +436,7 @@ static int bio_bucket_in_read(BIO *bio, char *in, int inl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inbio->getline) {
|
if (inbio->mode == AP_MODE_GETLINE) {
|
||||||
/* only read from the socket once in getline mode.
|
/* only read from the socket once in getline mode.
|
||||||
* since callers buffer size is likely much larger than
|
* since callers buffer size is likely much larger than
|
||||||
* the request headers. caller can always come back for more
|
* the request headers. caller can always come back for more
|
||||||
@@ -643,7 +646,7 @@ static apr_status_t ssl_io_input_read(ssl_io_input_ctx_t *ctx,
|
|||||||
|
|
||||||
if ((bytes = char_buffer_read(&ctx->cbuf, buf, wanted))) {
|
if ((bytes = char_buffer_read(&ctx->cbuf, buf, wanted))) {
|
||||||
*len = bytes;
|
*len = bytes;
|
||||||
if ((*len >= wanted) || ctx->inbio.getline) {
|
if ((*len >= wanted) || ctx->inbio.mode == AP_MODE_GETLINE) {
|
||||||
return APR_SUCCESS;
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -664,9 +667,7 @@ static apr_status_t ssl_io_input_getline(ssl_io_input_ctx_t *ctx,
|
|||||||
const char *pos;
|
const char *pos;
|
||||||
apr_status_t status;
|
apr_status_t status;
|
||||||
|
|
||||||
ctx->inbio.getline = 1;
|
|
||||||
status = ssl_io_input_read(ctx, buf, len);
|
status = ssl_io_input_read(ctx, buf, len);
|
||||||
ctx->inbio.getline = 0;
|
|
||||||
|
|
||||||
if (status != APR_SUCCESS) {
|
if (status != APR_SUCCESS) {
|
||||||
return status;
|
return status;
|
||||||
@@ -725,6 +726,7 @@ static apr_status_t ssl_io_filter_error(ap_filter_t *f,
|
|||||||
static apr_status_t ssl_io_filter_Input(ap_filter_t *f,
|
static apr_status_t ssl_io_filter_Input(ap_filter_t *f,
|
||||||
apr_bucket_brigade *bb,
|
apr_bucket_brigade *bb,
|
||||||
ap_input_mode_t mode,
|
ap_input_mode_t mode,
|
||||||
|
apr_read_type_e block,
|
||||||
apr_off_t *readbytes)
|
apr_off_t *readbytes)
|
||||||
{
|
{
|
||||||
apr_status_t status;
|
apr_status_t status;
|
||||||
@@ -735,11 +737,12 @@ static apr_status_t ssl_io_filter_Input(ap_filter_t *f,
|
|||||||
int is_init = (mode == AP_MODE_INIT);
|
int is_init = (mode == AP_MODE_INIT);
|
||||||
|
|
||||||
/* XXX: we don't currently support peek or readbytes == -1 */
|
/* XXX: we don't currently support peek or readbytes == -1 */
|
||||||
if (mode == AP_MODE_PEEK || *readbytes == -1) {
|
if (mode == AP_MODE_EATCRLF || *readbytes == -1) {
|
||||||
return APR_ENOTIMPL;
|
return APR_ENOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->inbio.mode = is_init ? AP_MODE_BLOCKING : mode;
|
ctx->inbio.mode = mode;
|
||||||
|
ctx->inbio.block = block;
|
||||||
|
|
||||||
/* XXX: we could actually move ssl_hook_process_connection to an
|
/* XXX: we could actually move ssl_hook_process_connection to an
|
||||||
* ap_hook_process_connection but would still need to call it for
|
* ap_hook_process_connection but would still need to call it for
|
||||||
@@ -759,17 +762,20 @@ static apr_status_t ssl_io_filter_Input(ap_filter_t *f,
|
|||||||
return APR_SUCCESS;
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes > 0) {
|
if (ctx->inbio.mode == AP_MODE_READBYTES) {
|
||||||
/* Protected from truncation, bytes < MAX_SIZE_T */
|
/* Protected from truncation, bytes < MAX_SIZE_T */
|
||||||
if (bytes < len) {
|
if (bytes < len) {
|
||||||
len = (apr_size_t)bytes;
|
len = (apr_size_t)bytes;
|
||||||
}
|
}
|
||||||
ctx->inbio.getline = 0;
|
|
||||||
status = ssl_io_input_read(ctx, ctx->buffer, &len);
|
status = ssl_io_input_read(ctx, ctx->buffer, &len);
|
||||||
}
|
}
|
||||||
else {
|
else if (ctx->inbio.mode == AP_MODE_GETLINE) {
|
||||||
status = ssl_io_input_getline(ctx, ctx->buffer, &len);
|
status = ssl_io_input_getline(ctx, ctx->buffer, &len);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
/* We have no idea what you are talking about, so return an error. */
|
||||||
|
return APR_ENOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
if (status != APR_SUCCESS) {
|
if (status != APR_SUCCESS) {
|
||||||
return ssl_io_filter_error(f, bb, status);
|
return ssl_io_filter_error(f, bb, status);
|
||||||
@@ -804,7 +810,6 @@ static void ssl_io_input_add_filter(SSLFilterRec *frec, conn_rec *c,
|
|||||||
ctx->inbio.f = frec->pInputFilter;
|
ctx->inbio.f = frec->pInputFilter;
|
||||||
ctx->inbio.bb = apr_brigade_create(c->pool);
|
ctx->inbio.bb = apr_brigade_create(c->pool);
|
||||||
ctx->inbio.bucket = NULL;
|
ctx->inbio.bucket = NULL;
|
||||||
ctx->inbio.getline = 0;
|
|
||||||
ctx->inbio.cbuf.length = 0;
|
ctx->inbio.cbuf.length = 0;
|
||||||
|
|
||||||
ctx->cbuf.length = 0;
|
ctx->cbuf.length = 0;
|
||||||
|
@@ -2973,7 +2973,9 @@ 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 net_time_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_off_t *readbytes)
|
static int net_time_filter(ap_filter_t *f, apr_bucket_brigade *b,
|
||||||
|
ap_input_mode_t mode, apr_read_type_e block,
|
||||||
|
apr_off_t *readbytes)
|
||||||
{
|
{
|
||||||
int keptalive = f->c->keepalive == 1;
|
int keptalive = f->c->keepalive == 1;
|
||||||
apr_socket_t *csd = ap_get_module_config(f->c->conn_config, &core_module);
|
apr_socket_t *csd = ap_get_module_config(f->c->conn_config, &core_module);
|
||||||
@@ -2984,7 +2986,7 @@ static int net_time_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_
|
|||||||
*first_line = 1;
|
*first_line = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode != AP_MODE_INIT && mode != AP_MODE_PEEK) {
|
if (mode != AP_MODE_INIT && mode != AP_MODE_EATCRLF) {
|
||||||
if (*first_line) {
|
if (*first_line) {
|
||||||
apr_setsocketopt(csd, APR_SO_TIMEOUT,
|
apr_setsocketopt(csd, APR_SO_TIMEOUT,
|
||||||
(int)(keptalive
|
(int)(keptalive
|
||||||
@@ -2999,10 +3001,12 @@ static int net_time_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ap_get_brigade(f->next, b, mode, readbytes);
|
return ap_get_brigade(f->next, b, mode, block, readbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_off_t *readbytes)
|
static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b,
|
||||||
|
ap_input_mode_t mode, apr_read_type_e block,
|
||||||
|
apr_off_t *readbytes)
|
||||||
{
|
{
|
||||||
apr_bucket *e;
|
apr_bucket *e;
|
||||||
apr_status_t rv;
|
apr_status_t rv;
|
||||||
@@ -3046,7 +3050,7 @@ static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mod
|
|||||||
/* ### AP_MODE_PEEK is a horrific name for this mode because we also
|
/* ### AP_MODE_PEEK is a horrific name for this mode because we also
|
||||||
* eat any CRLFs that we see. That's not the obvious intention of
|
* eat any CRLFs that we see. That's not the obvious intention of
|
||||||
* this mode. Determine whether anyone actually uses this or not. */
|
* this mode. Determine whether anyone actually uses this or not. */
|
||||||
if (mode == AP_MODE_PEEK) {
|
if (mode == AP_MODE_EATCRLF) {
|
||||||
apr_bucket *e;
|
apr_bucket *e;
|
||||||
const char *c;
|
const char *c;
|
||||||
|
|
||||||
@@ -3096,7 +3100,7 @@ static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mod
|
|||||||
* This is just an all-around bad idea. We may be better off by
|
* This is just an all-around bad idea. We may be better off by
|
||||||
* just closing the socket. Determine whether anyone uses this.
|
* just closing the socket. Determine whether anyone uses this.
|
||||||
*/
|
*/
|
||||||
if (*readbytes == -1) {
|
if (mode == AP_MODE_EXHAUSTIVE) {
|
||||||
apr_bucket *e;
|
apr_bucket *e;
|
||||||
apr_off_t total;
|
apr_off_t total;
|
||||||
|
|
||||||
@@ -3110,8 +3114,8 @@ static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mod
|
|||||||
APR_BRIGADE_INSERT_TAIL(b, e);
|
APR_BRIGADE_INSERT_TAIL(b, e);
|
||||||
return APR_SUCCESS;
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
/* readbytes == 0 is "read a single line". otherwise, read a block. */
|
/* read up to the amount they specified. */
|
||||||
if (*readbytes) {
|
if (mode == AP_MODE_READBYTES) {
|
||||||
apr_off_t total;
|
apr_off_t total;
|
||||||
apr_bucket *e;
|
apr_bucket *e;
|
||||||
apr_bucket_brigade *newbb;
|
apr_bucket_brigade *newbb;
|
||||||
@@ -3119,7 +3123,7 @@ static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mod
|
|||||||
AP_DEBUG_ASSERT(*readbytes > 0);
|
AP_DEBUG_ASSERT(*readbytes > 0);
|
||||||
|
|
||||||
e = APR_BRIGADE_FIRST(ctx->b);
|
e = APR_BRIGADE_FIRST(ctx->b);
|
||||||
rv = apr_bucket_read(e, &str, &len, mode);
|
rv = apr_bucket_read(e, &str, &len, block);
|
||||||
|
|
||||||
if (APR_STATUS_IS_EAGAIN(rv)) {
|
if (APR_STATUS_IS_EAGAIN(rv)) {
|
||||||
*readbytes = 0;
|
*readbytes = 0;
|
||||||
@@ -3153,7 +3157,7 @@ static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mod
|
|||||||
const char *pos;
|
const char *pos;
|
||||||
|
|
||||||
e = APR_BRIGADE_FIRST(ctx->b);
|
e = APR_BRIGADE_FIRST(ctx->b);
|
||||||
rv = apr_bucket_read(e, &str, &len, mode);
|
rv = apr_bucket_read(e, &str, &len, block);
|
||||||
|
|
||||||
/* We should treat EAGAIN here the same as we do for EOF (brigade is
|
/* We should treat EAGAIN here the same as we do for EOF (brigade is
|
||||||
* empty). We do this by returning whatever we have read. This may
|
* empty). We do this by returning whatever we have read. This may
|
||||||
|
@@ -1550,8 +1550,8 @@ static int pass_request(request_rec *r)
|
|||||||
/* ### this "read one line" doesn't seem right... shouldn't we be
|
/* ### this "read one line" doesn't seem right... shouldn't we be
|
||||||
### reading large chunks of data or something?
|
### reading large chunks of data or something?
|
||||||
*/
|
*/
|
||||||
while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING,
|
while (ap_get_brigade(r->input_filters, bb, AP_MODE_GETLINE,
|
||||||
&zero /* read one line */) == APR_SUCCESS) {
|
APR_NONBLOCK_READ, &zero) == APR_SUCCESS) {
|
||||||
apr_bucket *e;
|
apr_bucket *e;
|
||||||
APR_BRIGADE_FOREACH(e, bb) {
|
APR_BRIGADE_FOREACH(e, bb) {
|
||||||
const char *str;
|
const char *str;
|
||||||
@@ -1656,7 +1656,9 @@ static int perchild_post_read(request_rec *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b,
|
static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b,
|
||||||
ap_input_mode_t mode, apr_off_t *readbytes)
|
ap_input_mode_t mode,
|
||||||
|
apr_read_type_e block,
|
||||||
|
apr_off_t *readbytes)
|
||||||
{
|
{
|
||||||
apr_bucket *e;
|
apr_bucket *e;
|
||||||
apr_status_t rv;
|
apr_status_t rv;
|
||||||
@@ -1664,7 +1666,8 @@ static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b,
|
|||||||
const char *str;
|
const char *str;
|
||||||
apr_size_t len;
|
apr_size_t len;
|
||||||
|
|
||||||
if ((rv = ap_get_brigade(f->next, b, mode, readbytes)) != APR_SUCCESS) {
|
if ((rv = ap_get_brigade(f->next, b, mode, block,
|
||||||
|
readbytes)) != APR_SUCCESS) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1550,8 +1550,8 @@ static int pass_request(request_rec *r)
|
|||||||
/* ### this "read one line" doesn't seem right... shouldn't we be
|
/* ### this "read one line" doesn't seem right... shouldn't we be
|
||||||
### reading large chunks of data or something?
|
### reading large chunks of data or something?
|
||||||
*/
|
*/
|
||||||
while (ap_get_brigade(r->input_filters, bb, AP_MODE_NONBLOCKING,
|
while (ap_get_brigade(r->input_filters, bb, AP_MODE_GETLINE,
|
||||||
&zero /* read one line */) == APR_SUCCESS) {
|
APR_NONBLOCK_READ, &zero) == APR_SUCCESS) {
|
||||||
apr_bucket *e;
|
apr_bucket *e;
|
||||||
APR_BRIGADE_FOREACH(e, bb) {
|
APR_BRIGADE_FOREACH(e, bb) {
|
||||||
const char *str;
|
const char *str;
|
||||||
@@ -1656,7 +1656,9 @@ static int perchild_post_read(request_rec *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b,
|
static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b,
|
||||||
ap_input_mode_t mode, apr_off_t *readbytes)
|
ap_input_mode_t mode,
|
||||||
|
apr_read_type_e block,
|
||||||
|
apr_off_t *readbytes)
|
||||||
{
|
{
|
||||||
apr_bucket *e;
|
apr_bucket *e;
|
||||||
apr_status_t rv;
|
apr_status_t rv;
|
||||||
@@ -1664,7 +1666,8 @@ static apr_status_t perchild_buffer(ap_filter_t *f, apr_bucket_brigade *b,
|
|||||||
const char *str;
|
const char *str;
|
||||||
apr_size_t len;
|
apr_size_t len;
|
||||||
|
|
||||||
if ((rv = ap_get_brigade(f->next, b, mode, readbytes)) != APR_SUCCESS) {
|
if ((rv = ap_get_brigade(f->next, b, mode, block,
|
||||||
|
readbytes)) != APR_SUCCESS) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -223,8 +223,9 @@ AP_DECLARE(int) ap_rgetline(char **s, int n, request_rec *r, int fold)
|
|||||||
if (APR_BRIGADE_EMPTY(b)) {
|
if (APR_BRIGADE_EMPTY(b)) {
|
||||||
apr_off_t zero = 0;
|
apr_off_t zero = 0;
|
||||||
if ((retval = ap_get_brigade(r->input_filters, b,
|
if ((retval = ap_get_brigade(r->input_filters, b,
|
||||||
AP_MODE_BLOCKING,
|
AP_MODE_GETLINE,
|
||||||
&zero /* readline */)) != APR_SUCCESS ||
|
APR_BLOCK_READ,
|
||||||
|
&zero)) != APR_SUCCESS ||
|
||||||
APR_BRIGADE_EMPTY(b)) {
|
APR_BRIGADE_EMPTY(b)) {
|
||||||
apr_brigade_destroy(b);
|
apr_brigade_destroy(b);
|
||||||
return -1;
|
return -1;
|
||||||
|
@@ -356,10 +356,12 @@ AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
|
|||||||
AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next,
|
AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next,
|
||||||
apr_bucket_brigade *bb,
|
apr_bucket_brigade *bb,
|
||||||
ap_input_mode_t mode,
|
ap_input_mode_t mode,
|
||||||
|
apr_read_type_e block,
|
||||||
apr_off_t *readbytes)
|
apr_off_t *readbytes)
|
||||||
{
|
{
|
||||||
if (next) {
|
if (next) {
|
||||||
return next->frec->filter_func.in_func(next, bb, mode, readbytes);
|
return next->frec->filter_func.in_func(next, bb, mode, block,
|
||||||
|
readbytes);
|
||||||
}
|
}
|
||||||
return AP_NOBODY_READ;
|
return AP_NOBODY_READ;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user