]> granicus.if.org Git - apache/commitdiff
Reduce the manualarity of managing bucket brigade lists by using the
authorTony Finch <fanf@apache.org>
Fri, 8 Sep 2000 10:16:14 +0000 (10:16 +0000)
committerTony Finch <fanf@apache.org>
Fri, 8 Sep 2000 10:16:14 +0000 (10:16 +0000)
new AP_RING macros. Most of this commit is fairly pedestrian as you
would expect, but I had to redo the chunking filter because of the
amount of pointer juggling it did. I have done some minimal testing
of this patch and it seems to work.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86178 13f79535-47bb-0310-9956-ffa450edef68

modules/generators/mod_cgi.c
modules/http/http_core.c
modules/http/http_protocol.c
server/util_filter.c

index d929167181f47251d2fb3128b816b553c9dc4fcc..569c2718da5ff7380524363402787ee764a96ec9 100644 (file)
@@ -656,8 +656,8 @@ static int cgi_handler(request_rec *r)
        ap_send_http_header(r);
        if (!r->header_only) {
             bb = ap_brigade_create(r->pool);
-            ap_brigade_append_buckets(bb, ap_bucket_create_pipe(script_in));
-            ap_brigade_append_buckets(bb, ap_bucket_create_eos());
+            ap_brigade_add_bucket(bb, ap_bucket_create_pipe(script_in));
+            ap_brigade_add_bucket(bb, ap_bucket_create_eos());
        }
         ap_pass_brigade(r->filters, bb);
 
@@ -667,8 +667,8 @@ static int cgi_handler(request_rec *r)
 
     if (script_in && nph) {
         bb = ap_brigade_create(r->pool);
-        ap_brigade_append_buckets(bb, ap_bucket_create_pipe(script_in));
-        ap_brigade_append_buckets(bb, ap_bucket_create_eos());
+        ap_brigade_add_bucket(bb, ap_bucket_create_pipe(script_in));
+        ap_brigade_add_bucket(bb, ap_bucket_create_eos());
         ap_pass_brigade(r->filters, bb);
     }
 
index 43b87336d7fbeb7624c3066054114c6f696aa0c4..cdedb158217f8711c731d394a997f0f1aa096a01 100644 (file)
@@ -2914,89 +2914,77 @@ static int default_handler(request_rec *r)
     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.
