Hello,
I'm currently writing a module for 2.0 which needs to observe the traffic to and from various handlers. The approach I'm using is to register input and output filters of type AP_FTYPE_PROTOCOL+1 (so I get headers, but don't see encrypted traffic), and add them in a create_request hook. However, when I do this, I see some odd behavour, which I think is a bug.
Long story short, it looks like the HTTP input and output handlers don't get added properly. First, when I send a GET with a body, Apache blocks hangs in an attempt to read HUGE_STRING_LEN from core_in, which is caused by the HTTP input filter's absence, since normally it would trim that down based on the content-length or chunk size. Second, Apache's responses are missing their HTTP headers. (Under 2.0, I get both problems; with the latest 2.1 I only see the latter). I can provide code for a module that will create the problems.
I found a logic problem in util_filter.c, add_any_filter_handle(), which explains this. Basically, if more than one protocol filter is added to a request, the request->{input,output}_filters ptr isn't updated properly. Below is a patch. I've tested it with a 2.1 build that I got from CVS earlier today, and it solves my problem without noticably causing any others. Perhaps someone with a test environment can run this through some hoops.


Thanks,
Jim


--- server/util_filter.c.orig 2003-03-10 15:19:47.809999000 -0800 +++ server/util_filter.c 2003-03-10 16:25:52.199998000 -0800 @@ -340,24 +340,30 @@ if (INSERT_BEFORE(f, *outf)) { f->next = *outf;

-        if (*outf) {
-            ap_filter_t *first = NULL;
+        if (r) {
+            /* push the p_filter back */
+            if (outf == c_filters && *p_filters == *outf)
+                *p_filters = f;
+
+            /* push the r_filter back */
+            if ( (outf == c_filters || outf == p_filters) &&
+                    *r_filters == *outf) {
+                *r_filters = f;
+            }
+            /* now set the previous filter's next ptr (unless we just
+             * changed r_filter) */
+            else if (outf != r_filters) {
+                ap_filter_t *first = NULL;
+
+                first = *r_filters;
+                while (first && (first->next != (*outf))) {
+                    first = first->next;
+                }

-            if (r) {
-                /* If we are adding our first non-connection filter,
-                 * Then don't try to find the right location, it is
-                 * automatically first.
-                 */
-                if (*r_filters != *c_filters) {
-                    first = *r_filters;
-                    while (first && (first->next != (*outf))) {
-                        first = first->next;
-                    }
+                if (first && first != (*outf)) {
+                    first->next = f;
                 }
             }
-            if (first && first != (*outf)) {
-                first->next = f;
-            }
         }
         *outf = f;
     }



Reply via email to