Here's the new patch incorporating the feedback. One thing that I'd like feedback : The eoc bucket is inserted by the ap_end_connection() function(in server/connection.c) - and deleted by SSL in ssl_engine_io.c. I don't feel comfortable with it.
Is that okay ? If not, what is a good place for inserting the EOC bucket (in mod_ssl) ? Thanks -Madhu Index: server/connection.c =================================================================== RCS file: /home/cvspublic/httpd-2.0/server/connection.c,v retrieving revision 1.114 diff -u -r1.114 connection.c --- server/connection.c 9 Feb 2004 20:40:49 -0000 1.114 +++ server/connection.c 25 Feb 2004 00:41:18 -0000 @@ -65,10 +65,23 @@ #define MAX_SECS_TO_LINGER 30 #endif +AP_CORE_DECLARE(void) ap_end_connection(conn_rec *c) +{ + apr_bucket_brigade *bb; + apr_bucket *b; + + bb = apr_brigade_create(c->pool, c->bucket_alloc); + b = ap_bucket_eoc_create(c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, b); + ap_pass_brigade(c->output_filters, bb); +} + AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c) { apr_bucket_brigade *bb; apr_bucket *b; + + ap_end_connection(c); bb = apr_brigade_create(c->pool, c->bucket_alloc); b = apr_bucket_flush_create(c->bucket_alloc); Index: include/http_protocol.h =================================================================== RCS file: /home/cvspublic/httpd-2.0/include/http_protocol.h,v retrieving revision 1.87 diff -u -r1.87 http_protocol.h --- include/http_protocol.h 26 Jan 2004 22:08:06 -0000 1.87 +++ include/http_protocol.h 25 Feb 2004 00:42:48 -0000 @@ -666,6 +666,32 @@ */ AP_DECLARE_HOOK(apr_port_t,default_port,(const request_rec *r)) +AP_DECLARE_DATA extern const apr_bucket_type_t ap_bucket_type_eoc; + +/** + * Determine if a bucket is an End Of Connection (EOC) bucket + * @param e The bucket to inspect + * @return true or false + */ +#define AP_BUCKET_IS_EOC(e) (e->type == &ap_bucket_type_eoc) + +/** + * Make the bucket passed in an End Of Connection (EOC) bucket + * @param b The bucket to make into an EOC bucket + * @return The new bucket, or NULL if allocation failed + * @deffunc apr_bucket *ap_bucket_eoc_make(apr_bucket *b) + */ +AP_DECLARE(apr_bucket *) ap_bucket_eoc_make(apr_bucket *b); + +/** + * Create a bucket referring to an End Of Connection (EOC). This indicates + * that the connection will be closed. + * @param list The freelist from which this bucket should be allocated + * @return The new bucket, or NULL if allocation failed + * @deffunc apr_bucket *ap_bucket_eoc_create(apr_bucket_alloc_t *list) + */ +AP_DECLARE(apr_bucket *) ap_bucket_eoc_create(apr_bucket_alloc_t *list); + typedef struct ap_bucket_error ap_bucket_error; /** Index: modules/ssl/ssl_engine_io.c =================================================================== RCS file: /home/cvspublic/httpd-2.0/modules/ssl/ssl_engine_io.c,v retrieving revision 1.117 diff -u -r1.117 ssl_engine_io.c --- modules/ssl/ssl_engine_io.c 9 Feb 2004 20:29:22 -0000 1.117 +++ modules/ssl/ssl_engine_io.c 25 Feb 2004 01:16:28 -0000 @@ -100,6 +100,7 @@ BIO *pbioWrite; ap_filter_t *pInputFilter; ap_filter_t *pOutputFilter; + int nobuffer; /* non-zero to prevent buffering */ } ssl_filter_ctx_t; typedef struct { @@ -193,7 +194,8 @@ */ BIO_clear_retry_flags(bio); - if (!outctx->length && (inl + outctx->blen < sizeof(outctx->buffer))) { + if (!outctx->length && (inl + outctx->blen < sizeof(outctx->buffer)) && + !outctx->filter_ctx->nobuffer) { /* the first two SSL_writes (of 1024 and 261 bytes) * need to be in the same packet (vec[0].iov_base) */ @@ -1394,6 +1396,14 @@ */ apr_bucket_delete(bucket); } + } + else if (AP_BUCKET_IS_EOC(bucket)) { + /* The special "EOC" bucket means a shutdown is needed; + * turn off buffering in bio_filter_out_write. + */ + filter_ctx->nobuffer = 1; + status = ssl_filter_io_shutdown(filter_ctx, f->c, 0); + apr_bucket_delete(bucket); } else { /* filter output */ Index: server/Makefile.in =================================================================== RCS file: /home/cvspublic/httpd-2.0/server/Makefile.in,v retrieving revision 1.91 diff -u -r1.91 Makefile.in --- server/Makefile.in 2 Feb 2004 17:04:10 -0000 1.91 +++ server/Makefile.in 25 Feb 2004 00:44:05 -0000 @@ -13,7 +13,8 @@ connection.c listen.c \ mpm_common.c util_charset.c util_debug.c util_xml.c \ util_filter.c exports.c buildmark.c \ - scoreboard.c error_bucket.c protocol.c core.c request.c provider.c + scoreboard.c error_bucket.c protocol.c core.c request.c provider.c \ + eoc_bucket.c TARGETS = delete-exports $(LTLIBRARY_NAME) $(CORE_IMPLIB_FILE) export_vars.h httpd.exp ------------------------------------------------------------------------------ NEW FILE: server/eoc_bucket.c ----------------------------------------------------------------------------- /* Copyright 2000-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "http_protocol.h" #include "apr_buckets.h" static apr_status_t eoc_bucket_read(apr_bucket *b, const char **str, apr_size_t *len, apr_read_type_e block) { *str = NULL; *len = 0; return APR_SUCCESS; } APU_DECLARE(apr_bucket *) ap_bucket_eoc_make(apr_bucket *b) { b->length = 0; b->start = 0; b->data = NULL; b->type = &ap_bucket_type_eoc; return b; } APU_DECLARE(apr_bucket *) ap_bucket_eoc_create(apr_bucket_alloc_t *list) { apr_bucket *b = apr_bucket_alloc(sizeof(*b), list); APR_BUCKET_INIT(b); b->free = apr_bucket_free; b->list = list; return ap_bucket_eoc_make(b); } APU_DECLARE_DATA const apr_bucket_type_t ap_bucket_type_eoc = { "EOC", 5, APR_BUCKET_METADATA, apr_bucket_destroy_noop, eoc_bucket_read, apr_bucket_setaside_noop, apr_bucket_split_notimpl, apr_bucket_simple_copy };