+/*
+ * Turn a bucket brigade into a properly-formatted HTTP/1.1 chunk
+ * before passing it down to the next filter.
+ */
+static apr_status_t pass_chunk(ap_filter_t *f, ap_bucket_brigade *b,
+                              apr_off_t bytes, int eos)
+{
+    char chunk_hdr[20]; /* enough space for the snprintf below */
+    size_t hdr_len;
+    ap_bucket *e;
+
+    if (bytes == 0) {
+       return APR_SUCCESS;
+    }
+    hdr_len = apr_snprintf(chunk_hdr, sizeof(chunk_hdr), "%qx" CRLF, bytes);
+    e = ap_bucket_create_transient(chunk_hdr, hdr_len);
+    AP_RING_INSERT_HEAD(&b->list, e, link);
+    if (eos) {
+       /* any trailer should go between the last two CRLFs */
+       e = ap_bucket_create_immortal(CRLF "0" CRLF CRLF, 7);
+       AP_RING_INSERT_BEFORE(AP_RING_LAST(&b->list), e, link);
+    } else {
+       e = ap_bucket_create_immortal(CRLF, 2);
+       AP_RING_INSERT_TAIL(&b->list, e, link);
+    }
+    return ap_pass_brigade(f->next, b);
+}
+
+/*
+ * HTTP/1.1 chunked transfer encoding filter.
  */
 static apr_status_t chunk_filter(ap_filter_t *f, ap_bucket_brigade *b)
 {
-    ap_bucket *dptr = b->head, *lb, *next, *tail;
-    int len = 0, cur_len;
-    char lenstr[sizeof("ffffffff\r\n")];
-    const char *cur_str;
-    int hit_eos = 0;
-    apr_status_t rv = APR_SUCCESS;
-
-    while (dptr) {
-        if (dptr->type == AP_BUCKET_EOS) {
-            hit_eos = 1;
-            break;
-        } 
-        else if (dptr->length == -1) { /* indeterminate (e.g., a pipe) */
-            dptr->read(dptr, &cur_str, &cur_len, 0);
-            if (cur_len) {
-                len += cur_len;
-                /* write out what we have so far */
-                apr_snprintf(lenstr, sizeof(lenstr), "%x\r\n", len);
-                lb = ap_bucket_create_transient(lenstr, strlen(lenstr));
-                lb->next = b->head;
-                lb->next->prev = lb;
-                b->head = lb;
-                next = dptr->next;
-                tail = b->tail;
-                b->tail = ap_bucket_create_transient("\r\n", 2);
-                dptr->next = b->tail;
-                b->tail->prev = dptr;
-                rv = ap_pass_brigade(f->next, b);
-                if (rv != APR_SUCCESS) {
-                    return rv;
-                }
-                /* start a new brigade */
-                len = 0;
-                b = ap_brigade_create(f->r->pool);
-                dptr = next;
-                b->head = dptr;
-                b->tail = tail;
-            }
-            else {
-                dptr = dptr->next;
-            }
-        }
-        else {
-            len += dptr->length;
-            dptr = dptr->next;
-        }
-    }
-    if (len) {
-        apr_snprintf(lenstr, sizeof(lenstr), "%x\r\n", len);
-        lb = ap_bucket_create_transient(lenstr, strlen(lenstr));
-        lb->next = b->head;
-        lb->next->prev = lb;
-        b->head = lb;
-        lb = ap_bucket_create_transient("\r\n", 2);
-        if (hit_eos) {
-            b->tail->prev->next = lb;
-            lb->prev = b->tail->prev;
-            b->tail->prev = lb;
-            lb->next = b->tail;
-        }
-        else {
-            ap_brigade_append_buckets(b, lb);
-        }
-    }
-    if (hit_eos) {
-        lb = ap_bucket_create_transient("0\r\n\r\n", 5);
-        if (b->tail->prev) {
-            b->tail->prev->next = lb;
-        }
-        lb->prev = b->tail->prev;
-        b->tail->prev = lb;
-        lb->next = b->tail;
-        if (b->head == b->tail) {
-            b->head = lb;
-        }
+    ap_bucket_brigade *more = NULL;
+    ap_bucket *e;
+    apr_status_t rv;
+
+    for (more = NULL; b; b = more, more = NULL) {
+       apr_off_t bytes = 0;
+       int eos = 0;
+       AP_RING_FOREACH(e, &b->list, ap_bucket, link) {
+           if (e->type == AP_BUCKET_EOS) {
+               /* assume it is the last one in the brigade */
+               eos = 1;
+               break;
+           }
+           else if (e->length == -1) { /* indeterminate (e.g., a pipe) */
+               const char *data;
+               apr_ssize_t len;
+               rv = e->read(e, &data, &len, 1);
+               if (rv != APR_SUCCESS) {
+                   return rv;
+               }
+               bytes += len;
+               more = ap_brigade_split(b, AP_RING_NEXT(e, link));
+               break;
+           }
+           else {
+               bytes += e->length;
+           }
+       }
+       /*
+        * XXX: if there aren't very many bytes at this point it may
+        * be a good idea to set them aside and return for more.
+        */
+       rv = pass_chunk(f, b, bytes, eos);
+       if (rv != APR_SUCCESS || eos) {
+           return rv;
+       }
     }
-    return ap_pass_brigade(f->next, b);
+    return APR_SUCCESS;
 }
 
 /* Default filter.  This filter should almost always be used.  Its only job
@@ -3017,11 +3005,11 @@ static int core_filter(ap_filter_t *f, ap_bucket_brigade *b)
 #endif
     apr_status_t rv;
     apr_ssize_t bytes_sent = 0;
-    ap_bucket *dptr = b->head;
+    ap_bucket *e;
     int len = 0, written;
     const char *str;
-
-#if 0
+    
+#if 0 /* XXX: bit rot! */
     /* This will all be needed once BUFF is removed from the code */
     /* At this point we need to discover if there was any data saved from
      * the last call to core_filter.
@@ -3042,16 +3030,19 @@ static int core_filter(ap_filter_t *f, ap_bucket_brigade *b)
     } 
     else {
 #endif
-    while (dptr->read(dptr, &str, &len, 0) != AP_END_OF_BRIGADE) {
-        if ((rv = ap_bwrite(f->r->connection->client, str, len, &written))
-            != APR_SUCCESS) {
+    AP_RING_FOREACH(e, &b->list, ap_bucket, link) {
+       rv = e->read(e, &str, &len, 0);
+       if (rv != APR_SUCCESS) {
             return rv;
         }
-        dptr = dptr->next;
-        bytes_sent += written;
-        if (!dptr) {
-            break;
+       if (len == AP_END_OF_BRIGADE) {
+           break;
+       }
+        rv = ap_bwrite(f->r->connection->client, str, len, &written);
+       if (rv != APR_SUCCESS) {
+            return rv;
         }
+        bytes_sent += written;
     }
     ap_brigade_destroy(b);
     /* This line will go away as soon as the BUFFs are removed */
index d74516814c0de4a27ee1df4186c9ddf67529b177..0969613a759e29198945a8b17ae75eca32531814 100644 (file)
@@ -1329,7 +1329,7 @@ static void end_output_stream(request_rec *r)
     ap_bucket_brigade *bb;
 
     bb = ap_brigade_create(r->pool);
-    ap_brigade_append_buckets(bb, ap_bucket_create_eos());
+    ap_brigade_add_bucket(bb, ap_bucket_create_eos());
     ap_pass_brigade(r->filters, bb);
 }
 
