From: Ryan Bloom Date: Wed, 4 Oct 2000 23:19:33 +0000 (+0000) Subject: Connection oriented filters are now stored in the conn_rec instead of the X-Git-Tag: APACHE_2_0_ALPHA_7~55 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8b56ba850ac12304e96535fadf52539d97afb87c;p=apache Connection oriented filters are now stored in the conn_rec instead of the request_rec. This means that a conn_rec must be supplied when calling ap_add_filter. The reason for this change is that we need to be able to add the core_filter (whether or SSL or not) before we try to read the request. This way, if a request fails, we can actually send the error page back to the client. With this change, we add the core filter to the conn_rec during the pre-connection phase. Submitted by: Ryan Bloom, Jeff Trawick, and Greg Ames git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86392 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/include/httpd.h b/include/httpd.h index f222e0d4ba..77086f946f 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -885,6 +885,9 @@ struct conn_rec { /** Location to store data read from the client. * @defvar ap_bucket_brigade *input_data */ struct ap_bucket_brigade *input_data; + /** A list of output filters to be used for this connection + * @defvar ap_filter_t *filters */ + struct ap_filter_t *output_filters; }; /* Per-vhost config... */ diff --git a/include/util_filter.h b/include/util_filter.h index c7b20ba867..2b4f760590 100644 --- a/include/util_filter.h +++ b/include/util_filter.h @@ -332,7 +332,8 @@ API_EXPORT(void) ap_add_input_filter(const char *name, void *ctx, conn_rec *r); * @param r The request to add this filter for. * @deffunc void ap_add_filter(const char *name, request_rec *r) */ -API_EXPORT(void) ap_add_filter(const char *name, void *ctx, request_rec *r); +API_EXPORT(void) ap_add_filter(const char *name, void *ctx, request_rec *r, + conn_rec *c); /* The next two filters are for abstraction purposes only. They could be * done away with, but that would require that we break modules if we ever diff --git a/modules/http/http_core.c b/modules/http/http_core.c index a910a546e7..7e5d63f325 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -2564,7 +2564,7 @@ static apr_status_t writev_it_all(apr_socket_t *s, struct iovec *vec, int nvec, return APR_SUCCESS; } /* XXX handle partial writes */ -static apr_status_t send_the_file(request_rec *r, apr_file_t *fd, +static apr_status_t send_the_file(conn_rec *c, apr_file_t *fd, apr_hdtr_t *hdtr, apr_off_t offset, apr_size_t length, apr_size_t *nbytes) { @@ -2573,11 +2573,11 @@ static apr_status_t send_the_file(request_rec *r, apr_file_t *fd, apr_size_t n = length; #if APR_HAS_SENDFILE - if (!r->connection->keepalive) { + if (!c->keepalive) { /* Prepare the socket to be reused */ flags |= APR_SENDFILE_DISCONNECT_SOCKET; } - rv = apr_sendfile(r->connection->client->bsock, + rv = apr_sendfile(c->client->bsock, fd, /* The file to send */ hdtr, /* Header and trailer iovecs */ &offset, /* Offset in file to begin sending from */ @@ -2592,6 +2592,7 @@ static apr_status_t send_the_file(request_rec *r, apr_file_t *fd, return APR_SUCCESS; } + /* Note --- ErrorDocument will now work from .htaccess files. * The AllowOverride of Fileinfo allows webmasters to turn it off */ @@ -3286,7 +3287,7 @@ static int core_output_filter(ap_filter_t *f, ap_bucket_brigade *b) ap_bucket_brigade *more = NULL; apr_ssize_t bytes_sent = 0, nbytes = 0; ap_bucket *e; - request_rec *r = f->r; + conn_rec *c = f->c; core_output_filter_ctx_t *ctx = f->ctx; apr_ssize_t nvec = 0; @@ -3299,7 +3300,7 @@ static int core_output_filter(ap_filter_t *f, ap_bucket_brigade *b) apr_off_t foffset = 0; if (ctx == NULL) { - f->ctx = ctx = apr_pcalloc(r->pool, sizeof(core_output_filter_ctx_t)); + f->ctx = ctx = apr_pcalloc(c->pool, sizeof(core_output_filter_ctx_t)); } /* If we have a saved brigade, concatenate the new brigade to it */ if (ctx->b) { @@ -3309,10 +3310,10 @@ static int core_output_filter(ap_filter_t *f, ap_bucket_brigade *b) } /* Hijack any bytes in BUFF and prepend it to the brigade. */ - if (r->connection->client->outcnt) { - e = ap_bucket_create_heap(r->connection->client->outbase, - r->connection->client->outcnt, 1, NULL); - r->connection->client->outcnt = 0; + if (c->client->outcnt) { + e = ap_bucket_create_heap(c->client->outbase, + c->client->outcnt, 1, NULL); + c->client->outcnt = 0; AP_BRIGADE_INSERT_HEAD(b, e); } @@ -3376,10 +3377,10 @@ static int core_output_filter(ap_filter_t *f, ap_bucket_brigade *b) hdtr.numtrailers = nvec_trailers; hdtr.trailers = vec_trailers; } - rv = send_the_file(r, fd, &hdtr, foffset, flen, &bytes_sent); + rv = send_the_file(c, fd, &hdtr, foffset, flen, &bytes_sent); } else { - rv = writev_it_all(r->connection->client->bsock, + rv = writev_it_all(c->client->bsock, vec, nvec, nbytes, &bytes_sent); nbytes = 0; /* in case more points to another brigade */ @@ -3423,12 +3424,6 @@ static const char *core_method(const request_rec *r) static unsigned short core_port(const request_rec *r) { return DEFAULT_HTTP_PORT; } -static int core_post_read_req(request_rec *r) -{ - ap_add_filter("CORE", NULL, r); - return DECLINED; -} - static void core_register_filter(request_rec *r) { int i; @@ -3439,7 +3434,7 @@ static void core_register_filter(request_rec *r) for (i = 0; i < conf->filters->nelts; i++) { char *foobar = items[i]; - ap_add_filter(foobar, NULL, r); + ap_add_filter(foobar, NULL, r, r->connection); } } @@ -3457,7 +3452,6 @@ static void register_hooks(void) /* FIXME: I suspect we can eliminate the need for these - Ben */ ap_hook_type_checker(do_nothing,NULL,NULL,AP_HOOK_REALLY_LAST); ap_hook_access_checker(do_nothing,NULL,NULL,AP_HOOK_REALLY_LAST); - ap_hook_post_read_request(core_post_read_req, NULL, NULL, AP_HOOK_REALLY_FIRST); /* define the CORE filter, then register a hook to insert it at * request-processing time. diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index 2e6b6feafb..3d3cb942ce 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -1244,6 +1244,7 @@ request_rec *ap_read_request(conn_rec *conn) r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */ r->the_request = NULL; + r->output_filters = conn->output_filters; #ifdef APACHE_XLATE r->rrx = apr_pcalloc(p, sizeof(struct ap_rr_xlate)); @@ -2108,8 +2109,8 @@ API_EXPORT(void) ap_send_http_header(request_rec *r) if (r->chunked) { apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked"); apr_table_unset(r->headers_out, "Content-Length"); - ap_add_filter("BUFFER", NULL, r); - ap_add_filter("CHUNK", NULL, r); + ap_add_filter("BUFFER", NULL, r, r->connection); + ap_add_filter("CHUNK", NULL, r, r->connection); } if (r->byterange > 1) { diff --git a/server/connection.c b/server/connection.c index 9b1e04942e..3eb453761f 100644 --- a/server/connection.c +++ b/server/connection.c @@ -217,6 +217,7 @@ CORE_EXPORT(void) ap_process_connection(conn_rec *c) int ap_pre_http_connection(conn_rec *c) { ap_add_input_filter("CORE_IN", NULL, c); + ap_add_filter("CORE", NULL, NULL, c); return OK; } diff --git a/server/util_filter.c b/server/util_filter.c index c7641c3c3f..f95532b6aa 100644 --- a/server/util_filter.c +++ b/server/util_filter.c @@ -148,25 +148,28 @@ API_EXPORT(void) ap_add_input_filter(const char *name, void *ctx, conn_rec *c) } } -API_EXPORT(void) ap_add_filter(const char *name, void *ctx, request_rec *r) +API_EXPORT(void) ap_add_filter(const char *name, void *ctx, request_rec *r, + conn_rec *c) { ap_filter_rec_t *frec = registered_output_filters; for (; frec != NULL; frec = frec->next) { if (!strcasecmp(name, frec->name)) { - ap_filter_t *f = apr_pcalloc(r->pool, sizeof(*f)); + apr_pool_t *p = r ? r->pool : c->pool; + ap_filter_t *f = apr_pcalloc(p, sizeof(*f)); + ap_filter_t **outf = r ? &r->output_filters : &c->output_filters; f->frec = frec; f->ctx = ctx; f->r = r; - f->c = NULL; + f->c = c; - if (INSERT_BEFORE(f, r->output_filters)) { - f->next = r->output_filters; - r->output_filters = f; + if (INSERT_BEFORE(f, *outf)) { + f->next = *outf; + *outf = f; } else { - ap_filter_t *fscan = r->output_filters; + ap_filter_t *fscan = *outf; while (!INSERT_BEFORE(f, fscan->next)) fscan = fscan->next; f->next = fscan->next; @@ -201,7 +204,7 @@ API_EXPORT(apr_status_t) ap_get_brigade(ap_filter_t *next, ap_bucket_brigade *bb API_EXPORT(apr_status_t) ap_pass_brigade(ap_filter_t *next, ap_bucket_brigade *bb) { if (next) { - if (AP_BRIGADE_LAST(bb)->type == AP_BUCKET_EOS) { + if (AP_BRIGADE_LAST(bb)->type == AP_BUCKET_EOS && next->r) { next->r->eos_sent = 1; } return next->frec->filter_func(next, bb); @@ -213,12 +216,13 @@ API_EXPORT(void) ap_save_brigade(ap_filter_t *f, ap_bucket_brigade **saveto, ap_bucket_brigade **b) { ap_bucket *e; + apr_pool_t *p = f->r ? f->r->pool : f->c->pool; /* If have never stored any data in the filter, then we had better * create an empty bucket brigade so that we can concat. */ if (!(*saveto)) { - *saveto = ap_brigade_create(f->r->pool); + *saveto = ap_brigade_create(p); } AP_RING_FOREACH(e, &(*b)->list, ap_bucket, link) {