The new diff available for Flood fixes protocol errors for keepalive (file
flood_socket_keepalive.c, function keepalive_recv_resp()) mainly by
assimilating the functionality of the wantresponse and !wantresponse modes
within the readback operations, and maintaining whatever worked correctly.
Also the algorithm for reading a decimal value within the above function
was simplified (we found cases where what was replaced did not work), as
was the routine for reading a hexadecimal value (this being in the
function keepalive_read_chunk_size()), the same reason for its replacement
applying.

Since this diff is independent of other changes made recently, I have done
it off the original file in CVS/Flood 1.1, which I have in my local
directory c:\flood-1.1

Norman Tuttle, developer, OpenDemand Systems, [EMAIL PROTECTED]

PS: In a comparison between the 2 modes mentioned above (wantresponse and
!wantresponse), the Chunked Transfer-Encoding method of reading of the
body is absent from the wantresponse pathway. I was wondering whether that
was inadvertent, and if so, it looks like we will have to add this
functionality as well or our readback of data in that case will be
incomplete.

--- flood_socket_keepalive.c    2003-10-22 12:11:38.000000000 -0400
+++ \flood-1.1\flood_socket_keepalive.c 2003-09-06 00:27:38.000000000 -0400
@@ -161,17 +161,25 @@
                         write_socket(ksock->s, req);

 }

 

-/* This is really a hex evaluator function. */

 static long keepalive_read_chunk_size(char *begin_chunk)

 {

-    long OutputHex=0;

-    unsigned char Addend;

-    while (isspace(*begin_chunk)) begin_chunk++;

-    while (isxdigit(Addend=(*(begin_chunk++))))

+    char chunk[17], *end_chunk;

+    long chunk_length;

+

+    /* FIXME: Handle chunk-extension */

+    end_chunk = strstr(begin_chunk, CRLF);

+

+    if (end_chunk && end_chunk - begin_chunk < 16)

     {

-      OutputHex=(OutputHex<<4)+((Addend & 0xF)+((Addend > '9')?9:0));

+        strncpy(chunk, begin_chunk, end_chunk - begin_chunk);

+        chunk[end_chunk-begin_chunk] = '\0';

+        /* Chunks are base-16 */

+        chunk_length = strtol(chunk, &end_chunk, 16);

+        if (*end_chunk == '\0')

+            return chunk_length;

     }

-    return OutputHex;

+

+    return 0;

 }

 

 static apr_status_t keepalive_read_chunk(response_t *resp,

@@ -233,7 +241,7 @@
                     return status;

                 }

 

-                /* We got caught in the middle of a chunk last time. */

+                /* We got caught in the middle of a chunk last time. */ 

                 if (old_length < 0) {

                     b -= old_length;

                     blen += old_length;

@@ -299,7 +307,7 @@
     return APR_SUCCESS;

 }

 