@@ -2519,7 +2519,7 @@ API_EXPORT(size_t) ap_send_mmap(apr_mmap_t *mm, request_rec *r, size_t offset,
      * until after the commit to actually write the code.
      */
     bb = ap_brigade_create(r->pool);
-    ap_brigade_append_buckets(bb, ap_bucket_create_mmap(mm, 0, mm->size));
+    ap_brigade_add_bucket(bb, ap_bucket_create_mmap(mm, 0, mm->size));
     ap_pass_brigade(r->filters, bb);
 
     return mm->size; /* XXX - change API to report apr_status_t? */
@@ -2535,7 +2535,7 @@ API_EXPORT(int) ap_rputc(int c, request_rec *r)
         return EOF;
 
     bb = ap_brigade_create(r->pool);
-    ap_brigade_append_buckets(bb, ap_bucket_create_transient(&c2, 1)); 
+    ap_brigade_add_bucket(bb, ap_bucket_create_transient(&c2, 1)); 
     ap_pass_brigade(r->filters, bb);
 
     return c;
@@ -2553,7 +2553,7 @@ API_EXPORT(int) ap_rputs(const char *str, request_rec *r)
 
     len = strlen(str);
     bb = ap_brigade_create(r->pool);
-    ap_brigade_append_buckets(bb, ap_bucket_create_transient(str, len));
+    ap_brigade_add_bucket(bb, ap_bucket_create_transient(str, len));
     ap_pass_brigade(r->filters, bb);
 
     return len;
@@ -2569,7 +2569,7 @@ API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
         return 0;
 
     bb = ap_brigade_create(r->pool);
-    ap_brigade_append_buckets(bb, ap_bucket_create_transient(buf, nbyte)); 
+    ap_brigade_add_bucket(bb, ap_bucket_create_transient(buf, nbyte)); 
     ap_pass_brigade(r->filters, bb);
     return nbyte;
 }
index 491a52b379429fa23b18016bb02706d6b09f7837..5146bbfc9efd78e40aeea01ddf48ba8058710de1 100644 (file)
@@ -189,7 +189,7 @@ API_EXPORT(ap_bucket_brigade *) ap_get_saved_data(ap_filter_t *f,
 API_EXPORT(void) ap_save_data_to_filter(ap_filter_t *f, ap_bucket_brigade **b)
 {
     ap_bucket_brigade *bb = (ap_bucket_brigade *)f->ctx;
-    ap_bucket *dptr = bb->head;
+    ap_bucket *e;
 
     /* If have never stored any data in the filter, then we had better
      * create an empty bucket brigade so that we can concat.
@@ -198,15 +198,9 @@ API_EXPORT(void) ap_save_data_to_filter(ap_filter_t *f, ap_bucket_brigade **b)
         bb = ap_brigade_create(f->r->pool);
     }
     
-    while (dptr) {
-        if (dptr->setaside) {
-            dptr->setaside(dptr);
-        }
+    AP_RING_FOREACH(e, &bb->list, ap_bucket, link) {
+       e->setaside(e);
     }
-
-    /* Apend b to bb.  This means b is now empty, and we can destory it safely. 
-     */
     ap_brigade_catenate(bb, *b);
-    ap_brigade_destroy(*b);
     f->ctx = bb;
 }