httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Doug MacEachern <do...@covalent.net>
Subject [patch] AP_MODE_INIT
Date Sat, 17 Nov 2001 00:18:11 GMT
i mentioned a while back that i had hacked jim winstead's "colobus" NNTP
server (designed to run under tcpserver or inetd) into a protocol handler
using modperl-2.0.  and that i had it working with mod_ssl.  however, to
get it working with ssl required a special case hack that didn't always
work.  nntp needs to respond to the client before the client sends any
request data.  ftp has a similar requirement, i imagine other protocols 
may as well.  the ssl filter currently assumes we will be reading request
data from the client first and does the handshake at that time.  if we try
to write the nntp welcome message before reading any client data, the
handshake hasn't happened and things break.  the patch below allows such a
protocol module to trigger the handshake, which is a noop without ssl in
the filter chain.

for a simple example of what needs to happen, see:
httpd-test/perl-framework/c-modules/nntp_like/mod_nntp_like.c
with this patch applied the test works both with and without ssl.
if somebody sees a better way todo this, you can use that test to develop
it.  or i can take a shot if there are other suggestions.

Index: include/util_filter.h
===================================================================
RCS file: /home/cvs/httpd-2.0/include/util_filter.h,v
retrieving revision 1.60
diff -u -r1.60 util_filter.h
--- include/util_filter.h	2001/10/08 16:44:04	1.60
+++ include/util_filter.h	2001/11/16 02:08:11
@@ -97,7 +97,12 @@
      *  ::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. */
-    AP_MODE_PEEK
+    AP_MODE_PEEK,
+    /*
+     * the filter should initialize the connection if needed,
+     * NNTP or FTP over SSL for example.
+     */
+    AP_MODE_INIT
 } ap_input_mode_t;
 
 /**
Index: modules/ssl/ssl_engine_io.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/ssl/ssl_engine_io.c,v
retrieving revision 1.43
diff -u -r1.43 ssl_engine_io.c
--- modules/ssl/ssl_engine_io.c	2001/11/15 20:55:13	1.43
+++ modules/ssl/ssl_engine_io.c	2001/11/16 02:08:12
@@ -202,6 +202,15 @@
     int found_eos = 0, n;
     char buf[1024];
     apr_status_t rv;
+    int do_handshake = (eMode == AP_MODE_INIT);
+ 
+    if (do_handshake) {
+        /* protocol module needs to handshake before sending
+         * data to client (e.g. NNTP or FTP)
+         */
+        *readbytes = AP_IOBUFSIZE;
+        eMode = AP_MODE_NONBLOCKING;
+    }
 
     /* Flush the output buffers. */
     churn_output(pRec);
@@ -213,6 +222,13 @@
 
     /* If we have nothing in the raw brigade, get some more. */
     if (APR_BRIGADE_EMPTY(ctx->rawb)) {
+        if (do_handshake) {
+            /* 
+             * ap_get_brigade with AP_MODE_INIT should always be called
+             * in non-blocking mode, but we need to block here
+             */
+            eMode = AP_MODE_BLOCKING;
+        }
         rv = ap_get_brigade(f->next, ctx->rawb, eMode, readbytes);
 
         if (rv != APR_SUCCESS)
@@ -289,6 +305,11 @@
      */
     rv = ssl_hook_process_connection(pRec);
 
+    if (do_handshake && (rv == APR_SUCCESS)) {
+        /* don't block after the handshake */
+        eMode = AP_MODE_NONBLOCKING;
+    }
+
     /* Flush again. */
     churn_output(pRec);
 
@@ -322,8 +343,12 @@
             return APR_SUCCESS;
         }
         if (rv == SSL_ERROR_WANT_READ) {
+            /* if eMode was originally AP_MODE_INIT,
+             * need to reset before we recurse
+             */
+            ap_input_mode_t mode = do_handshake ? AP_MODE_INIT : eMode;
             apr_off_t tempread = AP_IOBUFSIZE;
-            return churn_input(pRec, eMode, &tempread);
+            return churn_input(pRec, mode, &tempread);
         }
         return rv;
     }
Index: server/core.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/core.c,v
retrieving revision 1.98
diff -u -r1.98 core.c
--- server/core.c	2001/11/15 20:49:53	1.98
+++ server/core.c	2001/11/16 02:08:14
@@ -2790,6 +2790,20 @@
     apr_size_t len;
     int keptalive = f->c->keepalive == 1;
 
+    if (mode == AP_MODE_INIT) {
+        /*
+         * this mode is for filters that might need to 'initialize'
+         * a connection before reading request data from a client.
+         * NNTP over SSL for example needs to handshake before the 
+         * server sends the welcome message.
+         * such filters would have changed the mode before this point
+         * is reached.  however, protocol modules such as NNTP should
+         * not need to know anything about SSL.  given the example, if
+         * SSL is not in the filter chain, AP_MODE_INIT is a noop.
+         */
+        return APR_SUCCESS;
+    }
+
     if (!ctx)
     {
         ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));


Mime
View raw message