httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r..@covalent.net
Subject [PATCH] chunking filter.
Date Wed, 16 Aug 2000 19:02:11 GMT

This patch adds a chunking filter to Apache.  This is a pretty stupid
filter, and it would probably be good to add some more smarts to the
filter.  I think more benefit would be added by modifying the original
handler however.

I tried to remove most of the BUFF code for chunking, but I didn't work to
hard at that, because I expect the BUFF code to go away altogether very
soon.

This does work as far as I can tell.  There is one extra 0 added at the
end of response, but I think that is because I haven't completely removed
the BUFF chunking code.  At least, I can't find any other reason for it.

Ryan

Index: STATUS
===================================================================
RCS file: /home/cvs/apache-2.0/STATUS,v
retrieving revision 1.128
diff -u -d -b -w -u -r1.128 STATUS
--- STATUS	2000/08/15 14:57:21	1.128
+++ STATUS	2000/08/16 18:47:04
@@ -21,7 +21,7 @@
     * All of the bucket types must be implemented.  The list can be found
       in src/include/ap_buckets.h
 
-    * Remove Buff and IOL from the code.  To do this, a chunking and 
+    * Remove Buff and IOL from the code.  To do this, a  
       translation filter must be written.  This allows us to remove BUFF.
       IOLs can be removed as soon as somebody gets to it.
 
Index: src/CHANGES
===================================================================
RCS file: /home/cvs/apache-2.0/src/CHANGES,v
retrieving revision 1.201
diff -u -d -b -w -u -r1.201 CHANGES
--- src/CHANGES	2000/08/14 02:54:41	1.201
+++ src/CHANGES	2000/08/16 18:47:07
@@ -1,4 +1,7 @@
 Changes with Apache 2.0a6
+  *) Add a chunking filter to Apache.  This brings us one step closer
+     to removing BUFF. [Ryan Bloom]
+
   *) Apache 2.0 has been completely documented using Scandoc.  The
      docs can be generated by running 'make docs'.  [Ryan Bloom]
 
Index: src/main/buff.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/buff.c,v
retrieving revision 1.57
diff -u -d -b -w -u -r1.57 buff.c
--- src/main/buff.c	2000/08/07 19:26:00	1.57
+++ src/main/buff.c	2000/08/16 18:47:29
@@ -309,8 +309,6 @@
  */
 static void start_chunk(BUFF *fb)
 {
-    fb->outchunk = fb->outcnt;
-    fb->outcnt += CHUNK_HEADER_SIZE;
 }
 
 /*
@@ -322,69 +320,11 @@
 */
 static int end_chunk(BUFF *fb, int extra)
 {
-    int i;
-    unsigned char *strp;
-    int chunk_size;
-#ifdef CHARSET_EBCDIC
-    apr_size_t inbytes_left, outbytes_left;
-#endif
-
-    chunk_size = fb->outcnt - fb->outchunk - CHUNK_HEADER_SIZE + extra;
-    if (chunk_size == 0) {
-        /* nothing was written into this chunk, and we can't write a 0 size
-         * chunk because that signifies EOF, so just erase it
-         */
-        fb->outcnt = fb->outchunk;
-        fb->outchunk = -1;
         return 0;
     }
 
-    if (chunk_size > MAX_CHUNK_SIZE) {
-	extra -= chunk_size - MAX_CHUNK_SIZE;
-	chunk_size = MAX_CHUNK_SIZE;
-    }
 
-    /* we know this will fit because of space we saved in start_chunk() */
-    i = apr_snprintf((char *) &fb->outbase[fb->outchunk], CHUNK_HEADER_SIZE,
-                "%x", chunk_size);
 
-    /* we may have to tack some trailing spaces onto the number we just wrote
-     * in case it was smaller than our estimated size.  We've also written
-     * a \0 into the buffer with apr_snprintf so we might have to put a
-     * \r back in.
-     */
-    strp = &fb->outbase[fb->outchunk + i];
-    while (i < CHUNK_HEADER_SIZE - 2) {
-        *strp++ = ' ';
-        ++i;
-    }
-    /* CRLF intentionally left hardcoded in ascii on ebcdic boxes */
-    *strp++ = '\015';
-    *strp = '\012';
-
-#ifdef CHARSET_EBCDIC
-    /* Convert printable hex chunk size and padding from ebcdic->ascii,
-     * but leave CRLF in ascii
-     */
-    inbytes_left = outbytes_left = CHUNK_HEADER_SIZE - 2;
-    apr_xlate_conv_buffer(ap_hdrs_to_ascii,
-                          &fb->outbase[fb->outchunk], &inbytes_left,
-                          &fb->outbase[fb->outchunk], &outbytes_left);
-#endif /*CHARSET_EBCDIC*/
-
-    if (extra == 0) {
-	/* tack on the trailing CRLF, we've reserved room for this */
-	fb->outbase[fb->outcnt++] = '\015';
-	fb->outbase[fb->outcnt++] = '\012';
-    }
-
-    fb->outchunk = -1;
-    
-    return extra;
-}
-
-
-
 /*
  * Set a flag on (1) or off (0).
  */
