blob: 530178eea6b900ab74145534cc77a082ddd6cae7 [file] [log] [blame]
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 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.
* ====================================================================
*
*/
#ifndef SERF_H
#define SERF_H
/**
* @file serf.h
* @brief Main serf header file
*/
#include <apr.h>
#include <apr_errno.h>
#include <apr_allocator.h>
#include <apr_pools.h>
#include <apr_network_io.h>
#include <apr_time.h>
#include "serf_declare.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Forward declare some structures */
typedef struct serf_context_t serf_context_t;
typedef struct serf_bucket_t serf_bucket_t;
typedef struct serf_bucket_type_t serf_bucket_type_t;
typedef struct serf_bucket_alloc_t serf_bucket_alloc_t;
typedef struct serf_metadata_t serf_metadata_t;
typedef struct serf_connection_t serf_connection_t;
typedef struct serf_request_t serf_request_t;
/**
* @defgroup serf high-level constructs
* @ingroup serf
* @{
*/
/**
* Create a new context for serf operations.
*
* A serf context defines a control loop which processes multiple
* connections simultaneously.
*
* The context will be allocated within @a pool.
*/
SERF_DECLARE(serf_context_t *) serf_context_create(apr_pool_t *pool);
/** @see serf_context_run should not block at all. */
#define SERF_DURATION_NOBLOCK 0
/** @see serf_context_run should run for (nearly) "forever". */
#define SERF_DURATION_FOREVER 2000000000 /* approx 1^31 */
/**
* Run the main networking control loop.
*
* The set of connections defined by the serf context @a ctx are processed.
* Any outbound data is delivered, and incoming data is made available to
* the associated response handlers and their buckets. This function will
* block on the network for no longer than @a duration microseconds.
*
* If any data is processed (incoming or outgoing), then this function will
* return with APR_SUCCESS. Typically, the caller will just want to call it
* again to continue processing data.
*
* If no activity occurs within the specified timeout duration, then
* APR_TIMEUP is returned.
*
* All temporary allocations will be made in @a pool.
*/
SERF_DECLARE(apr_status_t) serf_context_run(serf_context_t *ctx,
apr_short_interval_time_t duration,
apr_pool_t *pool);
/** @} */
/**
* @defgroup serf connections and requests
* @ingroup serf
* @{
*/
/**
* Accept an incoming response for @a request, and its @a socket. A bucket
* for the response will be constructed and returned. This is the control
* point for assembling the appropriate wrapper buckets around the socket to
* enable processing of the incoming response.
*
* The @a acceptor_baton is the baton provided when the connection was
* first opened.
*
* The request's pool and bucket allocator should be used for any allocations
* that need to live for the duration of the response. Care should be taken
* to bound the amount of memory stored in this pool -- to ensure that
* allocations are not proportional to the amount of data in the response.
*
* Responsibility for the bucket is passed to the serf library. It will be
* destroyed when the response has been fully read (the bucket returns an
* APR_EOF status from its read functions).
*
* All temporary allocations should be made in @a pool.
*/
/* ### do we need to return an error? */
typedef serf_bucket_t * (*serf_response_acceptor_t)(serf_request_t *request,
apr_socket_t *skt,
void *acceptor_baton,
apr_pool_t *pool);
/**
* Notification callback for when a connection closes.
*
* This callback is used to inform an application that the @a conn
* connection has been (abnormally) closed. The @a closed_baton is the
* baton provided when the connection was first opened. The reason for
* closure is given in @a why, and will be APR_SUCCESS if the application
* requested closure (by clearing the pool used to allocate this
* connection).
*
* All temporary allocations should be made in @a pool.
*/
typedef void (*serf_connection_closed_t)(serf_connection_t *conn,
void *closed_baton,
apr_status_t why,
apr_pool_t *pool);
/**
* Response data has arrived and should be processed.
*
* Whenever a response arrives (initially, or continued data arrival), this
* handler is invoked. The response data is available in the @a response
* bucket. The @a handler_baton is passed along from the baton provided to
* the creation of this response's associated request.
*
* The handler MUST process data from the @a response bucket until the
* bucket's read function states it would block (see APR_STATUS_IS_EAGAIN).
* The handler is invoked only when new data arrives. If no further data
* arrives, and the handler does not process all available data, then the
* system can result in a deadlock around the unprocessed, but read, data.
*
* The handler should return APR_EOF when the response has been fully read.
* APR_EAGAIN should not be returned; simply return APR_SUCCESS.
*
* Note: if the connection closed (at the request of the application, or
* because of an (abnormal) termination) while a request is being delivered,
* or before a response arrives, then @a response will be NULL. This is the
* signal that the request was not delivered properly, and no further
* response should be expected (this callback will not be invoked again).
* If a request is injected into the connection (during this callback, or
* otherwise), then the connection will be reopened.
*
* All temporary allocations should be made in @a pool.
*/
typedef apr_status_t (*serf_response_handler_t)(serf_bucket_t *response,
void *handler_baton,
apr_pool_t *pool);
/**
* Create a new connection associated with the @a ctx serf context.
*
* A connection will be created to (eventually) connect to the address
* specified by @a address. The address must live at least as long as
* @a pool (thus, as long as the connection object).
*
* The connection object will be allocated within @a pool. Clearing or
* destroying this pool will close the connection, and terminate any
* outstanding requests or responses.
*
* When the connection is closed (upon request or because of an error),
* then the @a closed callback is invoked, and @a closed_baton is passed.
*
* NULL may be passed for @a acceptor and @a closed; default implementations
* will be used.
*
* Note: the connection is not made immediately. It will be opened on
* the next call to @see serf_context_run.
*/
SERF_DECLARE(serf_connection_t *) serf_connection_create(
serf_context_t *ctx,
apr_sockaddr_t *address,
serf_connection_closed_t closed,
void *closed_baton,
apr_pool_t *pool);
/**
* Construct a request object for the @a conn connection.
*
* A subpool for the request and its associated response will be built,
* and the request will be allocated within that subpool. An associated
* bucket allocator will be built. These items may be fetched from the
* request object through @see serf_request_get_pool or
* @see serf_request_get_alloc.
*
* The returned request can be finalized with @see ....
*
* If the request has not (yet) been delivered, then it may be canceled
* with @see serf_connection_request_cancel.
*/
SERF_DECLARE(serf_request_t *) serf_connection_request_create(
serf_connection_t *conn);
/**
* Schedule the @a request for delivery on the connection.
*
* The content of the request is specified by the @a req_bkt bucket. When
* a response arrives, the @a acceptor callback will be invoked (along with
* the @a acceptor_baton) to produce a response bucket. That bucket will then
* be passed to @a handler, along with the @a handler_baton.
*
* The responsibility for the request bucket is passed to the request
* object. When the request is done with the bucket, it will be destroyed.
*/
SERF_DECLARE(void) serf_request_deliver(
serf_request_t *request,
serf_bucket_t *req_bkt,
serf_response_acceptor_t acceptor,
void *acceptor_baton,
serf_response_handler_t handler,
void *handler_baton);
/**
* Cancel the request specified by the @a request object.
*
* If the request has been scheduled for delivery, then its response
* handler will be run, passing NULL for the response bucket.
*
* If the request has already been (partially or fully) delivered, then
* APR_EBUSY is returned and the request is *NOT* canceled. To properly
* cancel the request, the connection must be closed (by clearing or
* destroying its associated pool).
*/
SERF_DECLARE(apr_status_t) serf_request_cancel(serf_request_t *request);
/**
* Return the pool associated with @a request.
*
* WARNING: be very careful about the kinds of things placed into this
* pool. In particular, all allocation should be bounded in size, rather
* than proportional to any data stream.
*/
SERF_DECLARE(apr_pool_t *) serf_request_get_pool(
const serf_request_t *request);
/**
* Return the bucket allocator associated with @a request.
*/
SERF_DECLARE(serf_bucket_alloc_t *) serf_request_get_alloc(
const serf_request_t *request);
/* ### maybe some connection control functions for flood? */
/** @} */
/**
* @defgroup serf buckets
* @ingroup serf
* @{
*/
/** Pass as REQUESTED to the read function of a bucket to read, consume,
* and return all available data.
*/
#define SERF_READ_ALL_AVAIL ((apr_size_t)-1)
/** Acceptable newline types for bucket->readline(). */
#define SERF_NEWLINE_CR 0x0001
#define SERF_NEWLINE_CRLF 0x0002
#define SERF_NEWLINE_LF 0x0004
#define SERF_NEWLINE_ANY 0x0007
/** Used to indicate that a newline is not present in the data buffer. */
/* ### should we make this zero? */
#define SERF_NEWLINE_NONE 0x0008
/** Used to indicate that a CR was found at the end of a buffer, and CRLF
* was acceptable. It may be that the LF is present, but it needs to be
* read first.
*
* Note: an alternative to using this symbol would be for callers to see
* the SERF_NEWLINE_CR return value, and know that some "end of buffer" was
* reached. While this works well for @see serf_util_readline, it does not
* necessary work as well for buckets (there is no obvious "end of buffer",
* although there is an "end of bucket"). The other problem with that
* alternative is that developers might miss the condition. This symbol
* calls out the possibility and ensures that callers will watch for it.
*/
#define SERF_NEWLINE_CRLF_SPLIT 0x0010
struct serf_bucket_type_t {
/** name of this bucket type */
const char *name;
/**
* Read (and consume) up to @a requested bytes from @a bucket.
*
* A pointer to the data will be returned in @a data, and its length
* is specified by @a len.
*
* The data will exist until one of two conditions occur:
*
* 1) this bucket is destroyed
* 2) another call to any read function or to peek()
*
* If an application needs the data to exist for a longer duration,
* then it must make a copy.
*/
apr_status_t (*read)(serf_bucket_t *bucket, apr_size_t requested,
const char **data, apr_size_t *len);
/**
* Read (and consume) a line of data from @a bucket.
*
* The acceptable forms of a newline are given by @a acceptable, and
* the type found is returned in @a found. If a newline is not present
* in the returned data, then SERF_NEWLINE_NONE is stored into @a found.
*
* A pointer to the data is returned in @a data, and its length is
* specified by @a len. The data will include the newline, if present.
*
* Note that there is no way to limit the amount of data returned
* by this function.
*
* The lifetime of the data is the same as that of the @see read
* function above.
*/
apr_status_t (*readline)(serf_bucket_t *bucket, int acceptable,
int *found,
const char **data, apr_size_t *len);
/**
* Read a set of pointer/length pairs from the bucket.
*
* The size of the @a vecs array is specified by @a vecs_size. The
* bucket should fill in elements of the array, and return the number
* used in @a vecs_used.
*
* Each element of @a vecs should specify a pointer to a block of
* data and a length of that data.
*
* The total length of all data elements should not exceed the
* amount specified in @a requested.
*
* The lifetime of the data is the same as that of the @see read
* function above.
*/
apr_status_t (*read_iovec)(serf_bucket_t *bucket, apr_size_t requested,
int vecs_size, struct iovec *vecs,
int *vecs_used);
/**
* Read data from the bucket in a form suitable for apr_socket_sendfile()
*
* On input, hdtr->numheaders and hdtr->numtrailers specify the size
* of the hdtr->headers and hdtr->trailers arrays, respectively. The
* bucket should fill in the headers and trailers, up to the specified
* limits, and set numheaders and numtrailers to the number of iovecs
* filled in for each item.
*
* @a file should be filled in with a file that can be read. If a file
* is not available or appropriate, then NULL should be stored. The
* file offset for the data should be stored in @a offset, and the
* length of that data should be stored in @a len. If a file is not
* returned, then @a offset and @a len should be ignored.
*
* The file position is not required to correspond to @a offset, and
* the caller may manipulate it at will.
*
* The total length of all data elements, and the portion of the
* file should not exceed the amount specified in @a requested.
*
* The lifetime of the data is the same as that of the @see read
* function above.
*/
apr_status_t (*read_for_sendfile)(serf_bucket_t *bucket,
apr_size_t requested, apr_hdtr_t *hdtr,
apr_file_t **file, apr_off_t *offset,
apr_size_t *len);
/**
* Look within @a bucket for a bucket of the given @a type. The bucket
* must be the "initial" data because it will be consumed by this
* function. If the given bucket type is available, then read and consume
* it, and return it to the caller.
*
* This function is usually used by readers that have custom handling
* for specific bucket types (e.g. looking for a file bucket to pass
* to apr_socket_sendfile).
*
* If a bucket of the given type is not found, then NULL is returned.
*
* The returned bucket becomes the responsibility of the caller. When
* the caller is done with the bucket, it should be destroyed.
*/
serf_bucket_t * (*read_bucket)(serf_bucket_t *bucket,
const serf_bucket_type_t *type);
/**
* Peek, but don't consume, the data in @a bucket.
*
* Since this function is non-destructive, the implicit read size is
* SERF_READ_ALL_AVAIL. The caller can then use whatever amount is
* appropriate.
*
* The @a data parameter will point to the data, and @a len will
* specify how much data is available. The lifetime of the data follows
* the same rules as the @see read function above.
*
* Note: if the peek does not return enough data for your particular
* use, then you must read/consume some first, then peek again.
*
* If the returned data represents all available data, then APR_EOF
* will be returned. Since this function does not consume data, it
* can return the same data repeatedly rather than blocking; thus,
* APR_EAGAIN will never be returned.
*/
apr_status_t (*peek)(serf_bucket_t *bucket,
const char **data, apr_size_t *len);
/**
* Look up and return a piece of metadata from @a bucket.
*
* The metadata is specified by the metadata type @a md_type and the
* metadata name @a md_name. The value is returned in @a md_value, or
* NULL if the specified metadata does not exist in this bucket.
*
* Note that this function may return APR_EAGAIN if the metadata is
* not (yet) available. Other (networking) errors may be returned, too.
*/
apr_status_t (*get_metadata)(serf_bucket_t *bucket, const char *md_type,
const char *md_name, const void **md_value);
/**
* Set some metadata for @a bucket.
*
* The metadata is specified by the metadata type @a md_type and the
* metadata name @a md_name. The value is given by @a md_value, or
* NULL if the specified metadata should be deleted.
*
* Note that this function may return errors if the metadata cannot
* be set for some reason.
*/
apr_status_t (*set_metadata)(serf_bucket_t *bucket, const char *md_type,
const char *md_name, const void *md_value);
/**
* Destroy @a bucket, along with any associated resources.
*/
void (*destroy)(serf_bucket_t *bucket);
/* ### apr buckets have 'copy', 'split', and 'setaside' functions.
### not sure whether those will be needed in this bucket model.
*/
};
#define serf_bucket_read(b,r,d,l) ((b)->type->read(b,r,d,l))
#define serf_bucket_readline(b,a,f,d,l) ((b)->type->readline(b,a,f,d,l))
#define serf_bucket_read_iovec(b,r,s,v,u) ((b)->type->read_iovec(b,r,s,v,u))
#define serf_bucket_read_for_sendfile(b,r,h,f,o,l) \
((b)->type->read_for_sendfile(b,r,h,f,o,l))
#define serf_bucket_read_bucket(b,t) ((b)->type->read_bucket(b,t))
#define serf_bucket_peek(b,d,l) ((b)->type->peek(b,d,l))
#define serf_bucket_get_metadata(b,t,n,v) ((b)->type->get_metadata(b,t,n,v))
#define serf_bucket_set_metadata(b,t,n,v) ((b)->type->set_metadata(b,t,n,v))
#define serf_bucket_destroy(b) ((b)->type->destroy(b))
struct serf_bucket_t {
/** the type of this bucket */
const serf_bucket_type_t *type;
/** bucket-private data */
void *data;
/** this bucket's metadata: (TYPE, NAME) -> VALUE */
serf_metadata_t *metadata;
/** the allocator used for this bucket (needed at destroy time) */
serf_bucket_alloc_t *allocator;
};
/**
* Generic macro to construct "is TYPE" macros.
*/
#define SERF_BUCKET_CHECK(b, btype) ((b)->type == &serf_bucket_type_ ## btype)
/**
* Notification callback for a block that was not returned to the bucket
* allocator when its pool was destroyed.
*
* The block of memory is given by @a block. The baton provided when the
* allocator was constructed is passed as @a unfreed_baton.
*/
typedef void (*serf_unfreed_func_t)(void *unfreed_baton, void *block);
/**
* Create a new allocator for buckets.
*
* All buckets are associated with a serf bucket allocator. This allocator
* will be created within @a pool and will be destroyed when that pool is
* cleared or destroyed.
*
* When the allocator is destroyed, if any allocations were not explicitly
* returned (by calling serf_bucket_mem_free), then the @a unfreed callback
* will be invoked for each block. @a unfreed_baton will be passed to the
* callback.
*
* If @a unfreed is NULL, then the library will invoke the abort() stdlib
* call. Any failure to return memory is a bug in the application, and an
* abort can assist with determining what kinds of memory were not freed.
*/
SERF_DECLARE(serf_bucket_alloc_t *) serf_bucket_allocator_create(
apr_pool_t *pool,
serf_unfreed_func_t unfreed,
void *unfreed_baton);
/**
* Return the pool that was used for this @a allcoator.
*
* WARNING: the use of this pool for allocations requires a very
* detailed understanding of pool behaviors, the bucket system,
* and knowledge of the bucket's use within the overall pattern
* of request/response behavior.
*
* See design-guide.txt for more information about pool usage.
*/
SERF_DECLARE(apr_pool_t *) serf_bucket_allocator_get_pool(
const serf_bucket_alloc_t *allocator);
/** @} */
#ifdef __cplusplus
}
#endif
/*
* Every user of serf will want to deal with our various bucket types.
* Go ahead and include that header right now.
*
* Note: make sure this occurs outside of the C++ namespace block
*/
#include "serf_bucket_types.h"
#endif /* !SERF_H */