On 01/06/2008 11:39 AM, Ruediger Pluem wrote:
> 
> On 01/06/2008 02:20 AM, Nick Kew wrote:
>> On Sat, 05 Jan 2008 20:28:33 +0100
>> Ruediger Pluem <[EMAIL PROTECTED]> wrote:
>>
>>> On 01/05/2008 07:04 PM, Nick Kew wrote:
>>>> On Sat, 05 Jan 2008 12:38:58 +0100
>>>> Ruediger Pluem <[EMAIL PROTECTED]> wrote:
>>>>
>>>>> Ok. Can you setup a tcpdump between proxy and server and between
>>>>> client and proxy? I guess the network traces would be very helpful
>>>>> in finding out where things are starting to get wrong.
>>>> One testcase with its tcpdump at
>>>> http://people.apache.org/~niq/2.2.7/
>>> Thanks for this, but I think this is not sufficient:
>>>
>>> 1. It seems the dump is incomplete as I cannot see a 0 chunk at the
>>> end. 2. I would prefer the binary dump as it offers more
>>> possibilities to analyse it with wireshark.
>>>
>>> Sorry for being that demanding :-)
>> Do you mean as in tcpdump -x?  I've uploaded a pair of dumps
>> (one of client-proxy, the other of proxy-server) at the same
>> location.
> 
> 

Ok, next one. I missed to set the correct state in some situations.
Can you please give it a try again?

Regards

RĂ¼diger

Index: modules/http/http_filters.c
===================================================================
--- modules/http/http_filters.c	(Revision 609355)
+++ modules/http/http_filters.c	(Arbeitskopie)
@@ -68,8 +68,43 @@
         BODY_CHUNK_PART
     } state;
     int eos_sent;
+    char chunk_ln[30];
+    char *pos;
 } http_ctx_t;
 
+static apr_status_t get_chunk_line(http_ctx_t *ctx, int len)
+{
+    /*
+     * Check if we do not overflow our chunksize / empty line buffer
+     * (ctx->chunk_ln). If we do the chunksize / empty line is bogus anyway so
+     * bail out in this case.
+     * XXX: Currently we are very limited in accepting chunk-extensions. If
+     * this is needed the chunk_ln buffer must be much larger or we must
+     * find a different way to discard them as we do not process them anyway.
+     */
+    if ((ctx->pos - ctx->chunk_ln) + len < sizeof(ctx->chunk_ln)) {
+        ctx->pos += len;
+        *(ctx->pos) = '\0';
+        /*
+         * Check if we really got a full line. If yes the
+         * last char in the just read buffer must be LF.
+         * If not advance the buffer and return APR_EAGAIN.
+         * We do not start processing until we have the
+         * full line.
+         */
+        if (ctx->pos[-1] != APR_ASCII_LF) {
+            return APR_EAGAIN;
+        }
+        /*
+         * Line is complete. So reset ctx->pos for next round.
+         */
+        ctx->pos = ctx->chunk_ln;
+        return APR_SUCCESS;
+    }
+    return APR_ENOSPC;
+}
+
+
 /* This is the HTTP_INPUT filter for HTTP requests and responses from
  * proxied servers (mod_proxy).  It handles chunked and content-length
  * bodies.  This can only be inserted/used after the headers
@@ -96,6 +131,7 @@
         ctx->remaining = 0;
         ctx->limit_used = 0;
         ctx->eos_sent = 0;
+        ctx->pos = ctx->chunk_ln;
 
         /* LimitRequestBody does not apply to proxied responses.
          * Consider implementing this check in its own filter.
@@ -227,9 +263,8 @@
 
         /* We can't read the chunk until after sending 100 if required. */
         if (ctx->state == BODY_CHUNK) {
-            char line[30];
             apr_bucket_brigade *bb;
-            apr_size_t len = 30;
+            apr_size_t len = sizeof(ctx->chunk_ln) - (ctx->pos - ctx->chunk_ln);
             apr_off_t brigade_length;
 
             bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
@@ -256,9 +291,17 @@
                     rv = APR_ENOSPC;
                 }
                 if (rv == APR_SUCCESS) {
-                    rv = apr_brigade_flatten(bb, line, &len);
+                    rv = apr_brigade_flatten(bb, ctx->pos, &len);
                     if (rv == APR_SUCCESS) {
-                        ctx->remaining = get_chunk_size(line);
+                        rv = get_chunk_line(ctx, len);
+                        if (APR_STATUS_IS_EAGAIN(rv)) {
+                            apr_brigade_cleanup(bb);
+                            ctx->state = BODY_CHUNK_PART;
+                            return rv;
+                        }
+                        if (rv == APR_SUCCESS) {
+                            ctx->remaining = get_chunk_size(ctx->chunk_ln);
+                        }
                     }
                 }
             }
@@ -308,9 +351,9 @@
         case BODY_CHUNK:
         case BODY_CHUNK_PART:
             {
-                char line[30];
                 apr_bucket_brigade *bb;
-                apr_size_t len = 30;
+                apr_size_t len = sizeof(ctx->chunk_ln)
+                                 - (ctx->pos - ctx->chunk_ln);
                 apr_status_t http_error = HTTP_REQUEST_ENTITY_TOO_LARGE;
 
                 bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
@@ -319,11 +362,21 @@
                 if (ctx->state == BODY_CHUNK) {
                     rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
                                         block, 0);
-                    apr_brigade_cleanup(bb);
                     if (block == APR_NONBLOCK_READ &&
-                        (APR_STATUS_IS_EAGAIN(rv))) {
+                        ( (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) ||
+                          (APR_STATUS_IS_EAGAIN(rv)) )) {
                         return APR_EAGAIN;
                     }
+                    rv = apr_brigade_flatten(bb, ctx->pos, &len);
+                    apr_brigade_cleanup(bb);
+                    if (rv == APR_SUCCESS) {
+                        rv = get_chunk_line(ctx, len);
+                        if (APR_STATUS_IS_EAGAIN(rv)) {
+                            return rv;
+                        }
+                    }
+                    /* Reset len */
+                    len = sizeof(ctx->chunk_ln) - (ctx->pos - ctx->chunk_ln);
                 } else {
                     rv = APR_SUCCESS;
                 }
@@ -341,7 +394,7 @@
                     }
                     ctx->state = BODY_CHUNK;
                     if (rv == APR_SUCCESS) {
-                        rv = apr_brigade_flatten(bb, line, &len);
+                        rv = apr_brigade_flatten(bb, ctx->pos, &len);
                         if (rv == APR_SUCCESS) {
                             /* Wait a sec, that's a blank line!  Oh no. */
                             if (!len) {
@@ -349,7 +402,15 @@
                                 http_error = HTTP_SERVICE_UNAVAILABLE;
                             }
                             else {
-                                ctx->remaining = get_chunk_size(line);
+                                rv = get_chunk_line(ctx, len);
+                                if (APR_STATUS_IS_EAGAIN(rv)) {
+                                    ctx->state = BODY_CHUNK_PART;
+                                    apr_brigade_cleanup(bb);
+                                    return rv;
+                                }
+                               if (rv == APR_SUCCESS) {
+                                   ctx->remaining = get_chunk_size(ctx->chunk_ln);
+                               }
                             }
                         }
                     }

Reply via email to