On Mon, Jan 23, 2012 at 09:39:38PM +0100, Stefan Fritsch wrote:
> This patch allows us to later add members to core_ctx_t without 
> breaking binary compatibility to mod_ftp. Without such a patch, the 
> size of core_ctx_t is part of the ABI, which is bad.
> 
> Opinions?

After thinking about it more: the WinNT MPM use of this facility still 
seems unnecessary.  The same effect could be achieved using an input 
filter which returns the extra data from AcceptEx.

Here's a proof of concept for prefork, which prepends "GET" to data 
received from the socket - no core hacks required.  (This is dumb and 
should be more sophisticated, it would need to handle 
AP_MODE_GETBYTES/AP_MODE_GETLINE if possible from the "extra" data 
alone, without always fetching a brigade from the socket)

For mod_ftp the need to replace the socket bucket looks more convincing, 
but still surely a hook calling *out* from the core is better?

  AP_DECLARE_HOOK(int, insert_network_bucket, 
      (connection_conn *c, apr_bucket_brigade *bb, apr_socket_t *socket));

then core i.f. does

         net->in_ctx = ctx = ap_create_core_ctx(f->c);

         ap_run_insert_network_bucket(c, ctx->b, net->client_socket);

and mod_ftp can insert its polling data bucket there instead?

(I haven't thought this one through, I admit, handwaving may be 
required)

Index: server/mpm/prefork/prefork.c
===================================================================
--- server/mpm/prefork/prefork.c        (revision 1235252)
+++ server/mpm/prefork/prefork.c        (working copy)
@@ -95,6 +95,8 @@
 static int mpm_state = AP_MPMQ_STARTING;
 static ap_pod_t *pod;
 
+static ap_filter_rec_t *prefork_filter_handle;
+
 /* data retained by prefork across load/unload of the module
  * allocated on first call to pre-config hook; located on
  * subsequent calls to pre-config hook
@@ -468,6 +470,23 @@
 #endif
 }
 
+static apr_status_t prefork_filter(ap_filter_t *f, apr_bucket_brigade *bb,
+                                   ap_input_mode_t mode, apr_read_type_e block,
+                                   apr_off_t bytes)
+{
+    apr_status_t rv;
+    const char *string = f->ctx;
+
+    rv = ap_get_brigade(f->next, bb, mode, block, bytes);
+    if (rv == APR_SUCCESS && string) {    
+        apr_bucket *e = apr_bucket_immortal_create(string, strlen(string), 
f->c->bucket_alloc);
+        APR_BRIGADE_INSERT_HEAD(bb, e);
+        f->ctx = NULL;
+    }
+
+    return rv;
+}
+
 /*****************************************************************
  * Child process main loop.
  * The following vars are static to avoid getting clobbered by longjmp();
@@ -691,6 +710,10 @@
 
         current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, 
my_child_num, sbh, bucket_alloc);
         if (current_conn) {
+            
+            ap_add_input_filter_handle(prefork_filter_handle, "GET",
+                                       NULL, current_conn);
+
 #if APR_HAS_THREADS
             current_conn->current_thread = thd;
 #endif
@@ -1454,6 +1477,10 @@
     ap_hook_mpm(prefork_run, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_mpm_query(prefork_query, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_mpm_get_name(prefork_get_name, NULL, NULL, APR_HOOK_MIDDLE);
+
+    prefork_filter_handle = 
+        ap_register_input_filter("PREFORK", prefork_filter, NULL,
+                                 AP_FTYPE_NETWORK - 1);
 }
 
 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const 
char *arg)

Reply via email to