blob: b8c2e4afd51eb8cb421d23ba2f3722d8fd7c1285 [file] [log] [blame]
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#ifndef AP_BUCKETS_H
#define AP_BUCKETS_H
#include "httpd.h"
#include "apr_general.h"
#include "apr_mmap.h"
#include "apr_errno.h"
#include "ap_ring.h"
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h> /* for struct iovec */
#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
/**
* @package Bucket Brigades
*/
typedef enum {AP_NONBLOCK_READ, AP_BLOCK_READ} ap_read_type;
/*
* The one-sentence buzzword-laden overview: Bucket brigades represent
* a complex data stream that can be passed through a layered IO
* system without unnecessary copying. A longer overview follows...
*
* A bucket brigade is a doubly linked list of buckets, so we
* aren't limited to inserting at the front and removing at the end.
* Buckets are only passed around as members of a brigade, although
* singleton buckets can occur for short periods of time.
*
* Buckets are data stores of varous types. They can refer to data in
* memory, or part of a file or mmap area, or the output of a process,
* etc. Buckets also have some type-dependent accessor functions:
* read, split, setaside, and destroy.
*
* read returns the address and size of the data in the bucket. If the
* data isn't in memory then it is read in and the bucket changes type
* so that it can refer to the new location of the data. If all the
* data doesn't fit in the bucket then a new bucket is inserted into
* the brigade to hold the rest of it.
*
* split divides the data in a bucket into two regions. After a split
* the original bucket refers to the first part of the data and a new
* bucket inserted into the brigade after the original bucket refers
* to the second part of the data. Reference counts are maintained as
* necessary.
*
* setaside ensures that the data in the bucket has a long enough
* lifetime. Sometimes it is convenient to create a bucket referring
* to data on the stack in the expectation that it will be consumed
* (output to the network) before the stack is unwound. If that
* expectation turns out not to be valid, the setaside function is
* called to move the data somewhere safer.
*
* destroy maintains the reference counts on the resources used by a
* bucket and frees them if necessary.
*
* To write a bucket brigade, they are first made into an iovec, so that we
* don't write too little data at one time. Currently we ignore compacting the
* buckets into as few buckets as possible, but if we really want good
* performance, then we need to compact the buckets before we convert to an
* iovec, or possibly while we are converting to an iovec.
*/
/* The types of bucket brigades the code knows about. We don't really need
* this enum. All access to the bucket brigades is done through function
* pointers in the bucket type.
*/
/**
* Forward declaration of the main types.
*/
typedef struct ap_bucket_brigade ap_bucket_brigade;
typedef struct ap_bucket ap_bucket;
typedef struct ap_bucket_type ap_bucket_type;
struct ap_bucket_type {
/**
* The name of the bucket type
*/
const char *name;
/**
* The number of functions this bucket understands. Can not be less than
* four.
*/
int num_func;
/**
* Free the private data and any resources used by the bucket
* (if they aren't shared with another bucket).
* @param data The private data pointer from the bucket to be destroyed
*/
void (*destroy)(void *data);
/** Read the data from the bucket.
* @param b The bucket to read from
* @param str A place to store the data read. Allocation should only be
* done if absolutely necessary.
* @param len The amount of data read.
* @param block Should this read function block if there is more data that
* cannot be read immediately.
* @deffunc apr_status_t read(ap_bucket *b, const char **str, apr_size_t *len, ap_read_type block)
*/
apr_status_t (*read)(ap_bucket *b, const char **str, apr_size_t *len, ap_read_type block);
/** Make it possible to set aside the data. For most bucket types this is
* a no-op; buckets containing data that dies when the stack is un-wound
* must convert the bucket into a heap bucket.
* @param e The bucket to convert
* @deffunc apr_status_t setaside(ap_bucket *e)
*/
apr_status_t (*setaside)(ap_bucket *e);
/** Split one bucket in two at the specified position
* @param e The bucket to split
* @param point The offset of the first byte in the new bucket
* @deffunc apr_status_t split(ap_bucket *e, apr_off_t point)
*/
apr_status_t (*split)(ap_bucket *e, apr_off_t point);
};
/**
* ap_bucket_t structures are allocated on the malloc() heap and
* their lifetime is controlled by the parent ap_bucket_brigade
* structure. Buckets can move from one brigade to another e.g. by
* calling ap_brigade_concat(). In general the data in a bucket has
* the same lifetime as the bucket and is freed when the bucket is
* destroyed; if the data is shared by more than one bucket (e.g.
* after a split) the data is freed when the last bucket goes away.
*/
struct ap_bucket {
/** Links to the rest of the brigade */
AP_RING_ENTRY(ap_bucket) link;
/** The type of bucket. */
const ap_bucket_type *type;
/** The length of the data in the bucket. This could have been implemented
* with a function, but this is an optimization, because the most
* common thing to do will be to get the length. If the length is unknown,
* the value of this field will be -1.
*/
apr_off_t length;
/** type-dependent data hangs off this pointer */
void *data;
};
/** A list of buckets */
struct ap_bucket_brigade {
/** The pool to associate the brigade with. The data is not allocated out
* of the pool, but a cleanup is registered with this pool. If the
* brigade is destroyed by some mechanism other than pool destruction,
* the destroying function is responsible for killing the cleanup.
*/
apr_pool_t *p;
/** The buckets in the brigade are on this list. */
/*
* XXX: the ap_bucket_list structure doesn't actually need a name tag
* because it has no existence independent of struct ap_bucket_brigade;
* the ring macros are designed so that you can leave the name tag
* argument empty in this situation but apparently the Windows compiler
* doesn't like that.
*/
AP_RING_HEAD(ap_bucket_list, ap_bucket) list;
};
/**
* Wrappers around the RING macros to reduce the verbosity of the code
* that handles bucket brigades.
*/
#define AP_BRIGADE_SENTINEL(b) AP_RING_SENTINEL(&(b)->list, ap_bucket, link)
#define AP_BRIGADE_EMPTY(b) AP_RING_EMPTY(&(b)->list, ap_bucket, link)
#define AP_BRIGADE_FIRST(b) AP_RING_FIRST(&(b)->list)
#define AP_BRIGADE_LAST(b) AP_RING_LAST(&(b)->list)
#define AP_BRIGADE_FOREACH(e, b) \
AP_RING_FOREACH((e), &(b)->list, ap_bucket, link)
#define AP_BRIGADE_INSERT_HEAD(b, e) \
AP_RING_INSERT_HEAD(&(b)->list, (e), ap_bucket, link)
#define AP_BRIGADE_INSERT_TAIL(b, e) \
AP_RING_INSERT_TAIL(&(b)->list, (e), ap_bucket, link)
#define AP_BRIGADE_CONCAT(a, b) \
AP_RING_CONCAT(&(a)->list, &(b)->list, ap_bucket, link)
#define AP_BUCKET_INSERT_BEFORE(a, b) \
AP_RING_INSERT_BEFORE((a), (b), link)
#define AP_BUCKET_INSERT_AFTER(a, b) \
AP_RING_INSERT_AFTER((a), (b), link)
#define AP_BUCKET_NEXT(e) AP_RING_NEXT((e), link)
#define AP_BUCKET_PREV(e) AP_RING_PREV((e), link)
#define AP_BUCKET_REMOVE(e) AP_RING_REMOVE((e), link)
#define AP_BUCKET_IS_FLUSH(e) (e->type == &ap_flush_type)
#define AP_BUCKET_IS_EOS(e) (e->type == &ap_eos_type)
#define AP_BUCKET_IS_FILE(e) (e->type == &ap_file_type)
#define AP_BUCKET_IS_PIPE(e) (e->type == &ap_pipe_type)
#define AP_BUCKET_IS_SOCKET(e) (e->type == &ap_socket_type)
#define AP_BUCKET_IS_HEAP(e) (e->type == &ap_heap_type)
#define AP_BUCKET_IS_TRANSIENT(e) (e->type == &ap_transient_type)
#define AP_BUCKET_IS_IMMORTAL(e) (e->type == &ap_immortal_type)
#define AP_BUCKET_IS_MMAP(e) (e->type == &ap_mmap_type)
#define AP_BUCKET_IS_POOL(e) (e->type == &ap_pool_type)
/**
* General-purpose reference counting for the varous bucket types.
*
* Any bucket type that keeps track of the resources it uses (i.e.
* most of them except for IMMORTAL, TRANSIENT, and EOS) needs to
* attach a reference count to the resource so that it can be freed
* when the last bucket that uses it goes away. Resource-sharing may
* occur because of bucket splits or buckets that refer to globally
* cached data. */
/**
* The structure used to manage the shared resource must start with an
* ap_bucket_refcount which is updated by the general-purpose refcount
* code. A pointer to the bucket-type-dependent private data structure
* can be cast to a pointer to an ap_bucket_refcount and vice versa.
*/
typedef struct ap_bucket_refcount ap_bucket_refcount;
struct ap_bucket_refcount {
int refcount;
};
/**
* The data pointer of a refcounted bucket points to an
* ap_bucket_shared structure which describes the region of the shared
* object that this bucket refers to. The ap_bucket_shared isn't a
* fully-fledged bucket type: it is a utility type that proper bucket
* types are based on.
*/
typedef struct ap_bucket_shared ap_bucket_shared;
struct ap_bucket_shared {
/** start of the data in the bucket relative to the private base pointer */
apr_off_t start;
/** end of the data in the bucket relative to the private base pointer */
apr_off_t end;
/** pointer to the real private data of the bucket,
* which starts with an ap_bucket_refcount */
void *data;
};
/* ***** Non-reference-counted bucket types ***** */
typedef struct ap_bucket_simple ap_bucket_simple;
/**
* TRANSIENT and IMMORTAL buckets don't have much to do with looking
* after the memory that they refer to so they share a lot of their
* implementation.
*/
struct ap_bucket_simple {
/** The start of the data in the bucket */
const char *start;
/** The end of the data in the bucket */
const char *end;
};
typedef struct ap_bucket_pool ap_bucket_pool;
/**
* A bucket referring to data allocated out of a pool
*/
struct ap_bucket_pool {
/** Number of buckets using this memory */
ap_bucket_refcount refcount;
/** The start of the data actually allocated. This should never be
* modified, it is only used to free the bucket.
*/
const char *base;
/** The pool the data was allocated out of */
apr_pool_t *p;
/** This is a hack, because we call ap_destroy_bucket with the ->data
* pointer, so the pool cleanup needs to be registered with that pointer,
* but the whole point of the cleanup is to convert the bucket to another
* type. To do that conversion, we need a pointer to the bucket itself.
* This gives us a pointer to the original bucket.
*/
ap_bucket *b;
};
/* ***** Reference-counted bucket types ***** */
typedef struct ap_bucket_heap ap_bucket_heap;
/**
* A bucket referring to data allocated off the heap.
*/
struct ap_bucket_heap {
/** Number of buckets using this memory */
ap_bucket_refcount refcount;
/** The start of the data actually allocated. This should never be
* modified, it is only used to free the bucket.
*/
char *base;
/** how much memory was allocated. This may not be necessary */
size_t alloc_len;
};
typedef struct ap_bucket_mmap ap_bucket_mmap;
/**
* A bucket referring to an mmap()ed file
*/
struct ap_bucket_mmap {
/** Number of buckets using this memory */
ap_bucket_refcount refcount;
/** The mmap this sub_bucket refers to */
apr_mmap_t *mmap;
};
typedef struct ap_bucket_file ap_bucket_file;
/**
* A bucket referring to an file
*/
struct ap_bucket_file {
/** The file this bucket refers to */
apr_file_t *fd;
/** The offset into the file */
apr_off_t offset;
};
/* ***** Bucket Brigade Functions ***** */
/**
* Create a new bucket brigade. The bucket brigade is originally empty.
* @param The pool to associate with the brigade. Data is not allocated out
* of the pool, but a cleanup is registered.
* @return The empty bucket brigade
* @deffunc ap_bucket_brigade *ap_brigade_create(apr_pool_t *p)
*/
AP_DECLARE(ap_bucket_brigade *) ap_brigade_create(apr_pool_t *p);
/**
* destroy an entire bucket brigade. This includes destroying all of the
* buckets within the bucket brigade's bucket list.
* @param b The bucket brigade to destroy
* @deffunc apr_status_t ap_brigade_destroy(ap_bucket_brigade *b)
*/
AP_DECLARE(apr_status_t) ap_brigade_destroy(ap_bucket_brigade *b);
/**
* Split a bucket brigade into two, such that the given bucket is the
* first in the new bucket brigade. This function is useful when a
* filter wants to pass only the initial part of a brigade to the next
* filter.
* @param b The brigade to split
* @param e The first element of the new brigade
* @return The new brigade
* @deffunc ap_bucket_brigade *ap_brigade_split(ap_bucket_brigade *b, ap_bucket *e)
*/
AP_DECLARE(ap_bucket_brigade *) ap_brigade_split(ap_bucket_brigade *b,
ap_bucket *e);
/**
* consume nbytes from beginning of b -- call ap_bucket_destroy as
* appropriate, and/or modify start on last element
* @param b The brigade to consume data from
* @param nbytes The number of bytes to consume
* @deffunc void ap_brigade_consume(ap_bucket_brigade *b, int nbytes) */
AP_DECLARE(void) ap_brigade_consume(ap_bucket_brigade *b, int nbytes);
/**
* create an iovec of the elements in a bucket_brigade... return number
* of elements used. This is useful for writing to a file or to the
* network efficiently.
* @param The bucket brigade to create the iovec out of
* @param The iovec to create
* @param The number of elements in the iovec
* @return The number of iovec elements actually filled out.
* @deffunc int ap_brigade_to_iovec(ap_bucket_brigade *b, struct iovec *vec, int nvec);
*/
AP_DECLARE(int) ap_brigade_to_iovec(ap_bucket_brigade *b,
struct iovec *vec, int nvec);
/**
* This function writes a list of strings into a bucket brigade. We just
* allocate a new heap bucket for each string.
* @param b The bucket brigade to add to
* @param va A list of strings to add
* @return The number of bytes added to the brigade
* @deffunc int ap_brigade_vputstrs(ap_bucket_brigade *b, va_list va)
*/
AP_DECLARE(int) ap_brigade_vputstrs(ap_bucket_brigade *b, va_list va);
/**
* This function writes an unspecified number of strings into a bucket brigade.
* We just allocate a new heap bucket for each string.
* @param b The bucket brigade to add to
* @param ... The strings to add
* @return The number of bytes added to the brigade
* @deffunc int ap_brigade_putstrs(ap_bucket_brigade *b, ...)
*/
AP_DECLARE_NONSTD(int) ap_brigade_putstrs(ap_bucket_brigade *b, ...);
/**
* Evaluate a printf and put the resulting string into a bucket at the end
* of the bucket brigade.
* @param b The brigade to write to
* @param fmt The format of the string to write
* @param ... The arguments to fill out the format
* @return The number of bytes added to the brigade
* @deffunc int ap_brigade_printf(ap_bucket_brigade *b, const char *fmt, ...)
*/
AP_DECLARE_NONSTD(int) ap_brigade_printf(ap_bucket_brigade *b, const char *fmt, ...);
/**
* Evaluate a printf and put the resulting string into a bucket at the end
* of the bucket brigade.
* @param b The brigade to write to
* @param fmt The format of the string to write
* @param va The arguments to fill out the format
* @return The number of bytes added to the brigade
* @deffunc int ap_brigade_vprintf(ap_bucket_brigade *b, const char *fmt, va_list va)
*/
AP_DECLARE(int) ap_brigade_vprintf(ap_bucket_brigade *b, const char *fmt, va_list va);
/* ***** Bucket Functions ***** */
/**
* Initialize the core implemented bucket types. Once this is done,
* it is possible to add new bucket types to the server
* @param p The pool to allocate the array out of.
* @deffunc void ap_init_bucket_types(apr_pool_t *p)
*/
void ap_init_bucket_types(apr_pool_t *p);
/**
* free the resources used by a bucket. If multiple buckets refer to
* the same resource it is freed when the last one goes away.
* @param e The bucket to destroy
* @deffunc void ap_bucket_destroy(ap_bucket *e)
*/
#define ap_bucket_destroy(e) \
{ \
e->type->destroy(e->data); \
free(e); \
}
/**
* read the data from the bucket
* @param e The bucket to read from
* @param str The location to store the data in
* @param len The amount of data read
* @param block Whether the read function blocks
* @deffunc apr_status_t ap_bucket_read(ap_bucket *e, const char **str, apr_size_t *len, ap_read_type block)
*/
#define ap_bucket_read(e,str,len,block) e->type->read(e, str, len, block)
/**
* Setaside data so that stack data is not destroyed on returning from
* the function
* @param e The bucket to setaside
* @deffunc apr_status_t ap_bucket_setaside(ap_bucket *e)
*/
#define ap_bucket_setaside(e) e->type->setaside(e)
/**
* Split one bucket in two.
* @param e The bucket to split
* @param point The location to split the bucket at
* @deffunc apr_status_t ap_bucket_split(ap_bucket *e, apr_off_t point)
*/
#define ap_bucket_split(e,point) e->type->split(e, point)
/* Bucket type handling */
AP_DECLARE_NONSTD(apr_status_t) ap_bucket_setaside_notimpl(ap_bucket *data);
AP_DECLARE_NONSTD(apr_status_t) ap_bucket_split_notimpl(ap_bucket *data,
apr_off_t point);
AP_DECLARE_NONSTD(void) ap_bucket_destroy_notimpl(void *data);
/* There is no ap_bucket_read_notimpl, because it is a required function
*/
int ap_insert_bucket_type(const ap_bucket_type *type);
/* All of the bucket types implemented by the core */
extern const ap_bucket_type ap_flush_type;
extern const ap_bucket_type ap_eos_type;
extern const ap_bucket_type ap_file_type;
extern const ap_bucket_type ap_heap_type;
extern const ap_bucket_type ap_mmap_type;
extern const ap_bucket_type ap_pool_type;
extern const ap_bucket_type ap_pipe_type;
extern const ap_bucket_type ap_immortal_type;
extern const ap_bucket_type ap_transient_type;
extern const ap_bucket_type ap_socket_type;
/* ***** Shared reference-counted buckets ***** */
/**
* Initialize a bucket containing reference-counted data that may be
* shared. The caller must allocate the bucket if necessary and
* initialize its type-dependent fields, and allocate and initialize
* its own private data structure. This function should only be called
* by type-specific bucket creation functions.
* @param b The bucket to initialize,
* or NULL if a new one should be allocated
* @param data A pointer to the private data structure
* with the reference count at the start
* @param start The start of the data in the bucket
* relative to the private base pointer
* @param end The end of the data in the bucket
* relative to the private base pointer
* @return The new bucket, or NULL if allocation failed
* @deffunc AP_DECLARE(ap_bucket *) ap_bucket_shared_create(ap_bucket_refcount *r, apr_off_t start, apr_off_t end) */
AP_DECLARE(ap_bucket *) ap_bucket_make_shared(ap_bucket *b, void *data,
apr_off_t start, apr_off_t end);
/**
* Decrement the refcount of the data in the bucket and free the
* ap_bucket_shared structure. This function should only be called by
* type-specific bucket destruction functions.
* @param data The private data pointer from the bucket to be destroyed
* @return NULL if nothing needs to be done,
* otherwise a pointer to the private data structure which
* must be destroyed because its reference count is zero
* @deffunc AP_DECLARE(void *) ap_bucket_shared_destroy(ap_bucket *b) */
AP_DECLARE(void *) ap_bucket_destroy_shared(void *data);
/**
* Split a bucket into two at the given point, and adjust the refcount
* to the underlying data. Most reference-counting bucket types will
* be able to use this function as their split function without any
* additional type-specific handling.
* @param b The bucket to be split
* @param point The offset of the first byte in the new bucket
* @return APR_EINVAL if the point is not within the bucket;
* APR_ENOMEM if allocation failed;
* or APR_SUCCESS
* @deffunc AP_DECLARE(apr_status_t) ap_bucket_shared_split(ap_bucket *b, apr_off_t point)
*/
AP_DECLARE_NONSTD(apr_status_t) ap_bucket_split_shared(ap_bucket *b, apr_off_t point);
/* ***** Functions to Create Buckets of varying type ***** */
/**
* Each bucket type foo has two initialization functions:
* ap_bucket_make_foo which sets up some already-allocated memory as a
* bucket of type foo; and ap_bucket_create_foo which allocates memory
* for the bucket, calls ap_bucket_make_foo, and initializes the
* bucket's list pointers. The ap_bucket_make_foo functions are used
* inside the bucket code to change the type of buckets in place;
* other code should call ap_bucket_create_foo. All the initialization
* functions change nothing if they fail.
*/
/*
* This macro implements the guts of ap_bucket_create_foo
*/
#define ap_bucket_do_create(do_make) \
do { \
ap_bucket *b, *ap__b; \
b = calloc(1, sizeof(*b)); \
if (b == NULL) { \
return NULL; \
} \
ap__b = do_make; \
if (ap__b == NULL) { \
free(b); \
return NULL; \
} \
AP_RING_ELEM_INIT(ap__b, link); \
return ap__b; \
} while(0)
/**
* Create an End of Stream bucket. This indicates that there is no more data
* coming from down the filter stack. All filters should flush at this point.
* @return The new bucket, or NULL if allocation failed
* @deffunc ap_bucket *ap_bucket_create_eos(void)
*/
AP_DECLARE(ap_bucket *) ap_bucket_create_eos(void);
AP_DECLARE(ap_bucket *) ap_bucket_make_eos(ap_bucket *b);
/**
* Create a flush bucket. This indicates that filters should flush their
* data. There is no guarantee that they will flush it, but this is the
* best we can do.
* @return The new bucket, or NULL if allocation failed
* @deffunc ap_bucket *ap_bucket_create_flush(void)
*/
AP_DECLARE(ap_bucket *) ap_bucket_create_flush(void);
AP_DECLARE(ap_bucket *) ap_bucket_make_flush(ap_bucket *b);
/**
* Create a bucket referring to long-lived data.
* @param buf The data to insert into the bucket
* @param nbyte The size of the data to insert.
* @return The new bucket, or NULL if allocation failed
* @deffunc ap_bucket *ap_bucket_create_transient(const char *buf, apr_size_t nbyte, apr_size_t *w)
*/
AP_DECLARE(ap_bucket *) ap_bucket_create_immortal(
const char *buf, apr_size_t nbyte);
AP_DECLARE(ap_bucket *) ap_bucket_make_immortal(ap_bucket *b,
const char *buf, apr_size_t nbyte);
/**
* Create a bucket referring to data on the stack.
* @param buf The data to insert into the bucket
* @param nbyte The size of the data to insert.
* @return The new bucket, or NULL if allocation failed
* @deffunc ap_bucket *ap_bucket_create_transient(const char *buf, apr_size_t nbyte, apr_size_t *w)
*/
AP_DECLARE(ap_bucket *) ap_bucket_create_transient(
const char *buf, apr_size_t nbyte);
AP_DECLARE(ap_bucket *) ap_bucket_make_transient(ap_bucket *b,
const char *buf, apr_size_t nbyte);
/**
* Create a bucket referring to memory on the heap. If the caller asks
* for the data to be copied, this function always allocates 4K of
* memory so that more data can be added to the bucket without
* requiring another allocation. Therefore not all the data may be put
* into the bucket. If copying is not requested then the bucket takes
* over responsibility for free()ing the memory.
* @param buf The buffer to insert into the bucket
* @param nbyte The size of the buffer to insert.
* @param copy Whether to copy the data into newly-allocated memory or not
* @param w The number of bytes actually copied into the bucket.
* If copy is zero then this return value can be ignored by passing a NULL pointer.
* @return The new bucket, or NULL if allocation failed
* @deffunc ap_bucket *ap_bucket_create_heap(const char *buf, apr_size_t nbyte, int copy, apr_size_t *w)
*/
AP_DECLARE(ap_bucket *) ap_bucket_create_heap(
const char *buf, apr_size_t nbyte, int copy, apr_size_t *w);
AP_DECLARE(ap_bucket *) ap_bucket_make_heap(ap_bucket *b,
const char *buf, apr_size_t nbyte, int copy, apr_size_t *w);
/**
* Create a bucket referring to memory allocated out of a pool.
* @param buf The buffer to insert into the bucket
* @param p The pool the memory was allocated out of
* @return The new bucket, or NULL if allocation failed
* @deffunc ap_bucket *ap_bucket_create_pool(const char *buf, apr_size_t *length, apr_pool_t *p)
*/
AP_DECLARE(ap_bucket *) ap_bucket_create_pool(const char *buf,
apr_size_t length, apr_pool_t *p);
AP_DECLARE(ap_bucket *) ap_bucket_make_pool(ap_bucket *b,
const char *buf, apr_size_t length, apr_pool_t *p);
/**
* Create a bucket referring to mmap()ed memory.
* @param mmap The mmap to insert into the bucket
* @param start The offset of the first byte in the mmap
* that this bucket refers to
* @param length The number of bytes referred to by this bucket
* @return The new bucket, or NULL if allocation failed
* @deffunc ap_bucket *ap_bucket_create_mmap(const apr_mmap_t *buf, apr_size_t nbyte, apr_size_t *w)
*/
AP_DECLARE(ap_bucket *) ap_bucket_create_mmap(
apr_mmap_t *mm, apr_off_t start, apr_size_t length);
AP_DECLARE(ap_bucket *) ap_bucket_make_mmap(ap_bucket *b,
apr_mmap_t *mm, apr_off_t start, apr_size_t length);
/**
* Create a bucket referring to a socket.
* @param thissocket The socket to put in the bucket
* @return The new bucket, or NULL if allocation failed
* @deffunc ap_bucket *ap_bucket_create_socket(apr_socket_t *thissocket)
*/
AP_DECLARE(ap_bucket *) ap_bucket_create_socket(apr_socket_t *thissock);
AP_DECLARE(ap_bucket *) ap_bucket_make_socket(ap_bucket *b, apr_socket_t *thissock);
/**
* Create a bucket referring to a pipe.
* @param thispipe The pipe to put in the bucket
* @return The new bucket, or NULL if allocation failed
* @deffunc ap_bucket *ap_bucket_create_pipe(apr_file_t *thispipe)
*/
AP_DECLARE(ap_bucket *) ap_bucket_create_pipe(apr_file_t *thispipe);
AP_DECLARE(ap_bucket *) ap_bucket_make_pipe(ap_bucket *b, apr_file_t *thispipe);
/**
* Create a bucket referring to a file.
* @param fd The file to put in the bucket
* @param offset The offset where the data of interest begins in the file
* @param len The amount of data in the file we are interested in
* @return The new bucket, or NULL if allocation failed
* @deffunc ap_bucket *ap_bucket_create_file(apr_file_t *thispipe)
*/
AP_DECLARE(ap_bucket *) ap_bucket_create_file(apr_file_t *fd, apr_off_t offset, apr_size_t len);
AP_DECLARE(ap_bucket *) ap_bucket_make_file(ap_bucket *b, apr_file_t *fd,
apr_off_t offset, apr_size_t len);
#endif /* !AP_BUCKETS_H */