Apache Portable Runtime Utility Library
|
00001 /* Licensed to the Apache Software Foundation (ASF) under one or more 00002 * contributor license agreements. See the NOTICE file distributed with 00003 * this work for additional information regarding copyright ownership. 00004 * The ASF licenses this file to You under the Apache License, Version 2.0 00005 * (the "License"); you may not use this file except in compliance with 00006 * the License. You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00021 #ifndef APR_BUCKETS_H 00022 #define APR_BUCKETS_H 00023 00024 #if defined(APR_BUCKET_DEBUG) && !defined(APR_RING_DEBUG) 00025 #define APR_RING_DEBUG 00026 #endif 00027 00028 #include "apu.h" 00029 #include "apr_network_io.h" 00030 #include "apr_file_io.h" 00031 #include "apr_general.h" 00032 #include "apr_mmap.h" 00033 #include "apr_errno.h" 00034 #include "apr_ring.h" 00035 #include "apr.h" 00036 #if APR_HAVE_SYS_UIO_H 00037 #include <sys/uio.h> /* for struct iovec */ 00038 #endif 00039 #if APR_HAVE_STDARG_H 00040 #include <stdarg.h> 00041 #endif 00042 00043 #ifdef __cplusplus 00044 extern "C" { 00045 #endif 00046 00054 #define APR_BUCKET_BUFF_SIZE 8000 00055 00057 typedef enum { 00058 APR_BLOCK_READ, 00059 APR_NONBLOCK_READ 00060 } apr_read_type_e; 00061 00114 /* 00115 * Forward declaration of the main types. 00116 */ 00117 00119 typedef struct apr_bucket_brigade apr_bucket_brigade; 00121 typedef struct apr_bucket apr_bucket; 00123 typedef struct apr_bucket_alloc_t apr_bucket_alloc_t; 00124 00126 typedef struct apr_bucket_type_t apr_bucket_type_t; 00127 00131 struct apr_bucket_type_t { 00135 const char *name; 00140 int num_func; 00151 enum { 00153 APR_BUCKET_DATA = 0, 00155 APR_BUCKET_METADATA = 1 00156 } is_metadata; 00164 void (*destroy)(void *data); 00165 00176 apr_status_t (*read)(apr_bucket *b, const char **str, apr_size_t *len, 00177 apr_read_type_e block); 00178 00192 apr_status_t (*setaside)(apr_bucket *e, apr_pool_t *pool); 00193 00203 apr_status_t (*split)(apr_bucket *e, apr_size_t point); 00204 00211 apr_status_t (*copy)(apr_bucket *e, apr_bucket **c); 00212 00213 }; 00214 00224 struct apr_bucket { 00226 APR_RING_ENTRY(apr_bucket) link; 00228 const apr_bucket_type_t *type; 00234 apr_size_t length; 00242 apr_off_t start; 00244 void *data; 00252 void (*free)(void *e); 00254 apr_bucket_alloc_t *list; 00255 }; 00256 00258 struct apr_bucket_brigade { 00264 apr_pool_t *p; 00266 /* 00267 * The apr_bucket_list structure doesn't actually need a name tag 00268 * because it has no existence independent of struct apr_bucket_brigade; 00269 * the ring macros are designed so that you can leave the name tag 00270 * argument empty in this situation but apparently the Windows compiler 00271 * doesn't like that. 00272 */ 00273 APR_RING_HEAD(apr_bucket_list, apr_bucket) list; 00275 apr_bucket_alloc_t *bucket_alloc; 00276 }; 00277 00278 00282 typedef apr_status_t (*apr_brigade_flush)(apr_bucket_brigade *bb, void *ctx); 00283 00284 /* 00285 * define APR_BUCKET_DEBUG if you want your brigades to be checked for 00286 * validity at every possible instant. this will slow your code down 00287 * substantially but is a very useful debugging tool. 00288 */ 00289 #ifdef APR_BUCKET_DEBUG 00290 00291 #define APR_BRIGADE_CHECK_CONSISTENCY(b) \ 00292 APR_RING_CHECK_CONSISTENCY(&(b)->list, apr_bucket, link) 00293 00294 #define APR_BUCKET_CHECK_CONSISTENCY(e) \ 00295 APR_RING_CHECK_ELEM_CONSISTENCY((e), apr_bucket, link) 00296 00297 #else 00298 00304 #define APR_BRIGADE_CHECK_CONSISTENCY(b) 00305 00311 #define APR_BUCKET_CHECK_CONSISTENCY(e) 00312 #endif 00313 00314 00331 #define APR_BRIGADE_SENTINEL(b) APR_RING_SENTINEL(&(b)->list, apr_bucket, link) 00332 00338 #define APR_BRIGADE_EMPTY(b) APR_RING_EMPTY(&(b)->list, apr_bucket, link) 00339 00345 #define APR_BRIGADE_FIRST(b) APR_RING_FIRST(&(b)->list) 00346 00351 #define APR_BRIGADE_LAST(b) APR_RING_LAST(&(b)->list) 00352 00358 #define APR_BRIGADE_INSERT_HEAD(b, e) do { \ 00359 apr_bucket *ap__b = (e); \ 00360 APR_RING_INSERT_HEAD(&(b)->list, ap__b, apr_bucket, link); \ 00361 APR_BRIGADE_CHECK_CONSISTENCY((b)); \ 00362 } while (0) 00363 00369 #define APR_BRIGADE_INSERT_TAIL(b, e) do { \ 00370 apr_bucket *ap__b = (e); \ 00371 APR_RING_INSERT_TAIL(&(b)->list, ap__b, apr_bucket, link); \ 00372 APR_BRIGADE_CHECK_CONSISTENCY((b)); \ 00373 } while (0) 00374 00380 #define APR_BRIGADE_CONCAT(a, b) do { \ 00381 APR_RING_CONCAT(&(a)->list, &(b)->list, apr_bucket, link); \ 00382 APR_BRIGADE_CHECK_CONSISTENCY((a)); \ 00383 } while (0) 00384 00390 #define APR_BRIGADE_PREPEND(a, b) do { \ 00391 APR_RING_PREPEND(&(a)->list, &(b)->list, apr_bucket, link); \ 00392 APR_BRIGADE_CHECK_CONSISTENCY((a)); \ 00393 } while (0) 00394 00400 #define APR_BUCKET_INSERT_BEFORE(a, b) do { \ 00401 apr_bucket *ap__a = (a), *ap__b = (b); \ 00402 APR_RING_INSERT_BEFORE(ap__a, ap__b, link); \ 00403 APR_BUCKET_CHECK_CONSISTENCY(ap__a); \ 00404 } while (0) 00405 00411 #define APR_BUCKET_INSERT_AFTER(a, b) do { \ 00412 apr_bucket *ap__a = (a), *ap__b = (b); \ 00413 APR_RING_INSERT_AFTER(ap__a, ap__b, link); \ 00414 APR_BUCKET_CHECK_CONSISTENCY(ap__a); \ 00415 } while (0) 00416 00422 #define APR_BUCKET_NEXT(e) APR_RING_NEXT((e), link) 00423 00428 #define APR_BUCKET_PREV(e) APR_RING_PREV((e), link) 00429 00434 #define APR_BUCKET_REMOVE(e) APR_RING_REMOVE((e), link) 00435 00440 #define APR_BUCKET_INIT(e) APR_RING_ELEM_INIT((e), link) 00441 00448 #define APR_BUCKET_IS_METADATA(e) ((e)->type->is_metadata) 00449 00455 #define APR_BUCKET_IS_FLUSH(e) ((e)->type == &apr_bucket_type_flush) 00456 00461 #define APR_BUCKET_IS_EOS(e) ((e)->type == &apr_bucket_type_eos) 00462 00467 #define APR_BUCKET_IS_FILE(e) ((e)->type == &apr_bucket_type_file) 00468 00473 #define APR_BUCKET_IS_PIPE(e) ((e)->type == &apr_bucket_type_pipe) 00474 00479 #define APR_BUCKET_IS_SOCKET(e) ((e)->type == &apr_bucket_type_socket) 00480 00485 #define APR_BUCKET_IS_HEAP(e) ((e)->type == &apr_bucket_type_heap) 00486 00491 #define APR_BUCKET_IS_TRANSIENT(e) ((e)->type == &apr_bucket_type_transient) 00492 00497 #define APR_BUCKET_IS_IMMORTAL(e) ((e)->type == &apr_bucket_type_immortal) 00498 #if APR_HAS_MMAP 00499 00504 #define APR_BUCKET_IS_MMAP(e) ((e)->type == &apr_bucket_type_mmap) 00505 #endif 00506 00511 #define APR_BUCKET_IS_POOL(e) ((e)->type == &apr_bucket_type_pool) 00512 00513 /* 00514 * General-purpose reference counting for the various bucket types. 00515 * 00516 * Any bucket type that keeps track of the resources it uses (i.e. 00517 * most of them except for IMMORTAL, TRANSIENT, and EOS) needs to 00518 * attach a reference count to the resource so that it can be freed 00519 * when the last bucket that uses it goes away. Resource-sharing may 00520 * occur because of bucket splits or buckets that refer to globally 00521 * cached data. */ 00522 00524 typedef struct apr_bucket_refcount apr_bucket_refcount; 00531 struct apr_bucket_refcount { 00533 int refcount; 00534 }; 00535 00536 /* ***** Reference-counted bucket types ***** */ 00537 00539 typedef struct apr_bucket_heap apr_bucket_heap; 00543 struct apr_bucket_heap { 00545 apr_bucket_refcount refcount; 00549 char *base; 00551 apr_size_t alloc_len; 00553 void (*free_func)(void *data); 00554 }; 00555 00557 typedef struct apr_bucket_pool apr_bucket_pool; 00561 struct apr_bucket_pool { 00573 apr_bucket_heap heap; 00579 const char *base; 00586 apr_pool_t *pool; 00590 apr_bucket_alloc_t *list; 00591 }; 00592 00593 #if APR_HAS_MMAP 00594 00595 typedef struct apr_bucket_mmap apr_bucket_mmap; 00599 struct apr_bucket_mmap { 00601 apr_bucket_refcount refcount; 00603 apr_mmap_t *mmap; 00604 }; 00605 #endif 00606 00608 typedef struct apr_bucket_file apr_bucket_file; 00612 struct apr_bucket_file { 00614 apr_bucket_refcount refcount; 00616 apr_file_t *fd; 00619 apr_pool_t *readpool; 00620 #if APR_HAS_MMAP 00621 00623 int can_mmap; 00624 #endif /* APR_HAS_MMAP */ 00625 00626 apr_size_t read_size; 00627 }; 00628 00630 typedef union apr_bucket_structs apr_bucket_structs; 00635 union apr_bucket_structs { 00636 apr_bucket b; 00637 apr_bucket_heap heap; 00638 apr_bucket_pool pool; 00639 #if APR_HAS_MMAP 00640 apr_bucket_mmap mmap; 00641 #endif 00642 apr_bucket_file file; 00643 }; 00644 00650 #define APR_BUCKET_ALLOC_SIZE APR_ALIGN_DEFAULT(2*sizeof(apr_bucket_structs)) 00651 00652 /* ***** Bucket Brigade Functions ***** */ 00660 APU_DECLARE(apr_bucket_brigade *) apr_brigade_create(apr_pool_t *p, 00661 apr_bucket_alloc_t *list); 00662 00668 APU_DECLARE(apr_status_t) apr_brigade_destroy(apr_bucket_brigade *b); 00669 00681 APU_DECLARE(apr_status_t) apr_brigade_cleanup(void *data); 00682 00698 APU_DECLARE(apr_bucket_brigade *) apr_brigade_split_ex(apr_bucket_brigade *b, 00699 apr_bucket *e, 00700 apr_bucket_brigade *a); 00701 00713 APU_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b, 00714 apr_bucket *e); 00715 00728 APU_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b, 00729 apr_off_t point, 00730 apr_bucket **after_point); 00731 00740 APU_DECLARE(apr_status_t) apr_brigade_length(apr_bucket_brigade *bb, 00741 int read_all, 00742 apr_off_t *length); 00743 00751 APU_DECLARE(apr_status_t) apr_brigade_flatten(apr_bucket_brigade *bb, 00752 char *c, 00753 apr_size_t *len); 00754 00762 APU_DECLARE(apr_status_t) apr_brigade_pflatten(apr_bucket_brigade *bb, 00763 char **c, 00764 apr_size_t *len, 00765 apr_pool_t *pool); 00766 00775 APU_DECLARE(apr_status_t) apr_brigade_split_line(apr_bucket_brigade *bbOut, 00776 apr_bucket_brigade *bbIn, 00777 apr_read_type_e block, 00778 apr_off_t maxbytes); 00779 00789 APU_DECLARE(apr_status_t) apr_brigade_to_iovec(apr_bucket_brigade *b, 00790 struct iovec *vec, int *nvec); 00791 00800 APU_DECLARE(apr_status_t) apr_brigade_vputstrs(apr_bucket_brigade *b, 00801 apr_brigade_flush flush, 00802 void *ctx, 00803 va_list va); 00804 00828 APU_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b, 00829 apr_brigade_flush flush, void *ctx, 00830 const char *str, apr_size_t nbyte); 00831 00841 APU_DECLARE(apr_status_t) apr_brigade_writev(apr_bucket_brigade *b, 00842 apr_brigade_flush flush, 00843 void *ctx, 00844 const struct iovec *vec, 00845 apr_size_t nvec); 00846 00855 APU_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb, 00856 apr_brigade_flush flush, void *ctx, 00857 const char *str); 00858 00867 APU_DECLARE(apr_status_t) apr_brigade_putc(apr_bucket_brigade *b, 00868 apr_brigade_flush flush, void *ctx, 00869 const char c); 00870 00879 APU_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b, 00880 apr_brigade_flush flush, 00881 void *ctx, ...); 00882 00893 APU_DECLARE_NONSTD(apr_status_t) apr_brigade_printf(apr_bucket_brigade *b, 00894 apr_brigade_flush flush, 00895 void *ctx, 00896 const char *fmt, ...) 00897 __attribute__((format(printf,4,5))); 00898 00909 APU_DECLARE(apr_status_t) apr_brigade_vprintf(apr_bucket_brigade *b, 00910 apr_brigade_flush flush, 00911 void *ctx, 00912 const char *fmt, va_list va); 00913 00926 APU_DECLARE(apr_bucket *) apr_brigade_insert_file(apr_bucket_brigade *bb, 00927 apr_file_t *f, 00928 apr_off_t start, 00929 apr_off_t len, 00930 apr_pool_t *p); 00931 00932 00933 00934 /* ***** Bucket freelist functions ***** */ 00948 APU_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create(apr_pool_t *p); 00949 00958 APU_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create_ex(apr_allocator_t *allocator); 00959 00964 APU_DECLARE_NONSTD(void) apr_bucket_alloc_destroy(apr_bucket_alloc_t *list); 00965 00974 APU_DECLARE_NONSTD(apr_size_t) apr_bucket_alloc_aligned_floor(apr_bucket_alloc_t *list, 00975 apr_size_t size) 00976 __attribute__((nonnull(1))); 00977 00983 APU_DECLARE_NONSTD(void *) apr_bucket_alloc(apr_size_t size, apr_bucket_alloc_t *list); 00984 00989 APU_DECLARE_NONSTD(void) apr_bucket_free(void *block); 00990 00991 00992 /* ***** Bucket Functions ***** */ 00999 #define apr_bucket_destroy(e) do { \ 01000 (e)->type->destroy((e)->data); \ 01001 (e)->free(e); \ 01002 } while (0) 01003 01015 #define apr_bucket_delete(e) do { \ 01016 APR_BUCKET_REMOVE(e); \ 01017 apr_bucket_destroy(e); \ 01018 } while (0) 01019 01087 #define apr_bucket_read(e,str,len,block) (e)->type->read(e, str, len, block) 01088 01095 #define apr_bucket_setaside(e,p) (e)->type->setaside(e,p) 01096 01107 #define apr_bucket_split(e,point) (e)->type->split(e, point) 01108 01114 #define apr_bucket_copy(e,c) (e)->type->copy(e, c) 01115 01116 /* Bucket type handling */ 01117 01127 APU_DECLARE_NONSTD(apr_status_t) apr_bucket_setaside_noop(apr_bucket *data, 01128 apr_pool_t *pool); 01129 01137 APU_DECLARE_NONSTD(apr_status_t) apr_bucket_setaside_notimpl(apr_bucket *data, 01138 apr_pool_t *pool); 01139 01147 APU_DECLARE_NONSTD(apr_status_t) apr_bucket_split_notimpl(apr_bucket *data, 01148 apr_size_t point); 01149 01157 APU_DECLARE_NONSTD(apr_status_t) apr_bucket_copy_notimpl(apr_bucket *e, 01158 apr_bucket **c); 01159 01169 APU_DECLARE_NONSTD(void) apr_bucket_destroy_noop(void *data); 01170 01177 /* There is no apr_bucket_read_notimpl, because it is a required function 01178 */ 01179 01180 01181 /* All of the bucket types implemented by the core */ 01186 APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_flush; 01192 APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_eos; 01196 APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_file; 01201 APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_heap; 01202 #if APR_HAS_MMAP 01203 01206 APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_mmap; 01207 #endif 01208 01213 APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_pool; 01217 APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_pipe; 01223 APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_immortal; 01229 APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_transient; 01233 APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_socket; 01234 01235 01236 /* ***** Simple buckets ***** */ 01237 01249 APU_DECLARE_NONSTD(apr_status_t) apr_bucket_simple_split(apr_bucket *b, 01250 apr_size_t point); 01251 01262 APU_DECLARE_NONSTD(apr_status_t) apr_bucket_simple_copy(apr_bucket *a, 01263 apr_bucket **b); 01264 01265 01266 /* ***** Shared, reference-counted buckets ***** */ 01267 01282 APU_DECLARE(apr_bucket *) apr_bucket_shared_make(apr_bucket *b, void *data, 01283 apr_off_t start, 01284 apr_size_t length); 01285 01294 APU_DECLARE(int) apr_bucket_shared_destroy(void *data); 01295 01307 APU_DECLARE_NONSTD(apr_status_t) apr_bucket_shared_split(apr_bucket *b, 01308 apr_size_t point); 01309 01319 APU_DECLARE_NONSTD(apr_status_t) apr_bucket_shared_copy(apr_bucket *a, 01320 apr_bucket **b); 01321 01322 01323 /* ***** Functions to Create Buckets of varying types ***** */ 01324 /* 01325 * Each bucket type foo has two initialization functions: 01326 * apr_bucket_foo_make which sets up some already-allocated memory as a 01327 * bucket of type foo; and apr_bucket_foo_create which allocates memory 01328 * for the bucket, calls apr_bucket_make_foo, and initializes the 01329 * bucket's list pointers. The apr_bucket_foo_make functions are used 01330 * inside the bucket code to change the type of buckets in place; 01331 * other code should call apr_bucket_foo_create. All the initialization 01332 * functions change nothing if they fail. 01333 */ 01334 01341 APU_DECLARE(apr_bucket *) apr_bucket_eos_create(apr_bucket_alloc_t *list); 01342 01350 APU_DECLARE(apr_bucket *) apr_bucket_eos_make(apr_bucket *b); 01351 01359 APU_DECLARE(apr_bucket *) apr_bucket_flush_create(apr_bucket_alloc_t *list); 01360 01368 APU_DECLARE(apr_bucket *) apr_bucket_flush_make(apr_bucket *b); 01369 01377 APU_DECLARE(apr_bucket *) apr_bucket_immortal_create(const char *buf, 01378 apr_size_t nbyte, 01379 apr_bucket_alloc_t *list); 01380 01388 APU_DECLARE(apr_bucket *) apr_bucket_immortal_make(apr_bucket *b, 01389 const char *buf, 01390 apr_size_t nbyte); 01391 01399 APU_DECLARE(apr_bucket *) apr_bucket_transient_create(const char *buf, 01400 apr_size_t nbyte, 01401 apr_bucket_alloc_t *list); 01402 01410 APU_DECLARE(apr_bucket *) apr_bucket_transient_make(apr_bucket *b, 01411 const char *buf, 01412 apr_size_t nbyte); 01413 01428 APU_DECLARE(apr_bucket *) apr_bucket_heap_create(const char *buf, 01429 apr_size_t nbyte, 01430 void (*free_func)(void *data), 01431 apr_bucket_alloc_t *list); 01441 APU_DECLARE(apr_bucket *) apr_bucket_heap_make(apr_bucket *b, const char *buf, 01442 apr_size_t nbyte, 01443 void (*free_func)(void *data)); 01444 01454 APU_DECLARE(apr_bucket *) apr_bucket_pool_create(const char *buf, 01455 apr_size_t length, 01456 apr_pool_t *pool, 01457 apr_bucket_alloc_t *list); 01458 01467 APU_DECLARE(apr_bucket *) apr_bucket_pool_make(apr_bucket *b, const char *buf, 01468 apr_size_t length, 01469 apr_pool_t *pool); 01470 01471 #if APR_HAS_MMAP 01472 01481 APU_DECLARE(apr_bucket *) apr_bucket_mmap_create(apr_mmap_t *mm, 01482 apr_off_t start, 01483 apr_size_t length, 01484 apr_bucket_alloc_t *list); 01485 01495 APU_DECLARE(apr_bucket *) apr_bucket_mmap_make(apr_bucket *b, apr_mmap_t *mm, 01496 apr_off_t start, 01497 apr_size_t length); 01498 #endif 01499 01506 APU_DECLARE(apr_bucket *) apr_bucket_socket_create(apr_socket_t *thissock, 01507 apr_bucket_alloc_t *list); 01514 APU_DECLARE(apr_bucket *) apr_bucket_socket_make(apr_bucket *b, 01515 apr_socket_t *thissock); 01516 01523 APU_DECLARE(apr_bucket *) apr_bucket_pipe_create(apr_file_t *thispipe, 01524 apr_bucket_alloc_t *list); 01525 01532 APU_DECLARE(apr_bucket *) apr_bucket_pipe_make(apr_bucket *b, 01533 apr_file_t *thispipe); 01534 01551 APU_DECLARE(apr_bucket *) apr_bucket_file_create(apr_file_t *fd, 01552 apr_off_t offset, 01553 apr_size_t len, 01554 apr_pool_t *p, 01555 apr_bucket_alloc_t *list); 01556 01567 APU_DECLARE(apr_bucket *) apr_bucket_file_make(apr_bucket *b, apr_file_t *fd, 01568 apr_off_t offset, 01569 apr_size_t len, apr_pool_t *p); 01570 01577 APU_DECLARE(apr_status_t) apr_bucket_file_enable_mmap(apr_bucket *b, 01578 int enabled); 01579 01590 APU_DECLARE(apr_status_t) apr_bucket_file_set_buf_size(apr_bucket *e, 01591 apr_size_t size); 01592 01594 #ifdef __cplusplus 01595 } 01596 #endif 01597 01598 #endif /* !APR_BUCKETS_H */