@@ -868,58 +808,7 @@
 static apr_status_t large_write_chunk(BUFF *fb, const char *buf, apr_size_t nbyte,
                                      apr_ssize_t *bytes_written)
 {
-    apr_status_t rv;
-    apr_ssize_t total, n, amt;
-
-    ap_assert(nbyte > 0);
-    total = 0;
-    if (fb->chunk_overcommit) {
-	amt = nbyte > fb->chunk_overcommit ? fb->chunk_overcommit : nbyte;
-	rv = large_write(fb, buf, amt, &total);
-	fb->chunk_overcommit -= total;
-	if (rv != APR_SUCCESS) {
-	    *bytes_written = total;
-            return rv;
-	}
-	if (fb->chunk_overcommit) {
-	    /* above we ensured that we'd write at most the overcommit
-	       bytes -- so either we had a partial write,
-	       or we used up all of buf.  either way we're done.  */
-	    ap_assert(amt < fb->chunk_overcommit || *bytes_written < amt);
-	    *bytes_written = total;
-	    return APR_SUCCESS;
-	}
-	/* we've finished the overcommit so we end off the previous
-	   chunk, begin a new one, and shift buf
-
-           CRLF is intentionally left hardcoded in ascii on ebcdic boxes */
-	fb->outbase[0] = '\015';
-	fb->outbase[1] = '\012';
-	fb->outcnt = 2;
-	start_chunk(fb);
-	nbyte -= total;
-	buf += total;
-    }
-    ap_assert(fb->chunk_overcommit == 0 && fb->outchunk != -1);
-    while (nbyte) {
-	amt = end_chunk(fb, nbyte);
-	rv = large_write(fb, buf, amt, &n);
-	if (n < amt) {
-	    /* can only be non-blocking or an error... */
-	    fb->chunk_overcommit = amt - n;
-            *bytes_written = total + n;
-            return rv;
-	}
-	fb->outbase[0] = '\015';
-	fb->outbase[1] = '\012';
-	fb->outcnt = 2;
-	start_chunk(fb);
-	nbyte -= amt;
-	buf += amt;
-	total += amt;
-    }
-    *bytes_written = total;
-    return APR_SUCCESS;
+    return large_write(fb, buf, nbyte, bytes_written);
 }
 
 /* A wrapper for write which deals with error conditions and
Index: src/main/http_core.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_core.c,v
retrieving revision 1.100
diff -u -d -b -w -u -r1.100 http_core.c
--- src/main/http_core.c	2000/08/14 03:07:58	1.100
+++ src/main/http_core.c	2000/08/16 18:47:29
@@ -2915,6 +2915,38 @@
     return OK;
 }
 
+/* This is an incredibly stupid chunking filter.  This will need to be somewhat
+ * smart about when it actually sends the data, but this implements some sort
+ * of chunking for right now.
+ */
+static int chunk_filter(ap_filter_t *f, ap_bucket_brigade *b)
+{
+    ap_bucket *dptr = b->head;
+    int len = 0;
+    char lenstr[6];
+    int hit_eos = 0;
+
+    while (dptr) {
+        if (dptr->type == AP_BUCKET_EOS) {
+            hit_eos = 1;
+        } 
+        else {
+            len += dptr->length;
+        }
+        dptr = dptr->next;
+    }
+
+    apr_snprintf(lenstr, 6, "%x\r\n", len);
+    dptr = ap_bucket_transient_create(lenstr, 4, &len);
+    b->head->prev = dptr;
+    dptr->next = b->head;
+    b->head = dptr;
+    dptr = ap_bucket_heap_create("\r\n", 2, &len);
+    ap_brigade_append_buckets(b, dptr);
+
+    return ap_pass_brigade(f->next, b);
+}
+
 /* Default filter.  This filter should almost always be used.  It's only job
  * is to send the headers if they haven't already been sent, and then send
  * the actual data.  To send the data, we create an iovec out of the bucket
@@ -3023,6 +3055,7 @@
      */
     ap_hook_insert_filter(core_register_filter, NULL, NULL, AP_HOOK_MIDDLE);
     ap_register_filter("CORE", core_filter, AP_FTYPE_CONNECTION);
+    ap_register_filter("CHUNK", chunk_filter, AP_FTYPE_CONNECTION);
 }
 
 API_VAR_EXPORT module core_module = {
Index: src/main/http_protocol.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
retrieving revision 1.108
diff -u -d -b -w -u -r1.108 http_protocol.c
--- src/main/http_protocol.c	2000/08/14 21:33:27	1.108
+++ src/main/http_protocol.c	2000/08/16 18:47:30
@@ -1858,6 +1858,7 @@
     if (r->chunked) {
         apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
         apr_table_unset(r->headers_out, "Content-Length");
+        ap_add_filter("CHUNK", NULL, r);
     }
 
     if (r->byterange > 1)

_______________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
406 29th St.
San Francisco, CA 94131
-------------------------------------------------------------------------------


Mime
View raw message