-static apr_status_t keepalive_load_resp(response_t *resp,

+static apr_status_t keepalive_load_resp(response_t *resp, 

                                         keepalive_socket_t *sock,

                                         apr_size_t remaining, apr_pool_t *pool)

 {

@@ -352,7 +360,7 @@
         cp += i;

         remaining -= i;

     }

-    while (status != APR_EGENERAL && status != APR_EOF &&

+    while (status != APR_EGENERAL && status != APR_EOF && 

            status != APR_TIMEUP && (!remain || remaining));

 

     return status;

@@ -366,7 +374,6 @@
     keepalive_socket_t *ksock = (keepalive_socket_t *)sock;

     char *cl, *ecl, cls[17];

     char *current_line;

-    int keep_reading = 0;

     int i;

     response_t *new_resp;

     apr_status_t status;

@@ -400,7 +407,7 @@
         header_end = memchr(current_line, ':', line_length);

         if (header_end) {

             key_length = header_end - current_line;

-

+ 

             header_key = apr_pstrmemdup(pool, current_line, key_length);

             header_val = apr_pstrmemdup(pool, current_line + key_length + 2,

                                         line_length - key_length - 2);

@@ -413,10 +420,10 @@
     /* If this exists, we aren't keepalive anymore. */

     header = apr_table_get(new_resp->headers, "Connection");

     if (header && !strcasecmp(header, "Close")) {

-        new_resp->keepalive = 0;

+        new_resp->keepalive = 0; 

     }

     else {

-        new_resp->keepalive = 1;

+        new_resp->keepalive = 1; 

     }

 

     /* If we have a HEAD request, we shouldn't be receiving a body. */

@@ -426,12 +433,11 @@
         return APR_SUCCESS;

     }

 

-    new_resp->chunk = NULL;

-    new_resp->chunked = 0;

     header = apr_table_get(new_resp->headers, "Transfer-Encoding");

     if (header && !strcasecmp(header, "Chunked"))

     {

         new_resp->chunked = 1;

+        new_resp->chunk = NULL;

         /* Find where headers ended */

         cl = current_line;

 

@@ -443,7 +449,7 @@
         /* We have a partial chunk and we aren't at the end. */

         if (cl && *cl && (cl - (char*)new_resp->rbuf) < new_resp->rbufsize) {

             int remaining;

-

+    

             do {

                 if (new_resp->chunk) {

                     /* If we have enough space to skip over the ending CRLF,

@@ -468,13 +474,10 @@
                     chunk_length = keepalive_read_chunk_size(new_resp->chunk);

                     /* Search for the beginning of the chunk. */

                     foo = strstr(new_resp->chunk, CRLF);

-                    if (!foo)

-                    {

-                      return APR_EGENERAL; // this is a serious error 
involving violation of chunking protocol!

-                    }

+                    assert(foo);

                     new_resp->chunk = foo + 2;

-                    remaining = new_resp->rbufsize -

-                                    (int)(new_resp->chunk -

+                    remaining = new_resp->rbufsize - 

+                                    (int)(new_resp->chunk - 

                                           (char*)new_resp->rbuf);

                 }

                 else {

@@ -492,12 +495,23 @@
         header = apr_table_get(new_resp->headers, "Content-Length");

         if (!header)

         {

-            new_resp->keepalive = 0;

+            new_resp->keepalive = 0; 

         }

-        else

+

+        if (header)

         {

-          if ((content_length = atol(header))<=0) keep_reading = 1;

+            cl = (char*)header;

+            ecl = cl + strlen(cl);

+            if (ecl && ecl - cl < 16)

+            {

+                strncpy(cls, cl, ecl - cl);

+                cls[ecl-cl] = '\0';

+                content_length = strtol(cls, &ecl, 10);

+                if (*ecl != '\0')

+                    new_resp->keepalive = 0; 

+            }

         }

+

         if (new_resp->keepalive)

         {

             /* Find where we ended */

@@ -505,24 +519,20 @@
 

             /* We didn't get full headers.  Crap. */

             if (!ecl)

-                new_resp->keepalive = 0;

+                new_resp->keepalive = 0; 

             {

                 ecl += sizeof(CRLF) - 1;

                 content_length -= new_resp->rbufsize - (ecl - 
(char*)new_resp->rbuf);

-            }

+            } 

         }

     }

-

+   

     if (ksock->wantresponse)

     {

-      if (new_resp->keepalive)

-      {

-        if ((keep_reading)||(content_length>0))

-        {

-          status = keepalive_load_resp(new_resp, ksock, content_length, pool);

-        }

-      }

-      else status = keepalive_load_resp(new_resp, ksock, 0, pool);

+        if (new_resp->keepalive)

+            status = keepalive_load_resp(new_resp, ksock, content_length, 
pool);

+        else

+            status = keepalive_load_resp(new_resp, ksock, 0, pool);

     }

     else

     {

@@ -534,9 +544,9 @@
         }

         else if (new_resp->keepalive)

         {

-            while ((keep_reading || content_length) && status != APR_EGENERAL 
&&

+            while (content_length && status != APR_EGENERAL &&

                    status != APR_EOF && status != APR_TIMEUP) {

-                if ((keep_reading)||(content_length > MAX_DOC_LENGTH - 1))

+                if (content_length > MAX_DOC_LENGTH - 1)

                     i = MAX_DOC_LENGTH - 1;

                 else

                     i = content_length;

@@ -544,16 +554,14 @@
                 status = ksock_read_socket(ksock, b, &i);

 

                 content_length -= i;

-                new_resp->rbufsize += i; // This makes sure the rbufsize 
maintains the real count, required by reporting!

             }

         }

         else

         {

-            while (status != APR_EGENERAL && status != APR_EOF &&

+            while (status != APR_EGENERAL && status != APR_EOF && 

                    status != APR_TIMEUP) {

                 i = MAX_DOC_LENGTH - 1;

                 status = ksock_read_socket(ksock, b, &i);

-                new_resp->rbufsize += i; // This makes sure the rbufsize 
maintains the real count, required by reporting!

             }

         }

     }

@@ -574,7 +582,7 @@
         ksock->ssl ? ssl_close_socket(ksock->s) : close_socket(ksock->s);

         ksock->reopen_socket = 1; /* we just closed it */

     }

-

+        

     return APR_SUCCESS;

 }

 

Reply via email to