]> granicus.if.org Git - apache/commitdiff
Send the 'Close Alert' message to the peer upon closing a SSL session. This
authorMadhusudan Mathihalli <madhum@apache.org>
Sat, 28 Feb 2004 00:45:26 +0000 (00:45 +0000)
committerMadhusudan Mathihalli <madhum@apache.org>
Sat, 28 Feb 2004 00:45:26 +0000 (00:45 +0000)
required creating a new EOC (End-Of-Connection) bucket type to notify mod_ssl
that the connection is about to be closed.

Reviewed by: Joe Orton, Justin Erenkrantz

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@102793 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
include/http_connection.h
modules/ssl/ssl_engine_io.c
server/connection.c
server/core.c

diff --git a/CHANGES b/CHANGES
index 493215591c8abaaaac98f780e69434c8533b588c..6eee255c567e843a1e808013ff0dd10a17a00912 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,9 @@ Changes with Apache 2.1.0-dev
 
   [Remove entries to the current 2.0 section below, when backported]
 
+  *) mod_ssl: Send the Close Alert message to the peer before closing
+     the SSL session. [Madhusudan Mathihalli, Joe Orton]
+
   *) mod_setenvif: Remove "support" for Remote_User variable which
      never worked at all. PR 25725.  [AndrĂ© Malo]
 
index 1550fe385e9b1e08f2c62c168bb392d2b4d0c19a..75d614f37255b791ce42b38a76cb1bec32fde4d6 100644 (file)
@@ -103,6 +103,34 @@ AP_DECLARE_HOOK(int,pre_connection,(conn_rec *c, void *csd))
  */
 AP_DECLARE_HOOK(int,process_connection,(conn_rec *c))
 
+/* End Of Connection (EOC) bucket */
+
+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);
+
 #ifdef __cplusplus
 }
 #endif
index 5787c86c3117ac743dbc4af651af06131aac406e..19f763fb3b4dcd520d7a36a7c4ee16aadbc6ce74 100644 (file)
@@ -100,6 +100,7 @@ typedef struct {
     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 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl)
      */
     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)
          */
@@ -1396,6 +1398,22 @@ static apr_status_t ssl_io_filter_output(ap_filter_t *f,
                 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
+             * - issue the SSL_shutdown
+             */
+            filter_ctx->nobuffer = 1;
+            status = ssl_filter_io_shutdown(filter_ctx, f->c, 0);
+            if (status != APR_SUCCESS) {
+                ap_log_error(APLOG_MARK, APLOG_INFO, status, NULL,
+                             "SSL filter error shutting down I/O");
+            }
+            if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
+                return status;
+            }
+            break;
+        }
         else {
             /* filter output */
             const char *data;
index 0f9ac746ccfb5d1f38ce883f1e85889858b288ca..07e3341878e962410eaee61bcf936d0b354b7a44 100644 (file)
@@ -71,8 +71,15 @@ AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c)
     apr_bucket *b;
 
     bb = apr_brigade_create(c->pool, c->bucket_alloc);
+
+    /* FLUSH bucket */
     b = apr_bucket_flush_create(c->bucket_alloc);
     APR_BRIGADE_INSERT_TAIL(bb, b);
+
+    /* End Of Connection bucket */
+    b = apr_bucket_eoc_create(c->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(bb, b);
+
     ap_pass_brigade(c->output_filters, bb);
 }
 
index 2bd91f1355e4f6d0877a9daf5f9e77f91c24a5a7..467b5b06ac88498be654b6acdc4d1a0c05a6388c 100644 (file)
@@ -3854,6 +3854,9 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
             if (APR_BUCKET_IS_EOS(e)) {
                 break;
             }
+            if (AP_BUCKET_IS_EOC(e)) {
+                apr_bucket_delete(e);
+            }
             if (APR_BUCKET_IS_FLUSH(e)) {
                 if (e != APR_BRIGADE_LAST(b)) {
                     more = apr_brigade_split(b, APR_BUCKET_NEXT(e));