upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr-util / buckets / apr_brigade.c
1 /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
2  * applicable.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "apr.h"
18 #include "apr_lib.h"
19 #include "apr_strings.h"
20 #include "apr_pools.h"
21 #include "apr_tables.h"
22 #include "apr_buckets.h"
23 #include "apr_errno.h"
24 #define APR_WANT_MEMFUNC
25 #define APR_WANT_STRFUNC
26 #include "apr_want.h"
27
28 #if APR_HAVE_SYS_UIO_H
29 #include <sys/uio.h>
30 #endif
31
32 static apr_status_t brigade_cleanup(void *data) 
33 {
34     return apr_brigade_cleanup(data);
35 }
36
37 APU_DECLARE(apr_status_t) apr_brigade_cleanup(void *data)
38 {
39     apr_bucket_brigade *b = data;
40     apr_bucket *e;
41
42     /*
43      * Bah! We can't use APR_RING_FOREACH here because this bucket has
44      * gone away when we dig inside it to get the next one.
45      */
46     while (!APR_BRIGADE_EMPTY(b)) {
47         e = APR_BRIGADE_FIRST(b);
48         apr_bucket_delete(e);
49     }
50     /*
51      * We don't need to free(bb) because it's allocated from a pool.
52      */
53     return APR_SUCCESS;
54 }
55
56 APU_DECLARE(apr_status_t) apr_brigade_destroy(apr_bucket_brigade *b)
57 {
58     apr_pool_cleanup_kill(b->p, b, brigade_cleanup);
59     return apr_brigade_cleanup(b);
60 }
61
62 APU_DECLARE(apr_bucket_brigade *) apr_brigade_create(apr_pool_t *p,
63                                                      apr_bucket_alloc_t *list)
64 {
65     apr_bucket_brigade *b;
66
67     b = apr_palloc(p, sizeof(*b));
68     b->p = p;
69     b->bucket_alloc = list;
70
71     APR_RING_INIT(&b->list, apr_bucket, link);
72
73     apr_pool_cleanup_register(b->p, b, brigade_cleanup, apr_pool_cleanup_null);
74     return b;
75 }
76
77 APU_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b,
78                                                     apr_bucket *e)
79 {
80     apr_bucket_brigade *a;
81     apr_bucket *f;
82
83     a = apr_brigade_create(b->p, b->bucket_alloc);
84     /* Return an empty brigade if there is nothing left in 
85      * the first brigade to split off 
86      */
87     if (e != APR_BRIGADE_SENTINEL(b)) {
88         f = APR_RING_LAST(&b->list);
89         APR_RING_UNSPLICE(e, f, link);
90         APR_RING_SPLICE_HEAD(&a->list, e, f, apr_bucket, link);
91     }
92
93     APR_BRIGADE_CHECK_CONSISTENCY(a);
94     APR_BRIGADE_CHECK_CONSISTENCY(b);
95
96     return a;
97 }
98
99 APU_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b,
100                                                 apr_off_t point,
101                                                 apr_bucket **after_point)
102 {
103     apr_bucket *e;
104     const char *s;
105     apr_size_t len;
106     apr_status_t rv;
107
108     if (point < 0) {
109         /* this could cause weird (not necessarily SEGV) things to happen */
110         return APR_EINVAL;
111     }
112     if (point == 0) {
113         *after_point = APR_BRIGADE_FIRST(b);
114         return APR_SUCCESS;
115     }
116
117     APR_BRIGADE_CHECK_CONSISTENCY(b);
118
119     APR_BRIGADE_FOREACH(e, b) {
120         if ((e->length == (apr_size_t)(-1)) && (point > (apr_size_t)(-1))) {
121             /* XXX: point is too far out to simply split this bucket,
122              * we must fix this bucket's size and keep going... */
123             rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ);
124             if (rv != APR_SUCCESS) {
125                 *after_point = e;
126                 return rv;
127             }
128         }
129         if ((point < e->length) || (e->length == (apr_size_t)(-1))) {
130             /* We already checked e->length -1 above, so we now
131              * trust e->length < MAX_APR_SIZE_T.
132              * First try to split the bucket natively... */
133             if ((rv = apr_bucket_split(e, (apr_size_t)point)) 
134                     != APR_ENOTIMPL) {
135                 *after_point = APR_BUCKET_NEXT(e);
136                 return rv;
137             }
138
139             /* if the bucket cannot be split, we must read from it,
140              * changing its type to one that can be split */
141             rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ);
142             if (rv != APR_SUCCESS) {
143                 *after_point = e;
144                 return rv;
145             }
146
147             /* this assumes that len == e->length, which is okay because e
148              * might have been morphed by the apr_bucket_read() above, but
149              * if it was, the length would have been adjusted appropriately */
150             if (point < e->length) {
151                 rv = apr_bucket_split(e, (apr_size_t)point);
152                 *after_point = APR_BUCKET_NEXT(e);
153                 return rv;
154             }
155         }
156         if (point == e->length) {
157             *after_point = APR_BUCKET_NEXT(e);
158             return APR_SUCCESS;
159         }
160         point -= e->length;
161     }
162     *after_point = APR_BRIGADE_SENTINEL(b); 
163     return APR_INCOMPLETE;
164 }
165
166 APU_DECLARE(apr_status_t) apr_brigade_length(apr_bucket_brigade *bb,
167                                              int read_all, apr_off_t *length)
168 {
169     apr_off_t total = 0;
170     apr_bucket *bkt;
171
172     APR_BRIGADE_FOREACH(bkt, bb) {
173         if (bkt->length == (apr_size_t)(-1)) {
174             const char *ignore;
175             apr_size_t len;
176             apr_status_t status;
177
178             if (!read_all) {
179                 *length = -1;
180                 return APR_SUCCESS;
181             }
182
183             if ((status = apr_bucket_read(bkt, &ignore, &len,
184                                           APR_BLOCK_READ)) != APR_SUCCESS) {
185                 return status;
186             }
187         }
188
189         total += bkt->length;
190     }
191
192     *length = total;
193     return APR_SUCCESS;
194 }
195
196 APU_DECLARE(apr_status_t) apr_brigade_flatten(apr_bucket_brigade *bb,
197                                               char *c, apr_size_t *len)
198 {
199     apr_size_t actual = 0;
200     apr_bucket *b;
201  
202     APR_BRIGADE_FOREACH(b, bb) {
203         const char *str;
204         apr_size_t str_len;
205         apr_status_t status;
206
207         status = apr_bucket_read(b, &str, &str_len, APR_BLOCK_READ);
208         if (status != APR_SUCCESS) {
209             return status;
210         }
211
212         /* If we would overflow. */
213         if (str_len + actual > *len) {
214             str_len = *len - actual;
215         }
216
217         /* XXX: It appears that overflow of the final bucket
218          * is DISCARDED without any warning to the caller.
219          *
220          * No, we only copy the data up to their requested size.  -- jre
221          */
222         memcpy(c, str, str_len);
223
224         c += str_len;
225         actual += str_len;
226
227         /* This could probably be actual == *len, but be safe from stray
228          * photons. */
229         if (actual >= *len) {
230             break;
231         }
232     }
233
234     *len = actual;
235     return APR_SUCCESS;
236 }
237
238 APU_DECLARE(apr_status_t) apr_brigade_pflatten(apr_bucket_brigade *bb,
239                                                char **c,
240                                                apr_size_t *len,
241                                                apr_pool_t *pool)
242 {
243     apr_off_t actual;
244     apr_size_t total;
245     apr_status_t rv;
246
247     apr_brigade_length(bb, 1, &actual);
248     
249     /* XXX: This is dangerous beyond belief.  At least in the
250      * apr_brigade_flatten case, the user explicitly stated their
251      * buffer length - so we don't up and palloc 4GB for a single
252      * file bucket.  This API must grow a useful max boundry,
253      * either compiled-in or preset via the *len value.
254      *
255      * Shouldn't both fn's grow an additional return value for 
256      * the case that the brigade couldn't be flattened into the
257      * provided or allocated buffer (such as APR_EMOREDATA?)
258      * Not a failure, simply an advisory result.
259      */
260     total = (apr_size_t)actual;
261
262     *c = apr_palloc(pool, total);
263     
264     rv = apr_brigade_flatten(bb, *c, &total);
265
266     if (rv != APR_SUCCESS) {
267         return rv;
268     }
269
270     *len = total;
271     return APR_SUCCESS;
272 }
273
274 APU_DECLARE(apr_status_t) apr_brigade_split_line(apr_bucket_brigade *bbOut,
275                                                  apr_bucket_brigade *bbIn,
276                                                  apr_read_type_e block,
277                                                  apr_off_t maxbytes)
278 {
279     apr_off_t readbytes = 0;
280
281     while (!APR_BRIGADE_EMPTY(bbIn)) {
282         const char *pos;
283         const char *str;
284         apr_size_t len;
285         apr_status_t rv;
286         apr_bucket *e;
287
288         e = APR_BRIGADE_FIRST(bbIn);
289         rv = apr_bucket_read(e, &str, &len, block);
290
291         if (rv != APR_SUCCESS) {
292             return rv;
293         }
294
295         pos = memchr(str, APR_ASCII_LF, len);
296         /* We found a match. */
297         if (pos != NULL) {
298             apr_bucket_split(e, pos - str + 1);
299             APR_BUCKET_REMOVE(e);
300             APR_BRIGADE_INSERT_TAIL(bbOut, e);
301             return APR_SUCCESS;
302         }
303         APR_BUCKET_REMOVE(e);
304         if (APR_BUCKET_IS_METADATA(e) || len > APR_BUCKET_BUFF_SIZE/4) {
305             APR_BRIGADE_INSERT_TAIL(bbOut, e);
306         }
307         else {
308             if (len > 0) {
309                 rv = apr_brigade_write(bbOut, NULL, NULL, str, len);
310                 if (rv != APR_SUCCESS) {
311                     return rv;
312                 }
313             }
314             apr_bucket_destroy(e);
315         }
316         readbytes += len;
317         /* We didn't find an APR_ASCII_LF within the maximum line length. */
318         if (readbytes >= maxbytes) {
319             break;
320         }
321     }
322
323     return APR_SUCCESS;
324 }
325
326
327 APU_DECLARE(apr_status_t) apr_brigade_to_iovec(apr_bucket_brigade *b, 
328                                                struct iovec *vec, int *nvec)
329 {
330     int left = *nvec;
331     apr_bucket *e;
332     struct iovec *orig;
333     apr_size_t iov_len;
334     apr_status_t rv;
335
336     orig = vec;
337     APR_BRIGADE_FOREACH(e, b) {
338         if (left-- == 0)
339             break;
340
341         rv = apr_bucket_read(e, (const char **)&vec->iov_base, &iov_len,
342                              APR_NONBLOCK_READ);
343         if (rv != APR_SUCCESS)
344             return rv;
345         vec->iov_len = iov_len; /* set indirectly in case size differs */
346         ++vec;
347     }
348
349     *nvec = vec - orig;
350     return APR_SUCCESS;
351 }
352
353 APU_DECLARE(apr_status_t) apr_brigade_vputstrs(apr_bucket_brigade *b, 
354                                                apr_brigade_flush flush,
355                                                void *ctx,
356                                                va_list va)
357 {
358     for (;;) {
359         const char *str = va_arg(va, const char *);
360         apr_status_t rv;
361
362         if (str == NULL)
363             break;
364
365         rv = apr_brigade_write(b, flush, ctx, str, strlen(str));
366         if (rv != APR_SUCCESS)
367             return rv;
368     }
369
370     return APR_SUCCESS;
371 }
372
373 APU_DECLARE(apr_status_t) apr_brigade_putc(apr_bucket_brigade *b,
374                                            apr_brigade_flush flush, void *ctx,
375                                            const char c)
376 {
377     return apr_brigade_write(b, flush, ctx, &c, 1);
378 }
379
380 APU_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b,
381                                             apr_brigade_flush flush,
382                                             void *ctx, 
383                                             const char *str, apr_size_t nbyte)
384 {
385     apr_bucket *e = APR_BRIGADE_LAST(b);
386     apr_size_t remaining = APR_BUCKET_BUFF_SIZE;
387     char *buf = NULL;
388
389     if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)) {
390         apr_bucket_heap *h = e->data;
391
392         /* HEAP bucket start offsets are always in-memory, safe to cast */
393         remaining = h->alloc_len - (e->length + (apr_size_t)e->start);
394         buf = h->base + e->start + e->length;
395     }
396
397     if (nbyte > remaining) {
398         /* either a buffer bucket exists but is full, 
399          * or no buffer bucket exists and the data is too big
400          * to buffer.  In either case, we should flush.  */
401         if (flush) {
402             e = apr_bucket_transient_create(str, nbyte, b->bucket_alloc);
403             APR_BRIGADE_INSERT_TAIL(b, e);
404             return flush(b, ctx);
405         }
406         else {
407             e = apr_bucket_heap_create(str, nbyte, NULL, b->bucket_alloc);
408             APR_BRIGADE_INSERT_TAIL(b, e);
409             return APR_SUCCESS;
410         }
411     }
412     else if (!buf) {
413         /* we don't have a buffer, but the data is small enough
414          * that we don't mind making a new buffer */
415         buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc);
416         e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
417                                    apr_bucket_free, b->bucket_alloc);
418         APR_BRIGADE_INSERT_TAIL(b, e);
419         e->length = 0;   /* We are writing into the brigade, and
420                           * allocating more memory than we need.  This
421                           * ensures that the bucket thinks it is empty just
422                           * after we create it.  We'll fix the length
423                           * once we put data in it below.
424                           */
425     }
426
427     /* there is a sufficiently big buffer bucket available now */
428     memcpy(buf, str, nbyte);
429     e->length += nbyte;
430
431     return APR_SUCCESS;
432 }
433
434 APU_DECLARE(apr_status_t) apr_brigade_writev(apr_bucket_brigade *b,
435                                              apr_brigade_flush flush,
436                                              void *ctx,
437                                              const struct iovec *vec,
438                                              apr_size_t nvec)
439 {
440     apr_bucket *e;
441     apr_size_t total_len;
442     apr_size_t i;
443     char *buf;
444
445     /* Compute the total length of the data to be written.
446      */
447     total_len = 0;
448     for (i = 0; i < nvec; i++) {
449        total_len += vec[i].iov_len;
450     }
451
452     /* If the data to be written is very large, try to convert
453      * the iovec to transient buckets rather than copying.
454      */
455     if (total_len > APR_BUCKET_BUFF_SIZE) {
456         if (flush) {
457             for (i = 0; i < nvec; i++) {
458                 e = apr_bucket_transient_create(vec[i].iov_base,
459                                                 vec[i].iov_len,
460                                                 b->bucket_alloc);
461                 APR_BRIGADE_INSERT_TAIL(b, e);
462             }
463             return flush(b, ctx);
464         }
465         else {
466             for (i = 0; i < nvec; i++) {
467                 e = apr_bucket_heap_create((const char *) vec[i].iov_base,
468                                            vec[i].iov_len, NULL,
469                                            b->bucket_alloc);
470                 APR_BRIGADE_INSERT_TAIL(b, e);
471             }
472             return APR_SUCCESS;
473         }
474     }
475
476     i = 0;
477
478     /* If there is a heap bucket at the end of the brigade
479      * already, copy into the existing bucket.
480      */
481     e = APR_BRIGADE_LAST(b);
482     if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)) {
483         apr_bucket_heap *h = e->data;
484         apr_size_t remaining = h->alloc_len -
485             (e->length + (apr_size_t)e->start);
486         buf = h->base + e->start + e->length;
487
488         if (remaining >= total_len) {
489             /* Simple case: all the data will fit in the
490              * existing heap bucket
491              */
492             for (; i < nvec; i++) {
493                 apr_size_t len = vec[i].iov_len;
494                 memcpy(buf, (const void *) vec[i].iov_base, len);
495                 buf += len;
496             }
497             e->length += total_len;
498             return APR_SUCCESS;
499         }
500         else {
501             /* More complicated case: not all of the data
502              * will fit in the existing heap bucket.  The
503              * total data size is <= APR_BUCKET_BUFF_SIZE,
504              * so we'll need only one additional bucket.
505              */
506             const char *start_buf = buf;
507             for (; i < nvec; i++) {
508                 apr_size_t len = vec[i].iov_len;
509                 if (len > remaining) {
510                     break;
511                 }
512                 memcpy(buf, (const void *) vec[i].iov_base, len);
513                 buf += len;
514                 remaining -= len;
515             }
516             e->length += (buf - start_buf);
517             total_len -= (buf - start_buf);
518
519             if (flush) {
520                 apr_status_t rv = flush(b, ctx);
521                 if (rv != APR_SUCCESS) {
522                     return rv;
523                 }
524             }
525
526             /* Now fall through into the case below to
527              * allocate another heap bucket and copy the
528              * rest of the array.  (Note that i is not
529              * reset to zero here; it holds the index
530              * of the first vector element to be
531              * written to the new bucket.)
532              */
533         }
534     }
535
536     /* Allocate a new heap bucket, and copy the data into it.
537      * The checks above ensure that the amount of data to be
538      * written here is no larger than APR_BUCKET_BUFF_SIZE.
539      */
540     buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc);
541     e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
542                                apr_bucket_free, b->bucket_alloc);
543     for (; i < nvec; i++) {
544         apr_size_t len = vec[i].iov_len;
545         memcpy(buf, (const void *) vec[i].iov_base, len);
546         buf += len;
547     }
548     e->length = total_len;
549     APR_BRIGADE_INSERT_TAIL(b, e);
550
551     return APR_SUCCESS;
552 }
553
554 APU_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb,
555                                            apr_brigade_flush flush, void *ctx,
556                                            const char *str)
557 {
558     apr_size_t len = strlen(str);
559     apr_bucket *bkt = APR_BRIGADE_LAST(bb);
560     if (!APR_BRIGADE_EMPTY(bb) && APR_BUCKET_IS_HEAP(bkt)) {
561         /* If there is enough space available in a heap bucket
562          * at the end of the brigade, copy the string directly
563          * into the heap bucket
564          */
565         apr_bucket_heap *h = bkt->data;
566         apr_size_t bytes_avail = h->alloc_len - bkt->length;
567
568         if (bytes_avail >= len) {
569             char *buf = h->base + bkt->start + bkt->length;
570             memcpy(buf, str, len);
571             bkt->length += len;
572             return APR_SUCCESS;
573         }
574     }
575
576     /* If the string could not be copied into an existing heap
577      * bucket, delegate the work to apr_brigade_write(), which
578      * knows how to grow the brigade
579      */
580     return apr_brigade_write(bb, flush, ctx, str, len);
581 }
582
583 APU_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b, 
584                                                      apr_brigade_flush flush,
585                                                      void *ctx, ...)
586 {
587     va_list va;
588     apr_status_t rv;
589
590     va_start(va, ctx);
591     rv = apr_brigade_vputstrs(b, flush, ctx, va);
592     va_end(va);
593     return rv;
594 }
595
596 APU_DECLARE_NONSTD(apr_status_t) apr_brigade_printf(apr_bucket_brigade *b, 
597                                                     apr_brigade_flush flush,
598                                                     void *ctx, 
599                                                     const char *fmt, ...)
600 {
601     va_list ap;
602     apr_status_t rv;
603
604     va_start(ap, fmt);
605     rv = apr_brigade_vprintf(b, flush, ctx, fmt, ap);
606     va_end(ap);
607     return rv;
608 }
609
610 struct brigade_vprintf_data_t {
611     apr_vformatter_buff_t vbuff;
612
613     apr_bucket_brigade *b;  /* associated brigade */
614     apr_brigade_flush *flusher; /* flushing function */
615     void *ctx;
616
617     char *cbuff; /* buffer to flush from */
618 };
619
620 static apr_status_t brigade_flush(apr_vformatter_buff_t *buff)
621 {
622     /* callback function passed to ap_vformatter to be
623      * called when vformatter needs to buff and
624      * buff.curpos > buff.endpos
625      */
626
627     /* "downcast," have really passed a brigade_vprintf_data_t* */
628     struct brigade_vprintf_data_t *vd = (struct brigade_vprintf_data_t*)buff;
629     apr_status_t res = APR_SUCCESS;
630
631     res = apr_brigade_write(vd->b, *vd->flusher, vd->ctx, vd->cbuff,
632                           APR_BUCKET_BUFF_SIZE);
633
634     if(res != APR_SUCCESS) {
635       return -1;
636     }
637
638     vd->vbuff.curpos = vd->cbuff;
639     vd->vbuff.endpos = vd->cbuff + APR_BUCKET_BUFF_SIZE;
640
641     return res;
642 }
643
644 APU_DECLARE(apr_status_t) apr_brigade_vprintf(apr_bucket_brigade *b,
645                                               apr_brigade_flush flush,
646                                               void *ctx,
647                                               const char *fmt, va_list va)
648 {
649     /* the cast, in order of appearance */
650     struct brigade_vprintf_data_t vd;
651     char buf[APR_BUCKET_BUFF_SIZE];
652     apr_size_t written;
653
654     vd.vbuff.curpos = buf;
655     vd.vbuff.endpos = buf + APR_BUCKET_BUFF_SIZE;
656     vd.b = b;
657     vd.flusher = &flush;
658     vd.ctx = ctx;
659     vd.cbuff = buf;
660
661     written = apr_vformatter(brigade_flush, &vd.vbuff, fmt, va);
662
663     if (written == -1) {
664       return -1;
665     }
666
667     /* write out what remains in the buffer */
668     return apr_brigade_write(b, flush, ctx, buf, vd.vbuff.curpos - buf);
669 }
670